TIL - shell environment variables aren't available to OS X apps

2021-11-12 3-minute read

Just recently I have been exploring a very strange issue: My application couldn’t find a tool that was right where it should be…

I’m building a C# project that relies on a library called FFMpegCore. In turn, FFMpegCore relies on ffmpeg - a complete, cross-platform solution to record, convert and stream audio and video.

I discovered, though, that when testing my code in Visual Studio I had to provide the full path to ffmpeg - even though the documentation and examples suggested that wasn’t necessary.

I dug into the code of FFMpegCore to see how it was trying to launch and use ffmpeg. It creates a process, providing parameters with ProcessStartInfo - and it explicitly sets the UseShellExecute option to false.

The documentation for UseShellExecute states that:

When UseShellExecute is false, the FileName property can be either a fully qualified path to the executable, or a simple executable name that the system will attempt to find within folders specified by the PATH environment variable.

This suggests that if ffmpeg is on the PATH, the application should be able to find it - but this wasn’t happening. I checked my PATH and it clearly contained the location where Homebrew had installed ffmpeg.

This was made more complicated by the fact that other tools, such as docker, were reliably found.

What was going on?

Testing some theories

I created a solution where I could test out a variety of different scenarios.

I tried setting UseShellExecute to both true and false - and tested with ffmpeg and docker (the control - known to work). Here’s what I saw:

Tests show that with UseShellExecute false, ffmpeg cannot be found

When UseShellExecute was set to false, ffmpeg could not be found - and the test fails.

Interestingly with UseShellExecute set to true, ffmpeg was found - however, this actually leads to the risk of unwanted behaviour, as with UseShellExecute enabled, the process could easily launch a document or folder in the GUI with the same name as the preferred binary tool.

The answer

In the end, the answer should have been obvious from the start, as described in this thread:

Mac GUI applications do not inherit environment variables defined in your shell profile.

Visual Studio didn’t know about my PATH and nor did the tests it launched.

However, when launching the tests from the shell, using the dotnet CLI, they worked perfectly - as the process could now find ffmpeg in the PATH:

dotnet test

It is also possible to launch Visual Studio from the terminal, using the open command - so giving it visibility of your shell’s PATH:

open -n /Applications/Visual\ Studio.app