Roslyn generator fails to load referenced assembly present in nuget packages - c#

In my VS 2022 solution I have two projects, a roslyn generator and a console app that I use to test the generator and other stuff.
Whenever I try to build the test app I get this warning:
CS8784: Generator 'Generator' failed to initialize. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'FileNotFoundException' with message 'Could not load file or assembly 'Microsoft.SqlServer.ConnectionInfo, Version=16.200.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot find the file specified.'
So it seems that I'm missing an assembly.
But actually Microsoft.SqlServer.ConnectionInfo.dll is present in my nuget package directory (under .nuget\packages\microsoft.sqlserver.sqlmanagementobjects\161.47021.0\lib\netstandard2.0, netcoreapp3.1 and net462) and has the right version for all three frameworks.
I also tried to reference assembly path in visual studio, and it didn't give a different result.
Whatever program is running the generator don't seem to be able to resolve it.
Moreover, my test app references the exact the exact same packages and run without any problem.
My guess is that running the generator manually (with my own entrypoint) would allow me to see where it tries to find the assemblies, but I have no idea how to do that with a generator.
Also one of the package gives me this warning for the generator but not the test app:
NU1701: Package 'Microsoft.SqlServer.Management.SmoMetadataProvider 161.47021.0' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework '.NETStandard,Version=v2.0'. This package may not be fully compatible with your project.
I would like to know how I can make my generator work, or at least, have some way to debug it to get more information on why it fails to load the assembly.
Here are the .csproj for the generator:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<IsRoslynComponent>true</IsRoslynComponent>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.2.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.2.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" Version="161.47021.0" />
<PackageReference Include="Microsoft.SqlServer.Management.SqlParser" Version="160.22506.0" />
</ItemGroup>
<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>
</Project>
and for the test console app:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" Version="161.47021.0" />
<PackageReference Include="Microsoft.SqlServer.Management.SqlParser" Version="160.22506.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\sql_modeler.generator\sql_modeler.generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\sql_modeler\sql_modeler.csproj" />
</ItemGroup>
</Project>

Related

How to make VS to copy nuget packages dll's to output directory

I'm trying to use material design in the first time on my WPF project I install the package from nuget but when I'm trying torun it it's prompt:
System.Windows.Markup.XamlParseException: 'Could not load file or
assembly 'MaterialDesignThemes.Wpf, Culture=neutral,
PublicKeyToken=df2a72020bd7962a'. The system cannot find the file
specified.'
When I'm copying the assemblies manually to the output folder it's works.
My .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<BaseOutputPath>$(SolutionDir)\bin\</BaseOutputPath>
<OutputPath>$(SolutionDir)\bin\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<UseCommonOutputDirectory>true</UseCommonOutputDirectory>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="4.6.1" />
<PackageReference Include="ShowMeTheXAML.MSBuild" Version="2.0.0" />
</ItemGroup>
</Project>
I tried to add
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
but it does nothing.
Here is my .csproj
<Project Sdk="Microsoft.NET. Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="4.6.1" />
</ItemGroup>
</Project>
Auto copy is fine. Your problem did not occur. Have you tried recreating a project, does the same problem occur?
If that still doesn't work, you may need to add the msbuild event to copy the file. Use xcopy.

.NET 6 System.IO.FileNotFoundException: Could not load file or assembly System.Linq, Version=6.0.0.0

I am trying to migrate a project from .NET Core 3.1 to .NET 6.
I have followed the official migration guide from Microsoft.
During build in startup.Configure I get
System.IO.FileNotFoundException: 'Could not load file or assembly
'System.Linq, Version=6.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file
specified.'
This is .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<AssemblyName>Omicron.Insurance.Runner</AssemblyName>
<RootNamespace>Omicron.Insurance.Runner</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Omicron.Insurance.Entities" Version="1.0.139" />
<PackageReference Include="Omicron.Platform.Web.ApplicationInsights" Version="3.1.60" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="5.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.22" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="6.0.1" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" />
<PackageReference Include="NodaTime" Version="3.0.9" />
<PackageReference Include="ServiceBus.AttachmentPlugin" Version="6.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
I had to update AzureFunctionsVersion from v3 to v4. That solved the issue.
Upgrading Azure Functions wasn't mentioned in the official migration guide from Microsoft.
EDIT: you also need to upgrade the Azure Function App as well.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-versions?tabs=in-process%2Cv4&pivots=programming-language-csharp#migrating-from-3x-to-4x
My case is different from the OP's but I want to share it for information. I run into this error when I try to use dnSpy to patch a C# DLL. It turns out the dnSpy compilation is targeting dependencies of my development machine. When I move the compiled DLL to the target machine, this error is raised as the dependencies are not met there. I have to compile it again on my target machine and the error is gone.

Unable to add native .dll reference to source generator project

You can find the full source code at https://github.com/myblindy/GrimBuilding/tree/efcore (the efcore branch).
I understand that source generators can't automatically harvest dependencies from nuget packages and you have to use a clunky work-around to get it to work, and I have done so. This is my source generator project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.0-1.final" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.*-*" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.*-*" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.*-*" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.*-*" GeneratePathProperty="true" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
</PropertyGroup>
<Target Name="GetDependencyTargetPaths">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PKGSQLitePCLRaw_bundle_e_sqlite3)\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSQLitePCLRaw_provider_e_sqlite3)\lib\netstandard2.0\SQLitePCLRaw.provider.e_sqlite3.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSQLitePCLRaw_lib_e_sqlite3)\runtimes\win-x64\native\e_sqlite3.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGMicrosoft_Data_Sqlite_Core)\lib\netstandard2.0\Microsoft.Data.Sqlite.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
</Project>
Since there also isn't any transitive support, I added every nested Microsoft.Data.Sqlite package one by one, generated their path property and referenced it using TargetPathWithTargetPlatformMoniker. It all works until I get to the native e_sqlite3.dll, if I use TargetPathWithTargetPlatformMoniker with it, it tries to reference it as a managed library, and it fails as expected:
4>CSC : warning CS8034: Unable to load Analyzer assembly C:\Users\meep.nuget\packages\sqlitepclraw.lib.e_sqlite3\2.0.5-pre20210521085756\runtimes\win-x64\native\e_sqlite3.dll : PE image doesn't contain managed metadata.
So given that the path is found, is there a different tag I can use to make the main project copy the e_sqlite3.dll file so the analyzer can use it?
Taken from .NET project SDK overview:
Build events
In SDK-style projects, use an MSBuild target named PreBuild or PostBuild and set the BeforeTargets property for PreBuild or the AfterTargets property for PostBuild.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command=""$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo Output written to $(TargetDir)" />
</Target>
Maybe you can move the file manually using one of these directives?
There's also this:
<Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
<Pack>true</Pack>
<PackagePath>build\</PackagePath>
</Content>
Could you move the file like that?

.NET Core 2.0 Project Builds But Not When Referenced By Another .NET Core 2.0 Project

I'm on Ubuntu and I have two .NET Core 2.0 projects (Project Oranges.csproj and Apples.csproj). Oranges only contains references to NuGet packages, while Apples contains a reference to Oranges.
Running dotnet build -f netcoreapp2.0 Oranges.csproj succeeds! Oranges.dll now exists at /Oranges/bin/Debug/netcoreapp2.0/Oranges.dll.
Running dotnet build -f netcoreapp2.0 Apples.csproj fails with: error CS0009: Metadata file '/Oranges/bin/Debug/netcoreapp2.0/Oranges.dll' could not be opened -- PE image doesn't contain managed metadata
How can I go about referencing Oranges, which builds without issue, in Apples without issue?
Oranges.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>netcoreapp2.0;net451;</TargetFrameworks>
<RootNamespace>Oranges</RootNamespace>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\GeneratedKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcore2.0'">
<DefineConstants>NETCORE2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net451'">
<DefineConstants>NET4_5_1</DefineConstants>
</PropertyGroup>
<ItemGroup>
<None Remove="packages.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
</ItemGroup>
</Project>
Apples.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>netcoreapp2.0;net451;</TargetFrameworks>
<RootNamespace>Apples</RootNamespace>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>..\..\GeneratedKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<None Remove="packages.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Composition" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Oranges\Oranges.csproj" />
</ItemGroup>
</Project>
After deleting the bin and obj folders from the project directory and rebuilding, a different error was being displayed.
CSC : error CS7027: Error signing output with public key from file 'GeneratedKey.snk' -- Assembly signing not supported. [.../Oranges/Oranges.csproj]
After some research I stumbled across a solution.
Assembly Signing Not Supported
Adding the line below to the .csproj file for each assembly that required signing resolved the issue.
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
For now it seems like if you need to sign netcore assemblies, it should be done on Windows.

Nuget Conflicting projectreference and packagereference

I'm running a ASP.NET Core app on the .NET 4.6.1 framework. I have 1 solution with multiple projects in it. All of the projects are class libraries that reference each other via PackageReferences in their .csproj (this way we can build, package and version them independently). However, I want to be able to test their integration with one another without needing to push them up to NuGet first - aka I want to use them as ProjectReferences in the solution, but PackageReferences when building them through my Jenkins build process in order to version the components separately.
When .NET Core was project.json based, this worked fine. I would set the version at the top of the project.json and if a project existed with that version in the solution it would reference it as a project, otherwise it would look for it on my NuGet feed.
The problem with using ProjectReferences is that all project's would get the same version when they are built and sent to NuGet.
Is there any way to do this in csproj? Look for a project reference if it exists, otherwise look at NuGet?
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>1.3.0</VersionPrefix>
<TargetFramework>net461</TargetFramework>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblyName>MyProject1</AssemblyName>
<PackageId>MyProject1</PackageId>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MyProject2" Version="1.4.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="1.1.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>
Above is an example, I would like MyProject2 to be referenced by ProjectReference if 1.4.0 exists in the solution.
I recently was try to do the same thing and couldn't find the answer but figured out something that works for me. You can use the Exists condition in MSBuild for the csproj to include the project reference when its there and exclude the package reference if its there:
<Project Sdk="Microsoft.NET.Sdk">
...
<ItemGroup>
<PackageReference Condition="!Exists('[path-to-project].csproj')" Include="[package-id]" Version="[pacakage-version].*" />
</ItemGroup>
...
<ItemGroup>
<ProjectReference Condition="Exists('[path-to-project].csproj')" Include="[path-to-project].csproj" />
</ItemGroup>
...
</Project>

Categories

Resources