Skip to content

Diagnostics.Process.Start: UseShellExecute=true and EnvironmentVariables gotcha #58069

Closed

Description

@shadowfoxish

I was working on a program that needs to shell out to an OS handler to do some printing, and was continually getting this error while I was debugging.

The Process object must have the UseShellExecute property set to false in order to use environment variables.

Short summary; if you (or anything including a debugger, serializer, etc) accesses ProcessStartInfo.EnvironmentVariables it gets set to not null and causes an exception later on when you try to use UseShellExecute = true and start the process.

What is occurring is the check here Process.Win32.cs#L47 has a conflict with the lazy initialization logic here ProcessStartInfo.cs#L78.

  • Suggested Improvement 1; In StartWithShellExecuteEx during the argument validation phase, rather than just check _environmentVariables = null, add a check for an empty collection.
if (startInfo._environmentVariables != null && _environmentVariables.Any())
                throw new InvalidOperationException(SR.CantUseEnvVars);

This would be the least impactful to the API and allows a user struggling with this problem to simply issue myProcessStartInfo.EnvironmentVariables.Clear(); to remove the environment variables. However, if a user does clear the EnvironmentVariables collection, they still had to silently load them at some point, due to the lazy loading logic.

  • Suggested Improvement 2; In ProcessStartInfo, add a check for UseShellExecute to gate access or creation of the EnvironmentVariables collection. Something like this:
        public IDictionary<string, string?> Environment
        {
            get
            {
                if (_environmentVariables == null && UseShellExecute == false)
                {
                 [..do the needful..]

This isn't a full solution since there's partial classes at work here, but this would in principle prevent the _environmentVariables variable from getting initialized if UseShellExecute was set to true. This creates an order of operations issue which would also have to be considered. If you accessed EnvironmentVariables and then later set UseShellExecute=true, what should happen?

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Aug 24, 2021
  2. tmds commented on Aug 25, 2021

    @tmds
    Member

    Another option may be to track whether the IDictionary<string, string?> that was returned to the user was mutated.
    And if it wasn't, not throw an exception.

  3. added this to the Future milestone on Aug 26, 2021
  4. removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 26, 2021
  5. karthikpn commented on Sep 27, 2024

    @karthikpn

    Is there any workaround for this?

  6. self-assigned this
    on Nov 12, 2026
  7. modified the milestones: Future, 12.0.0 on Nov 12, 2026
  8. added
    in-prThere is an active PR which will close this issue when it is merged
    on Nov 12, 2026
  9. added a commit that references this issue on Nov 12, 2026
    aa931db
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions