MSBuildWorkspace.OpenProjectAsync fails when dotnet is not pre-installed in the system
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
*Version Used:*
.NET: 8.0
sdk: 8.0.406
Microsoft.CodeAnalysis.CSharp.Workspaces: 4.12.0
Microsoft.CodeAnalysis.Workspaces.MSBuild: 4.12.0
Microsoft.Build: 17.8.3
Microsoft.Build.Locator: 1.6.10
*Description:*
We encountered a problem that prevents us from upgrading the NuGet dependencies of our project (specifically Microsoft.CodeAnalysis.CSharp.Workspaces and Microsoft.CodeAnalysis.Workspaces.MSBuild) from version 4.7 to 4.12.
We have a C++ project that we distribute along with .NET. The main app communicates with a C# handler, which tries to open and analyze an external C# project by executing the following lines of code:
```
MSBuildLocator.RegisterMSBuildPath(dotnetSdkDirectory);
using var workspace = MSBuildWorkspace.Create();
var project = workspace.OpenProjectAsync(Path.Combine(assemblyDirectory, $"{assemblyName}.csproj")).Result;
```
Upgrading the aforementioned NuGet packages from version 4.7 to version 4.12 causes the function call OpenProjectAsync to fail if our application is installed on systems where .NET is not preinstalled.
*Steps to Reproduce:*
Despite being unable to reproduce this problem with a minimal working example, we managed to reproduce this issue in a VM with Windows 10. We analyzed the differences between the two versions of the NuGet packages by connecting a remote debugger to our running application. Specifically, these additional lines of code were not present in version 4.7 but can be found in version 4.12 of `Microsoft.CodeAnalysis.Workspaces.MSBuild`.
```
var preferredBuildHostKind = BuildHostProcessManager.GetKindForProject(projectPath);
var (buildHost, actualBuildHostKind) = await _buildHostProcessManager.GetBuildHostWithFallbackAsync(preferredBuildHostKind, projectPath, cancellationToken
```
Starting the BuildHostProcess (.NET Core) causes the error: the dotnet executable seems to be launched from the working directory `""`, (from the debugger we see `processStartInfo.workingDirectory = ""`), which, in general, may not contain `dotnet.exe`. As a consequence, the PATH environment variable is used. It would be nice to have a way to specify where to look for `dotnet.exe` to prevent this issue from occurring when .NET is not installed on the system.
*Expected Behavior:*
No exception is thrown. The function call succeeds.
*Actual Behavior:*
An exception is thrown:
```
---> System.ComponentModel.Win32Exception (2): An error occurred trying to start process 'dotnet.exe' with working directory 'C:\Users\USER\Desktop\tmp'. The system cannot find the file specified.
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at Microsoft.CodeAnalysis.MSBuild.BuildHostProcessManager.GetBuildHostAsync(BuildHostProcessKind buildHostKind, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.BuildHostProcessManager.GetBuildHostWithFallbackAsync(BuildHostProcessKind buildHostKind, String projectOrSolutionFilePath, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadProjectFileInfosAsync(String projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadProjectInfosFromPathAsync(String projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadAsync(CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(String projectFilePath, ProjectMap projectMap, IProgress`1 progress, ILogger msbuildLogger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(String projectFilePath, ProjectMap projectMap, IProgress`1 progress, ILogger msbuildLogger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.OpenProjectAsync(String projectFilePath, ILogger msbuildLogger, IProgress`1 progress, CancellationToken cancellationToken)
```
*Additional Note:*
- Further analysis revealed that the problem arises from version 4.8 to 4.9.
Contributor guide
Assessment
This issue has not been assessed yet.