Skip to content

Fix PATH environment handling for macOS application bundles. Fixes #941#943

Merged
KirillOsenkov merged 1 commit into
KirillOsenkov:mainfrom
snechaev:macos-appBundle-env-fix-941
Apr 2, 2026
Merged

Fix PATH environment handling for macOS application bundles. Fixes #941#943
KirillOsenkov merged 1 commit into
KirillOsenkov:mainfrom
snechaev:macos-appBundle-env-fix-941

Conversation

@snechaev

@snechaev snechaev commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

This pull request implements a workaround to address the issue of a restricted PATH environment in macOS app bundles. It will "steal" full PATH from the "normal" user environment and inject it to the current process, allowing CLI tools such as dotnet to be properly located. The does not affect non-macos environments and the situations when the app is runned from a terminal or from the IDE.

Fixes #941

…es. Fixes KirillOsenkov#941

Implements a solution to inherit the user's PATH variable on macOS when the app is launched outside of a terminal environment, ensuring CLI tools like `dotnet` are correctly located.
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
MacOsEnvironmentExporter.InheritUserPath();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to run the fix as earlier as possible, but still not sure that it is a correct place.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snechaev @KirillOsenkov I think I'd prefer running this only when you actually run build through the UI (we can also just modify the PATH of the ProcessStartInfo there, not of the whole binlog viewer process).

I never build through the UI and this will make startup of the app slower for everyone.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how much does this cost though?

@akoeplinger akoeplinger Apr 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not much, but seeing the process.WaitForExit() code waiting indefinitely and knowing how hard it is to not write Process code that deadlocks I'm a bit cautious :D

@snechaev snechaev Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akoeplinger The rationale behind choosing a global environment modification is primarily around maintainability and preventing future regressions:

  • We currently don't have a centralized wrapper for Process.Start. There are already multiple disconnected places that invoke dotnet. Furthermore, we expect more external process calls in the future (e.g., external diff tools, or porting the "Open binlog in VS Code with binlog MCP" feature from the Windows version). The global fix automatically covers all present and future invocations.

  • Discoverability of the bug: While setting environment variables locally for each Process.Start is arguably safer, it relies heavily on developers remembering to apply it on each new or modified Process-related code. Because this issue is highly specific - manifesting only at runtime, only on macOS, and only when launched as an app bundle - missing a local fix would be very easy to overlook and hard to catch during standard testing.

  • Scoping the fix specifically to the Build/Rebuild actions might be too narrow. As mentioned, features like opening VS Code or running diff tools will also need this corrected environment to function on macOS. We could implement a lazy initialization method to be called before every Process.Start (or, again, just to modify environment variables of the specific Process instance), but that brings us back to the risk of developers forgetting to invoke it.

Are there alternative approaches I might be missing that will allow to avoid the "global" fix and will not introduce a significant risk of the regressions and broken new functionality?

@KirillOsenkov, I took some measurements and found that executing InheritUserPath() takes around 45-50ms on my not so fast 3-year-old mac mini.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I didn't know there are multiple places where we invoke dotnet. let's just wait and see whether this actually causes issues :)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can live with 50ms, thanks for measuring :)

}
catch
{
//ignore

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skipping any errors here (and also there is a early return if a the process was null). We have no UI at this stage so we can't provide user with any diagnostics. But ignoring errors may be fragile. So, is it a better way to handle this? May be logs, asserts (for debug time), etc?

@KirillOsenkov
KirillOsenkov merged commit e98b9b8 into KirillOsenkov:main Apr 2, 2026
1 check passed
@snechaev
snechaev deleted the macos-appBundle-env-fix-941 branch April 2, 2026 17:52
tknightnd pushed a commit to NewDayTechnology/benchmarkdotnet.analyser that referenced this pull request Jul 22, 2026
Updated
[Microsoft.Extensions.DependencyInjection](https://github.com/dotnet/dotnet)
from 10.0.9 to 10.0.10.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.Extensions.DependencyInjection's
releases](https://github.com/dotnet/dotnet/releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/dotnet/dotnet/commits).
</details>

Updated [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest)
from 18.7.0 to 18.8.1.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.NET.Test.Sdk's
releases](https://github.com/microsoft/vstest/releases)._

## 18.8.1

## What's Changed
* Fix protocol negotiation timeout when STJ reflection is disabled
(18.8.1) by @​nohwnd in microsoft/vstest#16281


**Full Changelog**:
microsoft/vstest@v18.8.0...v18.8.1

## 18.8.0

## What's Changed
* Migrate from Newtonsoft.Json to System.Text.Json / Jsonite (merge to
main) by @​nohwnd in microsoft/vstest#15687
- For more detail refer to
https://devblogs.microsoft.com/dotnet/vs-test-is-removing-its-newtonsoft-json-dependency/
* Create source-only filter package by @​Youssef1313 in
microsoft/vstest#15638
* Add ARM64 msdia140.dll support to test platform packages by @​nohwnd
in microsoft/vstest#15692
* Fix mutex cleanup crash on macOS/Linux by @​nohwnd in
microsoft/vstest#15684
* Restrict artifact temp directory permissions on Unix by @​nohwnd in
microsoft/vstest#15729
* Add support for filtering uncategorized tests with TestCategory=None
by @​Evangelink in microsoft/vstest#15727
* Fix SCI binding failure in DTA hosts (main) by @​nohwnd in
microsoft/vstest#15724
* Fix HTML logger parallel file collision by @​nohwnd in
microsoft/vstest#15435
* Improve error message when testhost cannot be found by @​nohwnd in
microsoft/vstest#16053
* Fix HTML logger exception on invalid XML chars in test display names
by @​nohwnd in microsoft/vstest#16051

**Full Changelog**:
microsoft/vstest@v18.7.0...v18.8.0

Commits viewable in [compare
view](microsoft/vstest@v18.7.0...v18.8.1).
</details>

Updated
[MSBuild.StructuredLogger](https://github.com/KirillOsenkov/MSBuildStructuredLog)
from 2.3.204 to 2.3.213.

<details>
<summary>Release notes</summary>

_Sourced from [MSBuild.StructuredLogger's
releases](https://github.com/KirillOsenkov/MSBuildStructuredLog/releases)._

## 2.3.213

## What's Changed
* ci: bump AppVeyor macOS image to Sonoma by @​KirillOsenkov with
@​Copilot in
KirillOsenkov/MSBuildStructuredLog#940
* Fix empty MSBuild version list when dotnet process exits early by
@​snechaev in
KirillOsenkov/MSBuildStructuredLog#942
* Fix PATH environment handling for macOS application bundles. Fixes
#​941 by @​snechaev in
KirillOsenkov/MSBuildStructuredLog#943
* [TracingView] Fix a case where fast mouse drawing cause the position
to jump unexpectedly by @​yuehuang010 in
KirillOsenkov/MSBuildStructuredLog#944
* Preserve search text during rebuild process in Avalonia version by
@​snechaev in
KirillOsenkov/MSBuildStructuredLog#946
* Bump package version and ship net10 by @​stan-sz in
KirillOsenkov/MSBuildStructuredLog#947
* Don't specify PublicKey on Mac by @​KirillOsenkov in
KirillOsenkov/MSBuildStructuredLog#948
* Avalonia 12 support by @​maxkatz6 in
KirillOsenkov/MSBuildStructuredLog#937
* [macOS] Allow to run multiple instances by @​snechaev in
KirillOsenkov/MSBuildStructuredLog#949
* Add search field to Files tab in Avalonia version by @​rolfbjarne in
KirillOsenkov/MSBuildStructuredLog#951
* Bump DotUtils SensitiveDataDetector to 1.0.0 by @​YuliiaKovalova in
KirillOsenkov/MSBuildStructuredLog#953
* Add MSBuild Server lifecycle node support (binlog format v27) by
@​JanProvaznik in
KirillOsenkov/MSBuildStructuredLog#955

## New Contributors
* @​KirillOsenkov with @​Copilot made their first contribution in
KirillOsenkov/MSBuildStructuredLog#940
* @​rolfbjarne made their first contribution in
KirillOsenkov/MSBuildStructuredLog#951

**Full Changelog**:
KirillOsenkov/MSBuildStructuredLog@v2.3.154...v2.3.213

Commits viewable in [compare
view](https://github.com/KirillOsenkov/MSBuildStructuredLog/commits/v2.3.213).
</details>

Updated [NSubstitute](https://github.com/nsubstitute/NSubstitute) from
5.3.0 to 6.0.0.

<details>
<summary>Release notes</summary>

_Sourced from [NSubstitute's
releases](https://github.com/nsubstitute/NSubstitute/releases)._

## 6.0.0

:information_source: No changes from [Release Candidate
1](https://github.com/nsubstitute/NSubstitute/releases/tag/v6.0.0-rc.1).

# NSubstitute v6.0.0 

From
[RC1](https://github.com/nsubstitute/NSubstitute/releases/tag/v6.0.0-rc.1)
notes:

* [NEW] `ArgMatchers.Matching` predicate matcher as an alternative to
`Is(Expression<Predicate<T>>`. (.NET6 and above.)
* [UPDATE] Improved support for custom argument matchers. `Arg.Is` now
accepts arg matchers.
* [UPDATE][BREAKING] Update target frameworks: .NET8, .NET Standard 2.0
* [UPDATE][BREAKING] Remove legacy obsolete API
* [UPDATE][BREAKING] Mark as obsolete api CompatArg with pre c# 7.0
support
* [UPDATE][BREAKING] Nullability is enabled for public api for .NET 8+
TFMs
* [UPDATE] Migrate documentation to [docfx
platform](https://github.com/dotnet/docfx) and update samples to NUnit 4
* [NEW] Added NuGet Package README file.


## Full change list

* Update target frameworks and other infrastructure changes by @​Romfos
in nsubstitute/NSubstitute#831
* Remove Google Groups hyperlinks by @​304NotModified in
nsubstitute/NSubstitute#804
* Improve output for expected argument matchers in
nsubstitute/NSubstitute#806
* Mark Substitute.For<T> method as Pure by @​Dzliera in
nsubstitute/NSubstitute#844
* Move package creating from build.fsproj to github actions by @​Romfos
in nsubstitute/NSubstitute#838
* Added .NET 9 to test matrix by @​Romfos in
nsubstitute/NSubstitute#848
* Update dependencies by @​Saibamen in
nsubstitute/NSubstitute#843
* Migrate documentation to docfx by @​Romfos in
nsubstitute/NSubstitute#850
* Added test for issue #​716 by @​rbeurskens in
nsubstitute/NSubstitute#846
* feat: add dependabot for this project for minor and patch updates for
nuget packages and github actions by @​wmundev in
nsubstitute/NSubstitute#792
* #​853 Fix matching with multiple generic arguments of the same type by
@​rholek in nsubstitute/NSubstitute#858
* Ability to mock protected methods with and without return value by
@​Jason31569 in nsubstitute/NSubstitute#845
* Enable nullability for public api by @​Romfos in
nsubstitute/NSubstitute#856
* Bugfix/async event handlers return instantly by @​jmartschinke in
nsubstitute/NSubstitute#808
* Fix matching generic calls with AnyType when the generic argument is
also a generic argument in return type, out or ref parameter by
@​JMolenkamp in nsubstitute/NSubstitute#862
* Feature: allow interception of any generic method call when using
Arg.AnyType by @​JMolenkamp in
nsubstitute/NSubstitute#855
* Params arg unit test by @​Jason31569 in
nsubstitute/NSubstitute#874
* Added exception extensions for ValueTask without return type (rebase)
in nsubstitute/NSubstitute#873
* Migrate to slnx by @​Romfos in
nsubstitute/NSubstitute#882
* Migrate documentation validation from build.fsproj to Roslyn code
generator by @​Romfos in
nsubstitute/NSubstitute#883
* Fix doc links (#​884) in
nsubstitute/NSubstitute#886
* Add PackageReadmeFile. by @​peymanr34 in
nsubstitute/NSubstitute#888
* Make public api and tests the same for all TFMs by @​Romfos in
nsubstitute/NSubstitute#885
* Migrate documentation samples to NUnit4 by @​Romfos in
nsubstitute/NSubstitute#889
* Run unit tests in Microsoft.Testing.Platform mode by @​Romfos in
nsubstitute/NSubstitute#896
* Bump actions/checkout from 4 to 5 by @​dependabot[bot] in
nsubstitute/NSubstitute#902
* Fix typo in return value documentation by @​ericmutta in
nsubstitute/NSubstitute#903
* Bump actions/setup-dotnet from 4 to 5 by @​dependabot[bot] in
nsubstitute/NSubstitute#907
* Fix typo in received calls documentation by @​ericmutta in
nsubstitute/NSubstitute#904
* Simplify github actions to use less jobs by @​Romfos in
nsubstitute/NSubstitute#911
* Bump actions/upload-artifact from 4 to 5 by @​dependabot[bot] in
nsubstitute/NSubstitute#916
* Bump NUnit3TestAdapter from 5.0.0 to 5.2.0 by @​dependabot[bot] in
nsubstitute/NSubstitute#922
 ... (truncated)

## 6.0.0-rc.1

# NSubstitute v6.0.0 Release Candidate 1

Due to the large number of changes in this release, we wanted to start
with a release candidate to ensure we've correctly captured breaking
changes.

* [NEW] `ArgMatchers.Matching` predicate matcher as an alternative to
`Is(Expression<Predicate<T>>`. (.NET6 and above.)
* [UPDATE] Improved support for custom argument matchers. `Arg.Is` now
accepts arg matchers.
* [UPDATE][BREAKING] Update target frameworks: .NET8, .NET Standard 2.0
* [UPDATE][BREAKING] Remove legacy obsolete API
* [UPDATE][BREAKING] Mark as obsolete api CompatArg with pre c# 7.0
support
* [UPDATE][BREAKING] Nullability is enabled for public api for .NET 8+
TFMs
* [UPDATE] Migrate documentation to [docfx
platform](https://github.com/dotnet/docfx) and update samples to NUnit 4
* [NEW] Added NuGet Package README file.


## Full change list

* Update target frameworks and other infrastructure changes by @​Romfos
in nsubstitute/NSubstitute#831
* Remove Google Groups hyperlinks by @​304NotModified in
nsubstitute/NSubstitute#804
* Improve output for expected argument matchers in
nsubstitute/NSubstitute#806
* Mark Substitute.For<T> method as Pure by @​Dzliera in
nsubstitute/NSubstitute#844
* Move package creating from build.fsproj to github actions by @​Romfos
in nsubstitute/NSubstitute#838
* Added .NET 9 to test matrix by @​Romfos in
nsubstitute/NSubstitute#848
* Update dependencies by @​Saibamen in
nsubstitute/NSubstitute#843
* Migrate documentation to docfx by @​Romfos in
nsubstitute/NSubstitute#850
* Added test for issue #​716 by @​rbeurskens in
nsubstitute/NSubstitute#846
* feat: add dependabot for this project for minor and patch updates for
nuget packages and github actions by @​wmundev in
nsubstitute/NSubstitute#792
* #​853 Fix matching with multiple generic arguments of the same type by
@​rholek in nsubstitute/NSubstitute#858
* Ability to mock protected methods with and without return value by
@​Jason31569 in nsubstitute/NSubstitute#845
* Enable nullability for public api by @​Romfos in
nsubstitute/NSubstitute#856
* Bugfix/async event handlers return instantly by @​jmartschinke in
nsubstitute/NSubstitute#808
* Fix matching generic calls with AnyType when the generic argument is
also a generic argument in return type, out or ref parameter by
@​JMolenkamp in nsubstitute/NSubstitute#862
* Feature: allow interception of any generic method call when using
Arg.AnyType by @​JMolenkamp in
nsubstitute/NSubstitute#855
* Params arg unit test by @​Jason31569 in
nsubstitute/NSubstitute#874
* Added exception extensions for ValueTask without return type (rebase)
in nsubstitute/NSubstitute#873
* Migrate to slnx by @​Romfos in
nsubstitute/NSubstitute#882
* Migrate documentation validation from build.fsproj to Roslyn code
generator by @​Romfos in
nsubstitute/NSubstitute#883
* Fix doc links (#​884) in
nsubstitute/NSubstitute#886
* Add PackageReadmeFile. by @​peymanr34 in
nsubstitute/NSubstitute#888
* Make public api and tests the same for all TFMs by @​Romfos in
nsubstitute/NSubstitute#885
* Migrate documentation samples to NUnit4 by @​Romfos in
nsubstitute/NSubstitute#889
* Run unit tests in Microsoft.Testing.Platform mode by @​Romfos in
nsubstitute/NSubstitute#896
* Bump actions/checkout from 4 to 5 by @​dependabot[bot] in
nsubstitute/NSubstitute#902
* Fix typo in return value documentation by @​ericmutta in
nsubstitute/NSubstitute#903
* Bump actions/setup-dotnet from 4 to 5 by @​dependabot[bot] in
nsubstitute/NSubstitute#907
* Fix typo in received calls documentation by @​ericmutta in
nsubstitute/NSubstitute#904
* Simplify github actions to use less jobs by @​Romfos in
nsubstitute/NSubstitute#911
* Bump actions/upload-artifact from 4 to 5 by @​dependabot[bot] in
nsubstitute/NSubstitute#916
* Bump NUnit3TestAdapter from 5.0.0 to 5.2.0 by @​dependabot[bot] in
nsubstitute/NSubstitute#922
* Bump BenchmarkDotNet from 0.15.2 to 0.15.5 by @​dependabot[bot] in
nsubstitute/NSubstitute#921
* Add .NET 10 to test matrix by @​Romfos in
nsubstitute/NSubstitute#913
 ... (truncated)

Commits viewable in [compare
view](nsubstitute/NSubstitute@v5.3.0...v6.0.0).
</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An error occurred trying to start process 'dotnet' when using the ready-to-use macOS app bundle

3 participants