Application runs in debugging but publishing fails - c#

I have created solution with two projects:
Project1.csproj (using C#):
<PropertyGroup>
<TargetFrameworks>net7.0-maccatalyst;net7.0-ios;net7.0-android</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<OutputType>Exe</OutputType>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Smanager\Smanager.vbproj" />
</ItemGroup>
Project2.csproj (using visual basic):
<PropertyGroup>
<RootNamespace>Smanager</RootNamespace>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
Everything runs perfectly in debugging and release, my application works perfectly fine and breakpoints in both projects are triggered. However once I am trying to Publish my app, I am getting an error below. Before adding Project2, everything was also working fine and publishing succeeded every time. What might be wrong and how to fix it? I have already tried to clean solution, restart VS, rebuild, delete hidden .vs folder, set projects to build separately in solution properties, reinstall VS.
This is an output of publishing attempt:
1>1 of 2 projects are up-to-date for restore.
1>Cannot resolve Assembly or Windows Metadata file 'C:\Users\...\bin\Release\net7.0\Smanager.dll'
1>Metadata file 'C:\Users\...\bin\Release\net7.0\Smanager.dll' could not be found
========== Publish: 0 succeeded, 1 failed, 0 skipped ==========
========== Elapsed 00:18.234 ==========
========== Package: 0 succeeded, 1 failed ===========

Answer to this is to delete publishing profile. Even thought it is similar, just go to:
Your Startup project
Properties
PublishProfiles
Right click and delete all existing profiles
Clean solution
Start Publishing from the start

Related

Adding reference to another executable with ReferenceOutputAssembly=false doesn't copy dependencies

I have a solution with several executables in it (say, MainApp.exe and Tool.exe).
The main goal is to ensure that the tool (Tool.exe) with its dependencies is copied to the main executable directory during build.
I used the advice from here, and it seemed to work with the older Visual Studio version (at least with some version prior to 16.8).
My project structure (simplified) looks like this:
Solution.sln
├ MainApp.csproj
├ Tool.csproj
| └ App.config
└ ToolLib.csproj
Tool project contains App.config file, and references ToolLib project.
My MainApp.csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Tool/Tool.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Targets>Build;DebugSymbolsProjectOutputGroup</Targets>
</ProjectReference>
</ItemGroup>
</Project>
After upgrading to 16.8 after the compilation the file Tool.exe was indeed copied to the output directory, but neither its dependency ToolLib.dll nor Tool.config was copied to the output directory any more.
Is this a bug or intended behaviour? What is the proper way to ensure that the whole Tool with all the needed dependencies is copied to the MainApp's output dir?
Added test project reproducing the problem here: https://github.com/vladd/ReferenceOutputAssembly
What you gave is too old and it is not suitable for VS2019. And all your projects target to net core 3.1. I have tested your project both in VS2019 16.8 , VS2019 16.7, even 16.6 which all act the same behavior as you described. Only contain the Tool.dll and Tool.exe.
So I wonder why you said before that the result of the build of ToolLib will be printed in the main project.
Actually, <ReferenceOutputAssembly>false</ReferenceOutputAssembly> will prevent the most main output files of the referenced project and its dependency project being copied into the main project.
Suggestion
You have to set it as true:
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
If you want to not copy ToolLib.pdb and Tool.pdb files into the main project, you could add these node on MainApp.csproj file:
<PropertyGroup>
<AllowedReferenceRelatedFileExtensions>*.pdb;.dll.config</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
If you also want to copy pdb files, you should add .pdb under AllowedReferenceRelatedFileExtensions.
<AllowedReferenceRelatedFileExtensions>.pdb;.dll.config</AllowedReferenceRelatedFileExtensions>
Update 1
I tried your suggestion but with it the files Tools.deps,json and
Tool.runtimeconfig.json are not copied, so running the tool fails.
Add this on MainApp.csproj file:
<PropertyGroup>
<AllowedReferenceRelatedFileExtensions>.pdb;.dll.config;.runtimeconfig.dev.json;.runtimeconfig.json</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>

Cannot resolve "An assembly specified in the application dependencies manifest was not found" error

I'm trying to publish my C# project to an executable in order to distribute it. However, I've referenced 'Interop.IWshRuntimeLibrary' and since including it, my project publishes but then crashes on execution with:
An assembly specified in the application dependencies manifest was not found:
package: 'Interop.IWshRuntimeLibrary', version: '1.0.0.0'
path: 'Interop.IWshRuntimeLibrary.dll'
So far I have tried:
Setting the Copy Local and Embed Interlop Types properties for Interop.IWshRuntimeLibrary to every combination of true/false.
Setting the below tag to true/false in the .csproj file.
<PublishWithAspNetCoreTargetManifest>
Installing the System.Runtime.InteropServices NuGet package.
My .csproj file currently looks like this:
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Project</RootNamespace>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary.dll">
<Guid>f935dc20-1cf0-11d0-adb9-00c04fd58a0b</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<WrapperTool>tlbimp</WrapperTool>
<Lcid>0</Lcid>
<Isolated>false</Isolated>
</COMReference>
</ItemGroup>
Other references in the project, like to Newtonsoft work fine. I've consulted every thread I can find across the web pertaining to this. The closest I came to another thread describing my problem was Could not load file or assembly Interop.IWshRuntimeLibrary? but I found no useful info there either.
Ideally, I want to just click publish and publish to a folder on my desktop - preferably as the single .exe but the whole folder is fine if it works. I am unaware if I am perhaps missing a step somewhere as I've never used the publish function before. I'm at a loss for what to try next. Thanks.
How are you publishing at the moment?
You should be able to run the publish command with a flag to tell it to publish as a single file :
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true
More info here : https://dotnetcoretutorials.com/2019/06/20/publishing-a-single-exe-file-in-net-core-3-0/
But as for your particular issue. When publishing as a single file (Which you may already be doing), there is some level of treeshaking involved to try and limit which dependencies it's publishing. In some cases, if you are referencing a library that is loaded using reflection or similar, then ILLinker doesn't know that it's actually being referenced and used.
To get around this, you can add to your csproj file the following :
<ItemGroup>
<TrimmerRootAssembly Include="Interop.IWshRuntimeLibrary" />
</ItemGroup>
Then publish your project like so :
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
More info on how ILLinker works here : https://dotnetcoretutorials.com/2019/06/27/the-publishtrimmed-flag-with-il-linker/

project.assets.json not found with msbuild

I have an ASP.NET Core application that i wish to build on a jenkins machine with MSBuild 15.
When i try to build i get the following error:
C:\Program Files\dotnet\sdk\2.1.502\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,
5): error NETSDK1004: Assets file 'C:\sync\Src\Util\myUtil\ob
j\project.assets.json' not found. Run a NuGet package restore to generate this file
I understand that i need to do nuget restore somehow, but i failed to make it work.
My build process:
Running a batch filed with the following command:
call "%VS150COMNTOOLS%VsDevCmd.bat"
MSBuild DailyBuild.proj /t:DailyBuild /p:VersionNumber=%2 /l:FileLogger,Microsoft.Build.Engine;logfile=Build.log
The DailyBuild.proj file look like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SourcesPath>$(MSBuildProjectDirectory)\..\..\</SourcesPath>
<CSCleanProperties>BuildType=Clean;Configuration=Release;IsFormalBuild=true</CSCleanProperties>
<CSBuildProperties>BuildType=ReBuild;Configuration=Release;PauseBuildOnError=false;PublishWebSites=true;VersionName=myProd-$(VersionNumber)</CSBuildProperties>
</PropertyGroup>
<Target Name="DailyBuildWithClean">
<MSBuild Projects="$(MSBuildProjectDirectory)\Make.proj" Targets="Clean" Properties="$(CSCleanProperties)"/>
<MSBuild Projects="$(MSBuildProjectDirectory)\Make.proj" Properties="$(CSCleanProperties)"/>
<MSBuild Projects="$(MSBuildProjectDirectory)\Make.proj" Targets="FormalBuild" Properties="$(CSBuildProperties)"/>
</Target>
<Target Name="DailyBuild">
<MSBuild Projects="$(MSBuildProjectDirectory)\Make.proj" Targets="SW;PreparePackFolder" Properties="$(CSBuildProperties)"/>
</Target>
</Project>
The Make.proj is a proj file containing definitions for many applications to be built, one of them is my ASP.NET Core app.
How do i fix this problem? thank you.
SOLUTION EDIT:
Thanks to solution by Martin Ullrich:
Added in the DailyBuild.proj the target Restore, also added in the Make.proj a target called restore as suggested
(IE:
<Target Name="Restore">
<MSBuild Projects="$(SourcesPath)\my.sln" Targets="Restore" />
</Target>
)
Add -r (-restore//Restore) to your MSBuild command to trigger a restore before the main build.
The restore parameter will build the Restore target, clear internal caches and then run the rest of the build as specified.
Since you build a custom MSBuild project, you then need to add a Restore target to it:
<Target Name="Restore">
<MSBuild Projects="$(SourcesPath)\my.sln" Targets="Restore" />
</Target>
(or alternatively add another Restore target on the make.proj file and forward it from there to the solution or individual projects that you need to be restored)
Be careful using Restore Nuget packages directly in MS build task configuration.
This option is deprecated, as mentioned here for Azure DevOps. (However, I am not sure how context-dependent that is.)
(Important) This option is deprecated. Make sure to clear this checkbox and instead use the NuGet Installer build step.
Source Link: MSBuild
However, I already used that step (in TFS), so this obviously would not fix it for me.
I tried removing the packages-folder in Source Control Explorer as mentioned here, but that did not fix it either.
Inspired by this, I upgraded the TFS NuGet Installer build step to use Nuget 4.0 (in "Advanced" options), and that did fix it. (Maybe in combination with the removal of the packages-folder?)
Simply rebuild your project in another location(directory/folder ) and run your solution it works 100%.

Visual Studio 2017 for Mac failing simple new project. How to fix?

Using the botnet command:
dotnet new console -o myApp
cd myApp
then,
donet run
I get:
Hello World!
as I should!
However, When I open Visual Studio 2017 Community Edition for Mac and add the myApp project and click 'Run Item', I get:
The other projects in the solution work fine and they are also console apps. Here is the project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
</Project>
I have recreated the project in Visual Studio and get the same behavior. The various things I've read online are very obscure. None of the words in the warning and error mean anything and the "make sure the same settings..." without telling what is meant is meaningless. I've looked at the dotnet-runtime... and again, meaningless. It's talking about deploying applications. Why would creating a new project for Hello World behave like this? What to do to solve the problem?
try adding this
<PropertyGroup>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
</PropertyGroup>
If this does not works, then
<PropertyGroup>
<RuntimeFrameworkVersion>2.2.0</RuntimeFrameworkVersion>
<PlatformTarget>AnyCPU</PlatformTarget>
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
</PropertyGroup>

How do I get .NET Core projects to copy NuGet references to the build output?

I'm trying to write a plugin system with .NET Core, and one of my requirements are to be able to distribute the plugin DLL along with its dependencies to the user for install.
However, I can't figure out how to include my NuGet dependencies as a build artifact and have them output to the build folder, without having to use dotnet publish as a hack. Is there some way I can specify this in the .csproj file (project file)?
You can add this to a <PropertyGroup> inside your csproj file to enforce copying NuGet assemblies to the build output:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
However, note that the build output (bin/Release/netcoreapp*/*) is not supposed to be portable and distributable, the output of dotnet publish is. But in your case, copying the assemblies to the build output is probably very useful for testing purposes. But note that you could also use the DependencyContext api to resolve the DLLs and their locations that are part of the application's dependency graph instead of enumerating a local directory.
You can use PostBuildEvent to automate module deployment on build.
To get NuGet assemblies in build folder add in csproj of your module
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
Define what module files you want where using Include/Exclude (modify path as necessary)
<ItemGroup>
<ModuleFiles
Include="$(TargetDir)*.dll"
Exclude="$(TargetDir)System*.dll;$(TargetDir)Microsoft*.dll"
DestinationPath="$(SolutionDir)src\MyProject\Modules\MyModule\%(Filename)%(Extension)">
</ModuleFiles>
</ItemGroup>
Reset your build folder to default and add PostbuildEvent
<Target Name="PublishModule" AfterTargets="PostBuildEvent" Inputs="#(ModuleFiles)" Outputs="#(ModuleFiles->'%(DestinationPath)')">
<WriteLinesToFile File="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
<Copy SourceFiles="#(ModuleFiles)" DestinationFiles="#(ModuleFiles->'%(DestinationPath)')" />
<Delete Files="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
</Target>
I'm including app_offline to recycle app if it's already running to avoid file in use errors.
Adding
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
didn't work, but adding this to the Framework .csproj file:
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
did.
I am using .NET 5 and here is my solution to my similar issue.
Structure:
Project-A (Contained Selenium Nuget References, and selenium code)
Project-B (A unit test project, which calls methods in Project-A)
Issue:
When building the solution, the chromedriver.exe file was appearing in the Project-A bin folder, but would not get copied to the Project-B bin folder, so the unit tests could not execute. An exception was thrown saying chromedriver.exe was not found.
Solution:
Modify the attribute in Project-A for the Selenium ChromeDriver NuGet package reference to only consider 'contentfiles;analyzers' as private assets. The default value for this is 'contentfiles;analyzers;build' when not specified. This now means it is okay to flow the output files of the build to parent referencing projects, but not contentfiles or analyzers, where as 'build' was also previously considered a private asset and would not flow through to parent projects.
Before (in Project-A.csproj):
<ItemGroup>
<PackageReference Include="Selenium.Support" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="87.0.4280.8800" />
</ItemGroup>
After (in Project-A.csproj):
<ItemGroup>
<PackageReference Include="Selenium.Support" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="87.0.4280.8800">
<PrivateAssets>contentfiles;analyzers</PrivateAssets>
</PackageReference>
</ItemGroup>
I found this information in this link:
https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-assets
Hope this helps someone! Good luck.
I "solved" (created work around) this in simpler way.
In post build
dotnet publish "$(ProjectFileName)" --no-build -o pub
xcopy "$(ProjectDir)pub\3rdPartyProvider.*.dll" "$(OutDir)"
pub is the folder where you want your published stuff go for staging
NOTE: depending on what version of dotnet.exe you use, command --no-build may not be available.
For example, not available in v2.0.3; and available in v2.1.402. I know that VS2017 Update4 had v2.0.3. And Update8 has 2.1.x
Update:
The setup above will work in the basic debug environment but to put it into build server/production environment more is needed. In this particular example that I had to solve, we build Release|x64 and Release|x86 separately. So I accounted for both. But to support the post build dotnet publish command, I first added RuntimeIdentifier to project file.
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\lib\</OutputPath>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<OutputPath>..\..\lib\</OutputPath>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>
Why I needed it and why you can get away without it? I needed this because my build program is set to intercept warning MSB3270, and fail the build if it appears. This warning says, "hey, some files in your dependencies are of wrong format". But do you remember the goal of this exercise? We need to pull package dependency DLLs. And in many cases it doesn't matter if this warning is there because following post build does not care. Again, this is my build program that cares. So, I only added RuntimeIdentifier to 2 configurations I use during production build.
Full Post build
if not exist "$(ProjectDir)obj\$(ConfigurationName)" mkdir "$(ProjectDir)obj\$(ConfigurationName)"
xcopy "$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)" "$(ProjectDir)obj\$(ConfigurationName)" /E /R /Y
if $(ConfigurationName) == Release (
dotnet publish "$(ProjectFileName)" --runtime win-$(PlatformName) --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
) else (
dotnet publish "$(ProjectFileName)" --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
)
xcopy "$(ProjectDir)pub\my3rdPartyCompany.*.dll" "$(OutDir)" /Y /R
Explanation: dotnet publish is looking for obj\Debug or obj\Release. We don't have it during the build because build creates obj\x64\Release or obj\x86\Release. Line 1 and 2 mitigate this issue. In line 3 I tell dotnet.exe to use specific configuration and target runtime. Otherwise, when this is debug mode, I don't care about runtime stuff and warnings. And in the last line I simply take my dlls and copy then into output folder. Job done.
In conjunction with the above answer:
I've got this working great in the Post-build event command line: in Visual Studio.
It loops over a selection of dlls (System*.dll and Microsoft.dll)*, and then skips the deletion of specific dlls. System.Data.SqlClient.dll and System.Runtime.Loader.dll
for %%f in ($(OutDir)System*.dll $(OutDir)Microsoft*.dll) do if not %%f == $(OutDir)System.Data.SqlClient.dll if not %%f == $(OutDir)System.Runtime.Loader.dll del %%f

Categories