_From @jnm2 on March 13, 2017 20:31_
You can no longer reference some GAC assemblies without specifying a HintPath, at which point there isn't much point in using the GAC at all.
Class1.cs:
```c#
using System;
using Microsoft.SolverFoundation.Services;
public class Class1
{
public static readonly Type X = typeof(ISolver);
}
Old .csproj, working:
```xml
<Project ToolsVersion="15.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<OutputPath>bin\$(Configuration)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Solver.Foundation" />
</ItemGroup>
<ItemGroup>
<Compile Include="*.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
New .csproj fails to find the reference:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Solver.Foundation" />
</ItemGroup>
</Project>
This also does not work: <Reference Include="Microsoft.Solver.Foundation, Version=3.0.2.10889, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
.
Why is this broken?
_Copied from original issue: dotnet/roslyn-project-system#1739_
_From @jnm2 on March 13, 2017 20:40_
I'm also witnessing a weird phenomenon where some GAC assemblies can be referenced and the build succeeds, but Visual Studio shows build warnings and reference node warning icons saying the reference could not be resolved and if you open any of the .cs files, and the editor creates a whole bunch of errors as though the reference was not referenced at all. The weird part is, it _builds_ fine. For example, <Reference Include="DevExpress.Data.v16.2, Version=16.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL">
. All DevExpress dlls are this way. In contrast, Microsoft Solver Foundation is not.
But the moment I add a <SpecificVersion>false</SpecificVersion>
or a <SpecificVersion>true</SpecificVersion>
subelement, it goes back to not building at all.
I would really like to understand this phenomenon.
I don't want to use HintPaths because of the chance something will be different across developer machines and the build server, and why should I have to add ugly GAC paths?
_From @jnm2 on March 13, 2017 21:49_
As it turns out, HintPath with SpecificVersion false is not a useful workaround because the HintPath does not exist on different machines.
_From @jnm2 on March 13, 2017 23:11_
Adding this to the bottom of the new csproj and reopening the solution fixes all problems:
<!-- Workaround for https://github.com/dotnet/roslyn-project-system/issues/1739 -->
<PropertyGroup>
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
</PropertyGroup>
_From @jmarolf on March 13, 2017 23:35_
I can repro this. I'll need to look into what has changed regarding the GAC.
This should work in the mean time.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Solver.Foundation" Version="3.1.0" />
</ItemGroup>
</Project>
In SDK-based projects {GAC} is no longer part of the search paths. GAC is a runtime-lookup location, not a build-time lookup location. This is a deliberate change - it resulted in a huge number of bugs where projects would accidentally pick up the wrong dependencies on build machines because a targeting pack or SDK wasn't installed. I suspect when you add a version number, you are resolving it from a build-time location such as {AssemblyFoldersEx} instead of the GAC. Looking at the build log would help us figure that out.
As you found, the workaround is to explicitly add {GAC} to the set of search paths.
GAC is a runtime-lookup location, not a build-time lookup location.
Gotcha- and the ironic part is that we always have Copy Local true so at runtime they are never resolved from the GAC.
What's the ideal solution to resolve these references at build-time, with no hint path so that it works across multiple machines? PackageReference
, or <AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
, or some other configuration? I'm not familiar with AssemblyFoldersEx
, is that where the ideal solution lies?
The package isn't Microsoft-provided, so based on that - I would not recommend you use it.
If Microsoft.Solver.Foundation isn't installed into a folder listed under HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft.NETFrameworkv4.0.30319AssemblyFoldersEx - and is only installed into the GAC, then the only recommendation I have is what you've done above.
@davkean Microsoft Solver Foundation, for whatever reason, only appears at HKEY_CURRENT_USER\SOFTWARE\Microsoft\.Net Framework\Assembly Folders\Microsoft.Solver.Foundation
, value All Assemblies In
. It's nowhere else. It appears in Visual Studio's Add Reference dialog only if I target net40
. It disappears if I target net45
, net46
or net462
.
DevExpress appears at HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx\DevExpress Components 16.2
, value (Default)
. For new csproj, the dlls in that folder never appear in the Add Reference dialog no matter what framework version I target. For legacy csproj, the dlls all show up under the Extensions category. Is this a bug?
This behaviour is by-design. You can opt back in as shown here. This should not be considered a workaround, but rather a deliberate and supported opt-in where you accept the consequences of having potentially different (and even incorrect) build behaviour on different machines.
I'm still curious why VS2017 shows no AssemblyFoldersEx assemblies under Extensions for CPS csproj, but it does them all for legacy csproj.
@jnm2 Let's open another bug for that - that's not by design.
I'm still having an issue even when adding in the <AssemblySearchPaths>
bit. Here's part of what's in my .csproj:
<PropertyGroup>
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
</PropertyGroup>
...
<ItemGroup>
<Reference Include="Microsoft.SqlServer.Management.IntegrationServices"/>
<Reference Include="Microsoft.SqlServer.Management.Sdk.Sfc" />
<Reference Include="Microsoft.SqlServer.Smo" />
</ItemGroup>
Getting this for each one:
Warnings:
C:\Program Files\dotnet\sdk\1.0.4\Microsoft.Common.CurrentVersion.targets(1964,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Microsoft.SqlServer.Management.IntegrationServices". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [C:\projects\xtend-exports\src\app\Xtend.Exports.Services.Processor\Xtend.Exports.Services.Processor.csproj]
Error
(7,27): error CS0234: The type or namespace name 'Management' does not exist in the namespace 'Microsoft.SqlServer' (are you missing an assembly reference?)
These are the assemblies for kicking off an SSIS package from managed code. So, what am I missing here?
@derekgreer can you get a diagnostic-level log with msbuild /flp:v=diag
and share that? That has a ton of information about how and where the ResolveAssemblyReferences
task looks to try to find each reference.
Perhaps I'm not using the switch appropriately, but I'm not seeing any output difference:
$ dotnet msbuild /flp:v=diag
Microsoft (R) Build Engine version 15.1.1012.6693
Copyright (C) Microsoft Corporation. All rights reserved.
MyCompany.MyProject.Domain -> C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Domain\bin\Debug\net452\MyCompany.MyProject.Domain.dll
MyCompany.MyProject.Infrastructure.Persistence -> C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Infrastructure.Persistence\bin\Debug\net452\MyCompany.MyProject.Infrastructure.Persistence.dll
MyCompany.MyProject.Application -> C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Application\bin\Debug\net452\MyCompany.MyProject.Application.dll
MyCompany.MyProject.Infrastructure -> C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Infrastructure\bin\Debug\net452\MyCompany.MyProject.Infrastructure.dll
C:\Program Files\dotnet\sdk\1.0.4\Microsoft.Common.CurrentVersion.targets(1964,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Microsoft.SqlServer.Management.IntegrationServices". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Services.Processor\MyCompany.MyProject.Services.Processor.csproj]
C:\Program Files\dotnet\sdk\1.0.4\Microsoft.Common.CurrentVersion.targets(1964,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Microsoft.SqlServer.Management.Sdk.Sfc". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Services.Processor\MyCompany.MyProject.Services.Processor.csproj]
C:\Program Files\dotnet\sdk\1.0.4\Microsoft.Common.CurrentVersion.targets(1964,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Microsoft.SqlServer.Smo". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Services.Processor\MyCompany.MyProject.Services.Processor.csproj]
ExportHandlers\IntegrationServicesExportTaskHandler.cs(7,27): error CS0234: The type or namespace name 'Management' does not exist in the namespace 'Microsoft.SqlServer' (are you missing an assembly reference?) [C:\projects\mycompany-myprojects\src\app\MyCompany.MyProject.Services.Processor\MyCompany.MyProject.Services.Processor.csproj]
You would have to build with desktop msbuild.exe
and not CoreCLR dotnet msbuild
for the GAC to actually get searched.
Woah, so no way to reference the GAC when compiling with the dotnet CLI?
Correct. CLI uses CoreCLR msbuild, which is compiled without FEATURE_GAC.
Most helpful comment
_From @jnm2 on March 13, 2017 23:11_
Adding this to the bottom of the new csproj and reopening the solution fixes all problems: