简体   繁体   中英

Executing MSBuild via C# using `Process.Start` fails with error but works if I try manually in the command line

I'm building a C# Program that manipulates existing projects and then tries to compile them.

My program is currently being built using net6.0 .

I've located the SDKs (new dotnet.exe and old MSBuild.exe) on my machine. If I use dotnet.exe, it works fine and I've had no issues.

However, projects in the old non-sdk style can't be built using dotnet, so I'm trying to fall back to MSBuild.exe

Now I'm executing it using Process.Start (I've used CliWrap for ease of use, but also tried with the standard Process.Start(ProcessStartInfo) and had the same results) to start MSBuild.exe and pass it the project and some arguments. This looks like this:

        var processStartInfo = new ProcessStartInfo
        {
            FileName = Path.Combine(MSBuildDirectory, "MSBuild.exe"),
            WorkingDirectory = Path.GetDirectoryName(projectToBuild),
            RedirectStandardError = true,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            Arguments = $"\"{Path.GetFileName(projectToBuild)}\" /restore -t:build /p:Configuration=Release",
        };

        var process = Process.Start(processStartInfo);

This basically generates this command:

C:\Users\me\repo > "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe" "MyProject.csproj" /restore -t:build /p:Configuration=Release

This successfully starts building but then starts failing with some tasks, but the interesting thing is it's using the new .NET Core SDKs? Why and how is that happening when I'm passing it the old style MSBuild.exe ?

The error I'm getting is this:

      Build Error: Microsoft (R) Build Engine version 17.2.1+52cd2da31 for .NET Framework
      Copyright (C) Microsoft Corporation. All rights reserved.

      Build started 04/08/2022 14:32:26.
      Project "C:\Users\me\repo\MyProject.csproj" on node 1 (build target(s)).
      Project "C:\Users\me\repo\MyProject.csproj" (1) is building "C:\Users\me\repo\DependentProject.csproj" (2) on node 1 (GetTargetFrameworks target(s)).
      C:\Users\me\repo\DependentProject.csproj : error MSB4244: The SDK resolver assembly "C:\Program Files\dotnet\sdk\6.0.302\Microsoft.Build.NuGetSdkResolver.dll" could not be loaded. Could not load file or assembly 'Microsoft.Build.NuGetSdkResolver, Version=6.2.1.7, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. An attempt was made to load a program with an incorrect format.
      Done Building Project "C:\Users\me\repo\DependentProject.csproj" (GetTargetFrameworks target(s)) -- FAILED.
      Done Building Project "C:\Users\me\repo\MyProject.csproj" (build target(s)) -- FAILED.

      Build FAILED.

      "C:\Users\me\repo\MyProject.csproj" (build target) (1) ->
      "C:\Users\me\repo\DependentProject.csproj" (GetTargetFrameworks target) (2) ->
        C:\Users\me\repo\DependentProject.csproj : error MSB4244: The SDK resolver assembly "C:\Program Files\dotnet\sdk\6.0.302\Microsoft.Build.NuGetSdkResolver.dll" could not be loaded. Could not load file or assembly 'Microsoft.Build.NuGetSdkResolver, Version=6.2.1.7, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. An attempt was made to load a program with an incorrect format.

          0 Warning(s)
          1 Error(s)

      Time Elapsed 00:00:00.15

However, if I take that generated command above, set the same working directory and run it manually in a new command prompt window, then it works.

Why and what is happening?

I thought Process.Start would spawn a new process, so whether I did that manually, or my program did it, they'd behave the same?

I've tried both 32 Bit and 64 Bit MSBuild.exe's and both give identical results. Both giving an error containing a path to thet .NET 6 SDK folder.

It's as if launching Process.Start from within .NET Core keeps some sort of .NET Core context?

Can someone help here?

Thanks

I found it out via Microsoft Build Structured Logging. The difference was in the environment variables. My .NET Core program was passing on some Environment variables when spawning the new process. These were locations for the SDK - The one I didn't want it to use. I've set these to null and it's working now!

["MsBuildExtensionPath"] = null,
["MsBuildSDKsPath"] = null,
["MSBUILD_EXE_PATH"] = null

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM