dotnet / dotnet/roslyn

MSBuildWorkspace.OpenProjectAsync fails when dotnet is not pre-installed in the system

Open
#77,640 5 comments 0 reactions 1 assignee Claimed by @JoeRobich View on GitHub
Area-IDE
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.