System.DllNotFoundException on Mono SQLite - c#

I've been trying to figure this out lately. It is working on my Windows machine, where I got SQLite from NuGet, but...
When I put System.Data.SQLite.dll and SQLite.Interop.dll straight from my Windows machine into Linux server it says that SQLite.Interop.dll is not found, but I am sure I see it next right to executable.
Then I tried to compile System.Data.SQLite.dll with /p:UseInteropDll=false, but with no luck. This time it says that System.Data.SQLite.dll is not found.
What is this "not found" mystery?

No code changes necessary. You can build it yourself.
apt-get install build-essentials unzip
Download the SQLITE source code - you want the full source code. Currently called sqlite-netFx-full-source-1.0.104.0.zip.
unzip and cd Source,
chmod +x the compile-interop-assembly-release.sh build shell script, then run it ./compile-interop-assembly-release.sh. - It'll build an .so file in the ../bin directory.
Copy this .so file to the directory that has your application in
Run your application as normal.
Note: Ensure that your SQLite database and the directory it's inside of are writable by the user you're trying to run as.

Use Mono.Data.SQLite.dll on Linux. Take a look at the Mono manual to using SQLite on Linux or build the System.Data.SQLite.dll on Mono.
You can also map the DLL:
<configuration>
<dllmap dll="sqlite" target="libsqlite.so.0" os="linux"/>
<dllmap dll="sqlite" target="libsqlite.0.dylib" os="osx"/>
<dllmap dll="sqlite3" target="libsqlite3.so.0" os="linux"/>
<dllmap dll="sqlite3" target="libsqlite3.0.dylib" os="osx"/>
</configuration>

I started the development in Windows, but then moved the application to Mono (Ubuntu 14), which is where the SQLite provider failed to load as OP described.
I had to recompile the System.Data.SQLite.dll using the following command:
MSBuild System.Data.SQLite.2012.csproj /t:Rebuild /p:UseInteropDll=false /p:UseSqliteStandard=true
However, after this I've got the following exception:
The provider did not return a ProviderManifest instance.
Method System.Data.SQLite.UnsafeNativeMethods:GetSettingValue (string,string)' is inaccessible from methodSystem.Data.SQLite.EF6.SQLiteProviderManifest:GetProviderManifestToken (string)'
To fix this, I had to recompile the System.Data.SQLite.EF6.dll using the following command:
MSBuild System.Data.SQLite.EF6.2012.csproj /t:Rebuild /p:UseInteropDll=false /p:UseSqliteStandard=true
After copying all of the generated files to Mono project's bin directory, everything worked.
The SQLite provider source code version I had used was 1.0.98.1.
Hope this saves someone a lot of time...

I tried all the above option but those options could not solve SQLite DLL problem, It may be because I am using ubuntu 18 version, So tried other option and here the steps,
1) Download SQLite source code from the https://system.data.sqlite.org/downloads/1.0.111.0/sqlite-netFx-full-source-1.0.111.0.zip
2) unzip source code and cd to unzip directory
3) Run the following command in the terminal,
xbuild /p:Configuration=Release /p:UseInteropDll=false /p:UseSqliteStandard=true ./System.Data.SQLite/System.Data.SQLite.2010.csproj
4) Above command would create a dll file at following path,
sqlite-netFx-full-source-1.0.111.0/bin/2010/ReleaseMonoOnPosix/bin
5) Copy System.Data.SQLite.dll to your project bin folder.
6) Clean project and build again.
I hope this would help.

Starting with System.Data.SQLite.Core 1.0.109 you don't need to compile anything yourself since the native SQLite.Interop.dll files are included in the NuGet package for all platforms (Linux, macOS and Windows). Note that although the dll extension is used for all platforms, the files are actually native dynamic libraries (usually suffixed dylib on macOS and so on Linux).
$ find ~/.nuget/packages/system.data.sqlite.core/1.0.111/runtimes -name SQLite.Interop.dll -print0 | xargs -0 file
…/runtimes/linux-x64/native/netstandard2.0/SQLite.Interop.dll: ELF 64-bit LSB pie executable x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=96ce4120b31bad7d95f7b9ccf7c4bbb7717ae0b1, with debug_info, not stripped
…/runtimes/osx-x64/native/netstandard2.0/SQLite.Interop.dll: Mach-O 64-bit dynamically linked shared library x86_64
…/runtimes/win-x86/native/netstandard2.0/SQLite.Interop.dll: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
…/runtimes/win-x64/native/netstandard2.0/SQLite.Interop.dll: PE32+ executable (DLL) (GUI) x86-64, for MS Windows
Unfortunately, the MSBuild target responsible for copying the native dynamic libraries into the output directory only works on Windows. This is probably because the authors of the package assumed that .NET Framework only runs on Windows, which is not true thanks to Mono. Also, if you wanto to have a look, the CopySQLiteInteropFiles target can be found in ~/.nuget/packages/system.data.sqlite.core/{version}/build/net4*/System.Data.SQLite.Core.targets.
But it's possible to automatically copy the SQLite.Interop.dll file into the output directory on Linux and macOS. Add the FixSQLiteInteropFilesOnLinuxAndOSX target (described below) in your csproj file and you'll be able to use System.Data.SQLite.Core on Linux and macOS running mono without the DllNotFoundException. Here's how your project should look like:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net452</TargetFramework>
</PropertyGroup>
<Target Name="FixSQLiteInteropFilesOnLinuxAndOSX" BeforeTargets="CopySQLiteInteropFiles">
<ItemGroup>
<SQLiteInteropFiles Condition="$([MSBuild]::IsOsPlatform(Linux)) OR $([MSBuild]::IsOsPlatform(OSX))" Remove="#(SQLiteInteropFiles)" />
<SQLiteInteropFiles Condition="$([MSBuild]::IsOsPlatform(Linux))" Include="$(PkgSystem_Data_SQLite_Core)/runtimes/linux-x64/native/netstandard2.0/SQLite.Interop.*" />
<SQLiteInteropFiles Condition="$([MSBuild]::IsOsPlatform(OSX))" Include="$(PkgSystem_Data_SQLite_Core)/runtimes/osx-x64/native/netstandard2.0/SQLite.Interop.*" />
</ItemGroup>
</Target>
<ItemGroup>
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.111" GeneratePathProperty="true" />
</ItemGroup>
</Project>
Make sure to add GeneratePathProperty="true" in the package reference. This is required for the PkgSystem_Data_SQLite_Core property to be defined.

Related

How can I wrap C# DLLs into a NuGet package on Ubuntu?

On Ubuntu I'd like to wrap a few C# DLL files into a NuGet package. On Windows one would use the NuGet package explorer or nuget.exe + manually edited *.csproj.nuspec. In summary when manually editing the *.nuspec file one may add DLLs via the <files> section:
<files>
<file src="some\Path\YourDll.dll" target="lib"></file>
</files>
On Ubuntu I'd like to use dotnet pack instead. However it seems like it's not able to operate on a *.csproj.nuspec file:
Usage: dotnet pack [options] <PROJECT | SOLUTION>
Arguments:
<PROJECT | SOLUTION> The project or solution file to operate on. If a file is not specified, the command will search the current directory for one.
Options:
-h, --help Show command line help.
-o, --output <OUTPUT_DIR> The output directory to place built packages in.
--no-build Do not build the project before packing. Implies --no-restore.
--include-symbols Include packages with symbols in addition to regular packages in output directory.
--include-source Include PDBs and source files. Source files go into the 'src' folder in the resulting nuget package.
-c, --configuration <CONFIGURATION> The configuration to use for building the package. The default for most projects is 'Debug'.
--version-suffix <VERSION_SUFFIX> Set the value of the $(VersionSuffix) property to use when building the project.
-s, --serviceable Set the serviceable flag in the package. See https://aka.ms/nupkgservicing for more information.
--nologo Do not display the startup banner or the copyright message.
--interactive Allows the command to stop and wait for user input or action (for example to complete authentication).
--no-restore Do not restore the project before building.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--runtime <RUNTIME_IDENTIFIER> The target runtime to restore packages for.
--no-dependencies Do not restore project-to-project references and only restore the specified project.
--force Force all dependencies to be resolved even if the last restore was successful.
This is equivalent to deleting project.assets.json.
Can I wrap C# DLLs into a NuGet package on Ubuntu using the dotnet CLI? Or do I have to use the nuget CLI (apt-get install nuget) instead with the approach like on Windows?
I would add this into the .csproj file:
<ItemGroup>
<Content Include="some.dll" PackageCopyToOutput="true">
<pack>true</pack>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
It's not pretty but it works.

What is the correct way to do a "dotnet publish" on Project1 before building Project2

I have a solution with 2 projects. One is a VSIX and the other is a .NET Core 2.1 Console app.
The projects do not directly depend on each other, but I need to ensure that VSIX embeds a fresh version of all output files from the other project as it is built, because it will need them at runtime.
Putting the following in the post-build event of the VSIX project used to work:
cd "$(SolutionDir)MyCoreConsoleApp"
dotnet publish --configuration $(Configuration)
It's worth mentioning that there were some strange problems with this setup in the beginning, though... The console app could be built fine if done by issuing rebuild of the project from Solution Explorer directly. Issuing dotnet publish from VSIX's before-build, on the other hand, would fail with errors, basically saying the build system could not locate all the required files.
After a lot of effort, I determined that the problem was the fact that console app used Fody Costura at the time. After removing this dependency, dotnet publish started working without any problems.
Fast forward to yesterday... I added a dependency on MSBuild Community Tasks to console app project, because I wanted to use the Zip task to embed a zipped copy of some content files as EmbeddedResource. I've added a custom Target to the csproj and confirmed that it worked correctly when doing a direct build of the project or issuing dotnet publish from command line. In case it matters, the Target itself looks like this:
<Target Name="ZipAndEmbedWwwRoot" BeforeTargets="BeforeBuild">
<CreateItem Include="wwwroot\**\*">
<Output ItemName="ZipFiles" TaskParameter="Include" />
</CreateItem>
<Zip ZipFileName="$(IntermediateOutputPath)wwwroot.zip" WorkingDirectory="wwwroot" Files="#(ZipFiles)" />
<ItemGroup>
<EmbeddedResource Include="$(IntermediateOutputPath)wwwroot.zip">
<LogicalName>wwwroot.zip</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Target>
But now building the VSIX started failing again. The error is:
The "MSBuild.Community.Tasks.Zip" task could not be loaded from the
assembly
C:\Users\MyUserName\.nuget\packages\msbuildtasks\1.5.0.235\build\..\tools\MSBuild.Community.Tasks.dll.
Could not load file or assembly 'Microsoft.Build.Utilities.v4.0,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
The system cannot find the file specified. Confirm that the
declaration is correct, that the assembly and all its
dependencies are available, and that the task contains a public class
that implements Microsoft.Build.Framework.ITask.
As soon as I remove the custom Target, things start working again.
I'm starting to think I'm probably missing something when calling dotnet publish on a project, which has additional msbuild dependencies. This was probably the reason why Fody Costura didn't work, either.
So the question is, how should I be doing this, then?
The community Zip task is quite old and no longer works with recent versions of MSBuild or the cross-platform dotnet CLI.
However, VS 2017 15.8 and the CLI 2.1.400 introduced the built-in ZipDirectory task you could use instead.

Automatic native and managed DLLs extracting from Nuget Package

This is driving me crazy for several months now and I'm still not able to achieve it. My managed libraries are extracted from the Nuget package but not the natives ones.
We have a bunch of managed and native libraries provided by another company.
We have both x86 and x64 version of them. In order to use them in an ASP.NET Core project I have to create an Nuget Package.
My architecture is:
an ASP.NET Core class library that I changed to target full .NET Framework only. This project references my Nuget Package
an ASP.NET Core website also targeting full .NET Framework and referencing the class library
Of course, at the end, I need my native libraries being extracted to the proper runtime folder of the Website (eg: \bin\Debug\net461\win7-x64).
For the moment my solution was:
to put the native libs inside the build folder
create a targets file that copies them to the $(OutputPath) (which is even not the runtime folder)
add some MsBuild commands to the xproj of my website to get the targets file in my $(USERPROFILE)\.nuget\packages\ folder and execute it
copy by hand the native DLLs now extracted in bin folder to the runtime one
I've tried to copy them directly to the runtime folder using some configuration in project.json (I honestly don't remember all the things I've tried for this part) but this was always failing. Also even though I specified SkipUnchangedFiles="true" in my targets file, this is just ignored and my DLLs are copied to my bin folder during each build.
This is an heavy process just to achieve a DLLs extracting, now I really want to get rid of all that MsBuild and get a much simpler solution.
I know with newer versions of Nuget, it's now capable of extracting them natively without any help of adding custom MsBuild commands. As written here, C# projects don't even need a targets file
Next, C++ and JavaScript projects that might consume your NuGet package need a .targets file to identify the necessary assembly and winmd files. (C# and Visual Basic projects do this automatically.)
I kept a tab opened in my browser for several month (original link) and realize this resource has been recently removed from Nuget website. It was explaining how to use the runtimes folder to automatically extract natives DLLs. However I've never been able to get a successful result as it was explained. Now this page has been deleted and replaced by this one with so few explanations and not talking about this runtimes folder at all.
My guess is that I should use runtimes folder for native DLLs and the lib one for managed but I'm not 100% sure of that. (also should I use the build folder?)
I've tried several things (I can't recall number of attempts, as I said several months of headache...) like this architecture (I don't understand here what's the point of having build/native and also natives folders under runtimes)
I also tried to use the .NET framework version structure as described here for my managed libraries.
This seems to be also part of the solution
The architecture is ignored by the compiler when creating an assembly reference. It's a load time concept. The loader will prefer an architecture specific reference if it exists.
One trick you can use to produce an AnyCPU assembly is to use corflags to remove the architecture from your x86 assembly. EG: corflags /32BITREQ- MySDK.dll. Corflags is part of the .NET SDK and can be found in VS's developer command prompt.
That's what I did, converting both x86 and x64 DLLs to AnyCPU (don't know if it does something for x64 DLLs but I didn't get errors) and then tried several different architectures in my Nuget package but still not working.
The default runtime without any entry in project.json is win7-x64, so I decided to explicitly specify it just in case
"runtimes": {
"win7-x64": {}
},
So this is the Runtime Identifier I'm using for all my attempts in my Nuget package. However I don't care about the windows version. I would actually prefer having win-x86 or win-x64 but it seems to be an invalid value according to this page
Windows RIDs
Windows 7 / Windows Server 2008 R2
win7-x64
win7-x86
Windows 8 / Windows Server 2012
win8-x64
win8-x86
win8-arm
Windows 8.1 / Windows Server 2012 R2
win81-x64
win81-x86
win81-arm
Windows 10 / Windows Server 2016
win10-x64
win10-x86
win10-arm
win10-arm64
However this Github source is describing more RID so which source is right?
As you can see, there is so many mysteries here, mostly because of the lack of documentation or even contradictions between different docs.
If at least I could have a working example, then I could perform my tests to answer other questions like trying generic win-x64 RID or see if I can include once my managed libs whatever the .NET Framework version.
Please pay attention to my special context: I have an ASP.NET Core project targeting the full .NET Framework
Thanks for your answers, I'm desperate to get this simple thing working.
I will try to explain all the pain and solutions I've been through as detailed as possible. In my example I use simple text files AAA86.txt, AAA64.txt and AAAany.txt instead of native DLLs to simply demonstrate the extraction process.
First thing you need to know:
If you try to mix the native NuGet's architecture with a lib folder containing some managed libraries, IT WILL NOT WORK
In that case your managed DLLs will be copied to your project's output directory but NOT your native ones.
Thanks to Jon Skeet who pointed me in the good direction, advising me to take a look at the Grpc.Core package. The trick is to create a targets file that will handle the DLL extraction.
Your targets file should contain something like this
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
<Content Include="$(MSBuildThisFileDirectory)..\runtimes\win-x64\native\AAA64.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>AAA64.txt</Link>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'x86' OR '$(Platform)' == 'AnyCPU' ">
<Content Include="$(MSBuildThisFileDirectory)..\runtimes\win-x86\native\AAA86.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>AAA86.txt</Link>
</Content>
</ItemGroup>
</Project>
Also make sure your .targets file is named the same as your AssemblyName. So if the name of your assembly is DemoPackage, your targets file should be named DemoPackage.targets. Otherwise, the .targets file might not be applied when referencing the package in another project.
Now few other things you need to know:
1) Visual Studio doesn't care at all about the settings you choose, it will always use a dummy RID. (In my case I always end up with a win7-x64 folder even though I'm on Windows 10...)
2) The platform setting in your project.json is also totally useless
{
"buildOptions": {
"platform": "x64"
}
}
3) In the runtimes settings if you set only win and/or win-x64
"runtimes": {
"win": {},
"win-x64": {}
}
Visual Studio will instead use win7-x64. But if you add win10-x64 while you are on a Windows 10 machine then this will be used
4) If you compile your application with a generic RID like this
dotnet build -c debug -r win
Then your targets file will receive the architecture of your machine (x64 in my case) instead of AnyCPU as I was expecting
5) With only native libraries without any managed ones, the extraction will work without a target file if you follow the architecture runtimes/RID/native
6) With only native libraries in my package, the chosen RID will always be win-x64 building with Visual Studio as I told you the runtime folder always created is win7-x64, no matter the configuration I select. If I only had one single win RID in my package then it would successfully be picked.
EDIT:
As a last useful note, when working on such tasks, you might find it convenient to print out the current directory from which your .targets file is being executed like this
<Target Name="TestMessage" AfterTargets="Build" >
<Message Text="***********************************************************" Importance="high"/>
<Message Text="$(MSBuildThisFileDirectory)" Importance="high"/>
<Message Text="***********************************************************" Importance="high"/>
</Target>
Your directory will be printed out in the Build output in Visual Studio
The problem of native DLLs not being copied to the output directory is gone nowadays when you use dotnet restore instead of nuget.exe restore.
The issue was solved in my case when using specifically dotnet restore --runtime win-x64 <path_to_the_solution.sln>.
As a continuation to the answer of #Jérôme MEVEL,
GeneratePathProperty is a new feature which is available with NuGet 5.0 or above and with Visual Studio 2019 16.0 or above.
Using this feature, you can know the exact path of the installed package in the consumer of the package.
If the package is named Mypackage.ID, then you can refer to its path as: $(PkgMypackage_id) with replacing dot '.' with underscore '_'.
In the package consumer
Add GeneratePathProperty="true" attribute to the PackageReference
<ItemGroup>
<PackageReference Include="Some.Package" Version="1.0.0" GeneratePathProperty="true" />
</ItemGroup>
In the package creator:
Path of the package can be reached as given below:
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
<Content Include="$(PkgMyPackage_Id)\runtimes\win-x64\native\AAA64.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>AAA64.txt</Link>
</Content>
</ItemGroup>
Notice the path is: "$(PkgMyPackage_Id)\runtimes\win-x64\native\AAA64.txt
For more details read: GeneratePathProperty

roslyn compiler not copied to AspnetCompileMerge folder using msbuild

I have a .NET MVC project that I'm trying to deploy using Jenkins.
I had been letting Jenkins run msbuild, then copying the resulting files out using RoboCopy. I wanted to switch to just use a publish profile. The publishing profile works fine on my local machine using Visual Studio, but on the Jenkins host it fails using msbuild.
The error it gives is
ASPNETCOMPILER : error ASPRUNTIME: Could not find a part of the path 'C:\Program Files (x86)\Jenkins\jobs\myProject\workspace\myProject\obj\Debug\AspnetCompileMerge\Source\bin\roslyn\csc.exe'. [C:\Program Files (x86)\Jenkins\jobs\myProject\workspace\myProject\calendar.csproj]
I'm using the Microsoft.Net.Compilers nuget package to pull in the C# compiler, because some of the collaborators on the project are still on Visual Studio 2013, but we're using C#6 language features in the project.
Thing is, the project built just fine using MSBuild on jenkins before I added the publish flag. It's only since adding the /p:DeployOnBuild=true;PublishProfile=MyProfile setting that it started failing... yet the publish step works fine from withing Visual Studio, and the roslyn compiler even gets copied to the obj\Debug\AspnetCompileMerge\Source\bin\ folder on my local machine. What gives?
Honestly, since msbuild14 is available on the Jenkins server, it probably doesn't even need the roslyn csc.exe file. Is there a way I can make msbuild ignore it?
My Publish Profile
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>\\myserver\someshare\mysite</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
<PrecompileBeforePublish>True</PrecompileBeforePublish>
<EnableUpdateable>True</EnableUpdateable>
<DebugSymbols>False</DebugSymbols>
<WDPMergeOption>DonotMerge</WDPMergeOption>
</PropertyGroup>
</Project>
What I've Tried So Far
I've tried updating the compiler package.
Manually copying compiler
I added steps to my .csproj file to force-copy the missing compiler files to the AspnetCompileMerge directory (I'd already been copying them to the bin\roslyn directory to resolve another problem)
<Target Name="CopyRoslynFiles" AfterTargets="BeforeBuild">
<ItemGroup>
<RoslynFiles Include="$(SolutionDir)packages\Microsoft.Net.Compilers.1.1.1\tools\*" Exclude="$(SolutionDir)packages\Microsoft.Net.Compilers.1.1.1\tools\*.sys" />
</ItemGroup>
<MakeDir Directories="$(WebProjectOutputDir)\bin\roslyn" />
<MakeDir Directories="$(WebProjectOutputDir)\obj\$(Configuration)\AspnetCompileMerge\Source\bin\roslyn" />
<Copy SourceFiles="#(RoslynFiles)" DestinationFolder="$(WebProjectOutputDir)\bin\roslyn" SkipUnchangedFiles="true" Retries="$(CopyRetryCount)" RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)" />
<Copy SourceFiles="#(RoslynFiles)" DestinationFolder="$(WebProjectOutputDir)\obj\$(Configuration)\AspnetCompileMerge\Source\bin\roslyn" SkipUnchangedFiles="true" Retries="$(CopyRetryCount)" RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)" />
</Target>
Turning off Updateability in the publish profile
Based on Wesley Rathburn's answer on a similar question, I tried making the precompiled site so it could not be updated in the publish profile:
<EnableUpdateable>False</EnableUpdateable>
Though this revealed some dead code that needed removed in my views, it didn't fix the error during the jenkins build.
Running MsBuild locally
I can successfully run the msbuild command on my local machine. It deploys to the server and everything. Here's the command I run in powershell:
&"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /p:Configuration=Debug "/p:DeployOnBuild=true;PublishProfile=MyProfile" myproject\myproject.csproj
Removing the statements that copy the compiler entirely
It occurred to me that maybe I didn't need the statements to copy the roslyn compiler to the bin folder anymore, since msbuild14 was available on Jenkins now (and I'm not sure it was when I first built the project). Sadly, same error occurs. It's looking for the roslyn\csc.exe file, even though there's no apparent need for it to do so!
Just putting this here, because I spent two days trying to resolve this same issue (roslyn csc.exe not copied), but none of these answers solved my problem.
It turns out that Microsoft.CodeDom.Providers.DotNetCompilerPlatform 1.0.6 (and 1.0.7) is broken. Downgrade to 1.0.5.
I was getting the same errors as everyone else here, but I'm using VS 2017, and both local WebDeploy as well as AzureDeploy were broken (no csc.exe found). I tried all the suggestions that I could find on the internet (most of them redirect back to this SO post) but nothing worked until I downgraded to 1.0.5.
So I hope this is helpful to anyone who is struggling and has just recently upgrade to 1.0.6!
See:
https://github.com/aspnet/RoslynCodeDomProvider/issues/13
and
https://github.com/dotnet/roslyn/issues/21340
So, the workaround I'm using for now (which I don't entirely like), is just to remove the dependencies on the Compilers and CodeDOM Compilers packages. I also had to clear out the references in the .csproj and web.config files. That involved removing those packages from a shared assembly as well.
This will break the project for people still using Visual Studio 2013, which I don't like, but it builds on my Jenkins host now, which I do like. If anyone has a better solution, I'd be happy to hear it.
So yeah, I have this problem too with VS2017 & VS2019 and Microsoft.CodeDom.Providers.DotNetCompilerPlatform2.0.1 too. Did a lot of troubleshoooting msbuild and digging deep and trying to do my own workarounds and the changes in build file that just did nothing, but that didn't seem right at all. So I started looking in a different direction.
What I discovered was I couldn't build a .csproj directly and have either the nuget targets in Microsoft.CodeDom.Providers.DotNetCompilerPlatform get run by msbuild, or my own custom ones.
However using msbuild with the .sln with a target of myproj:Rebuild made everything work.

SGEN: An attempt was made to load an assembly with an incorrect format

I have a project that can build fine on my local machine, however, when I get TFS to build it, I receive the following error -
SGEN: An attempt was made to load an assembly with an incorrect format:
After reading through many other posts here on this topic, most people just say I need to change the build type to either x86 or Any CPU, rather than x64, but after trying countless combinations, this was not the solution. My program is also a windows service, so setting the App Pool to allow 32 bit applications (as suggested by others) is also not the solution.
I encountered this same issue today. A project would not build on my PC but built fine on other PC's
I eventually fixed it by doing the following:
Right-clicked the project with the error, went into Properties
Selected the Build tab and went to the last option which is "Generate serialization assembly"
I set this to Off and the project now builds fine.
My problem was finally solved by this page - http://aplocher.wordpress.com/2012/10/12/sgen-an-attempt-was-made-to-load-an-assembly-with-an-incorrect-format-tfs-2010/
Just in case that page ever disappears in the future, here are the steps involved -
In Team Explorer, right click on your Build Definition and choose Open Process File Location
Double click on the XAML file that is selected
In the designer, select the container called Sequence (this is the top-level container that goes around everything else).
In the Arguments list (typically at the bottom), change MSBuildPlatform from Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto to Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.X86.
Save and close the file.
Check the file back in to TFS and try your build again.
The problem disappears after installing the latest Windows SDK which includes the 64Bit version of sgen.exe:
http://msdn.microsoft.com/en-us/windows/desktop/bg162891.aspx
Sometimes (if that one does not help) the older version helps:
http://msdn.microsoft.com/en-us/windows/desktop/hh852363.aspx
For some reason the 64bit version of sgen is not included in the Microsoft Build Tools
I found this issue relevant:
https://github.com/dotnet/sdk/issues/1630
While waiting for this to be fixed in a future version, I was able to solve the problem by adding two targets to the csproj file, as suggested by https://github.com/joperezr:
<Target Name="RemoveDesignTimeFacadesBeforeSGen" BeforeTargets="GenerateSerializationAssemblies">
<ItemGroup>
<ReferencePath Remove="#(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
</ItemGroup>
<Message Importance="normal" Text="Removing DesignTimeFacades from ReferencePath before running SGen." />
</Target>
<Target Name="ReAddDesignTimeFacadesBeforeSGen" AfterTargets="GenerateSerializationAssemblies">
<ItemGroup>
<ReferencePath Include="#(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
</ItemGroup>
<Message Importance="normal" Text="Adding back DesignTimeFacades from ReferencePath now that SGen has run." />
</Target>
This question still pops up first in Google when I search certain keywords, so I'll post this in case anyone finds it relevant.
In my case, I had a project that built fine in "debug" but gave the OP's error in "release" mode. None of the solutions elsewhere in this thread solved the problem.
However, I ran into an obscure comment in another forum about web service references interfering with the build. A light bulb went off. My project had a number of legacy web service references that were no longer used. So I ripped them out. Lo and behold, I could now build the project in "release" mode, without disabling assembly serialization or fiddling with the CSPROJ or messing with SGEN references in Azure DevOps/VSTS.
Hopefully this saves someone time.
I encountered the same error when I tried to compile my project (Platform target is set to x86) in Release. It compiled fine in Debug. I came to find out that in Release, Generate serialization assembly is run; hence, the call to the SGen utility. The problem was that MSBuild called the x64 version of SGen against my x86 EXE, which generated the error. I had to pass this MSBuild argument so that MSBuild uses the correct version of SGen:
/p:SGenToolPath="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools"
My answer is an extension to that of ola-eldøy. In my case I had to exclude more assemblies, because each of them yielded the same dreadful error:
Could not load file or assembly bla-bla-bla or one of its dependencies. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)
Therefore my solution was to extend ola-eldøy's code and save it in Directory.Build.targets:
<Project>
<ItemGroup>
<ReflectionOnlyAssemblyNames Include="Microsoft.Bcl.AsyncInterfaces"/>
<ReflectionOnlyAssemblyNames Include="System.Buffers"/>
<ReflectionOnlyAssemblyNames Include="System.Numerics.Vectors"/>
<ReflectionOnlyAssemblyNames Include="System.Runtime.CompilerServices.Unsafe"/>
</ItemGroup>
<Target Name="RemoveDesignTimeFacadesBeforeSGen" BeforeTargets="GenerateSerializationAssemblies">
<ItemGroup>
<_ReflectionOnlyAssembly_Names Include="#(_ReferencePath_Names)"
Condition="'#(ReflectionOnlyAssemblyNames)' == '#(_ReferencePath_Names)' And '%(Identity)' != ''"/>
</ItemGroup>
<ItemGroup>
<ReferencePath Remove="#(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
<ReferencePath Remove="#(_ReflectionOnlyAssembly_Names->'%(OriginalIdentity)')" />
</ItemGroup>
<Message Importance="normal" Text="Removing DesignTimeFacades from ReferencePath before running SGen." />
</Target>
<Target Name="ReAddDesignTimeFacadesBeforeSGen" AfterTargets="GenerateSerializationAssemblies">
<ItemGroup>
<ReferencePath Include="#(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
<ReferencePath Include="#(_ReflectionOnlyAssembly_Names->'%(OriginalIdentity)')" />
</ItemGroup>
<Message Importance="normal" Text="Adding back DesignTimeFacades from ReferencePath now that SGen has run." />
</Target>
</Project>
In my case, this error was due not to an invalid combination of x86 / x64 settings, but due to trying to build a project targeting a specific .NET framework version (v4.5.1) whose reference assemblies had not been installed on the build server.
The combination of the following two conditions was responsible for the error:
In Visual Studio, on the Project Properties page, on the Application tab, the "Target framework" was set to ".NET Framework 4.5.1";
On the build server, in folder C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework, a folder named v4.5.1 was not present. (Other folders with version numbers, including v3.5, v4.0, and v4.5, were present.)
The fix was to install Windows Software Development Kit (SDK) for Windows 8.1 on the build server. In the install wizard, in the "Select the features you want to install" step, I unchecked all boxes except for the one for ".NET framework 4.5.1 Software Development Kit".
Running that install caused the missing v4.5.1 folder in the Reference Assemblies\Microsoft\Framework.NETFramework folder to be created, and the build to run successfully.
Per one of the comments in the accepted answer by #james-white the following worked for me:
Chagnge: GenerateSerializationAssemblies property in the project file from 'On' to 'Auto'
Wanted to pull this suggestion into an answer to make it more obvious to anyone just skimming through. Thank you James White
I had this same issue and viewing the output screen gave me more details. From that I found the Target Framework was higher than was allowed for this type of project (I was building a SQL Server CLR project). The target framework in the project was set to 4.0. Changing this back to 3.5 fixed the issue for me.
Dave
I was having a similar problem, seeing the SGEN "incorrect format" error when building in VS or MSBuild from command line. My project is x64, but MSBuild insisted on using the 32-bit version of the tool. (Some of my peers work around this by building in VS 2015, but I have only VS 2017 installed and want to keep it that way.)
Looking at the diagnostic build output, it looks like SGEN is running from the directory named by its SdkToolsPath parameter (for me: C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\). This is assigned from TargetFrameworkSDKToolsDirectory. Looking at the targets files, this comes from SDK40ToolsPath. And that is set from MSBuild's .config file.
I resolved this by editing C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe.config (requires Admin privilege), setting the SDK40ToolsPath property using
<property name="SDK40ToolsPath" value="$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\NETFXSDK\4.6.2\WinSDK-NetFx40Tools-x64', 'InstallationFolder', null, RegistryView.Registry32))" />
(Note: If you're looking for this path in the registry on a 64-bit OS, go to HKLM\SOFTWARE\WOW6432Node\Microsoft...)
The main change is, of course, x86 to x64 to use the 64-bit tools. I also changed the framework to be what we use (4.6.2). This may mean we can reliably only use tools for 64-bit projects and for this framework, with this change in place. Still, I hope this might help someone running into this issue. (I'm shocked and dismayed MSBuild doesn't automatically change the tools path based on Framework & Architecture.)
I upgraded a project from 4.0 to 4.5.2 and installed the Microsoft .NET Framework 4.5.2 Developer Pack on the build server. After that it worked. You have developer pack for all the other .net versions.
https://support.microsoft.com/en-us/help/2901951/the-microsoft--net-framework-4-5-2-developer-pack-for-windows-server-2
In my case, the solution compiled correctly in Debug, but there was a Release error in only one project.
Using this https://social.msdn.microsoft.com/Forums/en-US/13d3cc7a-88dc-476c-8a15-fa2d4c59e5aa/sgen-an-attempt-was-made-to-load-an-assembly-with-an-incorrect-format?forum=netfx64bit, I changed the project PlatformTarget who was with x86 problems for Any CPU.
I maintained the Solution with Mixed Platform and it was possible to compile in Release
In VS2022 it helped to set the following property of the project:
GenerateSerializationAssemblies: Auto
It failed when
GenerateSerializationAssemblies: On
This worked for me on Visual Studio 2017:
I changed one of my Project's Platform to x64
then I was getting this error while PUBLISH (Not Run)
If this is your case:
Go to Publish Settings
Change Configuration Strictly from Any CPU to Release-x64 (or whatever)
Then the error while publish disappears.

Categories

Resources