New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't start a Process if StartInfo.EnvironmentVariables is called or evaluated on Windows systems
#94338
Comments
|
Tagging subscribers to this area: @dotnet/area-system-diagnostics-process Issue DetailsDescriptionThe When This is the message that is emitted as soon as Start() is called after evaluation:
What's worse is that this issue can be either triggered by hovering over the Furthermore, it appears to only affect Windows systems as Linux users don't get this error. Reproduction Steps
Expected behaviorThe process will start the Command Prompt on Windows and will not emit an Actual behaviorAn error of
This error comes from Regression?This is not a regression, because this issue occurred on .NET Framework, .NET 6.0, and .NET 7.0. Known WorkaroundsOne can use a dirty reflection-based workaround to get the StartInfo back to how it was before calling the internal static ProcessStartInfo StripEnvironmentVariables(ProcessStartInfo processStartInfo)
{
var privateReflection = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField;
var startInfoType = processStartInfo.GetType();
var envVarsField = startInfoType.GetField("_environmentVariables", privateReflection);
envVarsField.SetValue(processStartInfo, null);
return processStartInfo;
}Then, one can call this function to re-assign the Console.WriteLine($"{proc.StartInfo.EnvironmentVariables.Count}");
proc.StartInfo = StripEnvironmentVariables(proc.StartInfo)
proc.Start();This workaround is not needed in cases where However, this workaround only lasts until the next evaluation of Configuration
This issue only occurs when running on Windows. Other informationI've reviewed the source code for the .NET runtime and found that when starting processes with It looks like that one of these checks is for the if (startInfo._environmentVariables != null)
throw new InvalidOperationException(SR.CantUseEnvVars);This variable is populated when any attempt to evaluate public IDictionary<string, string?> Environment
{
get
{
if (_environmentVariables == null)
{
IDictionary envVars = System.Environment.GetEnvironmentVariables();
_environmentVariables = new DictionaryWrapper(new Dictionary<string, string?>(
envVars.Count,
OperatingSystem.IsWindows() ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal));
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
IDictionaryEnumerator e = envVars.GetEnumerator();
Debug.Assert(!(e is IDisposable), "Environment.GetEnvironmentVariables should not be IDisposable.");
while (e.MoveNext())
{
DictionaryEntry entry = e.Entry;
_environmentVariables.Add((string)entry.Key, (string?)entry.Value);
}
}
return _environmentVariables;
}
}
|
|
Duplicate of #58069. As suggested there, this could be fixed by attempting to detect mutation of the IDictionary. @AptiviCEO would you be interested in sending a PR? |

Description
The
Processclass contains a property calledStartInfothat allows you to customize how the process will start, likeUseShellExecuteto determine whether the process is created by the operating system or by the application itself.When
UseShellExecuteis turned on by setting it to true, the process can't be started withStart()because of anInvalidOperationException. This happens after evaluation of either theEnvironmentor theEnvironmentVariablesproperty from theStartInfoof theProcess.This is the message that is emitted as soon as
Start()is called after evaluation:System.InvalidOperationException: The Process object must have the UseShellExecute property set to false in order to use environment variables.What's worse is that this issue can be either triggered by hovering over the
Processvariable on Visual Studio and opening theStartInfoproperty to see its values while debugging your process start code, or by directly invoking theEnvironmentVariablesproperty from your code as we can see in the POC.Furthermore, it appears to only affect Windows systems as Linux users don't get this error.
Reproduction Steps
InvalidOperationExceptionExpected behavior
The process will start the Command Prompt on Windows and will not emit an
InvalidOperationExceptionActual behavior
An error of
InvalidOperationExceptionoccurs and the process will not launch.System.InvalidOperationException: The Process object must have the UseShellExecute property set to false in order to use environment variables.This error comes from
StartWithShellExecuteEx(), which is called byStartCore().Regression?
This is not a regression, because this issue occurred on .NET Framework, .NET 6.0, and .NET 7.0.
Known Workarounds
One can use a dirty reflection-based workaround to get the StartInfo back to how it was before calling the
EnvironmentVariablesproperty:Then, one can call this function to re-assign the
StartInfoproperty on the afflictedProcessvariable:This workaround is not needed in cases where
UseShellExecuteis not enabled.However, this workaround only lasts until the next evaluation of
EnvironmentVariablesorEnvironment.Configuration
This issue only occurs when running on Windows.
Other information
I've reviewed the source code for the .NET runtime and found that when starting processes with
UseShellExecuteenabled,StartCore()callsStartWithShellExecuteEx(), which checks the state of theProcessinstance before starting the process.It looks like that one of these checks is for the
startInfo._environmentVariablesvariable on line 47.This variable is populated when any attempt to evaluate
EnvironmentVariablesorEnvironmentis done either by the Visual Studio debugger or by the user code. This is on line 91.The text was updated successfully, but these errors were encountered: