Filter CopyLocalLockFileAssemblies output - c#

I set CopyLocalLockFileAssemblies to true and want to filter the output. So I used the following code:
<Target Name="FilterCopyLocalItems" AfterTargets="ResolveLockFileCopyLocalProjectDeps">
<ItemGroup>
<ReferenceCopyLocalPaths Remove="#(ReferenceCopyLocalPaths)" Condition="'%(Filename)' == 'Microsoft.Extensions.DependencyInjection.Abstractions'" />
</ItemGroup>
</Target>
But this code did not work, how can I put a filter on the output?

Your target FilterCopyLocalItems is to remove the reference dll from the output folder.
I wonder if you means that the target cannot be executed.
For me, I used the below xml code in my net core project which installed the nuget package Microsoft.Extensions.DependencyInjection.Abstractions.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<Target Name="FilterCopyLocalItems" AfterTargets="ResolveLockFileCopyLocalProjectDeps">
<ItemGroup>
<ReferenceCopyLocalPaths Remove="#(ReferenceCopyLocalPaths)" Condition="'%(Filename)' == 'Microsoft.Extensions.DependencyInjection.Abstractions'" />
</ItemGroup>
</Target>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.6" />
</ItemGroup>
</Project>
You can find the target under the Detailed output build log.
Enter Tools-->Options-->Projects and Solutions-->Build and Run-->set MSBuild project build output verbosity to Detailed.
And you can see the target by searching its name under the detailed output log while you build it.
It will prevent the Microsoft.Extensions.DependencyInjection.Abstractions.dll being generated in the output folder.
Update 1
Actually, you may do some extra operation which causes the target ResolveLockFileCopyLocalProjectDeps not to be triggered. Due to the lack of your detailed project structure and CSPROJ file, I did not notice that.
For your situation, the target ResolvePackageDependenciesForBuild works well.
So in your side, you should use this:
<Target Name="FilterCopyLocalItems" AfterTargets="ResolvePackageDependenciesForBuild">
<ItemGroup>
<ReferenceCopyLocalPaths Remove="#(ReferenceCopyLocalPaths)" Condition="'%(Filename)' == 'Microsoft.Extensions.DependencyInjection.Abstractions'" />
</ItemGroup>
</Target>
Besides, when you execute the target, please do not add <ExcludeAssets>Runtime</ExcludeAssets> under the PackageReference of your nuget package, its effect is actually the role of your target FilterCopyLocalItems. At runtime, remove the related package.dll in the output folder. See this document.
So you should delete it to avoid reuse.

Related

Extract git branch name while building C# project

While building the C# project locally/CI server, I wanted to control the NuGet package reference in the .csproj file. If the developer is building a C# project on github master branch (locally/CI server) I would like to add RC build NuGet package reference otherwise PRE releases NuGet package reference. How to do this? Can someone please assist me?
Some thoughts like -
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<GitBranch>$(GitBranch.Trim())</GitBranch>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GitInfo" Version="2.2.0" />
</ItemGroup>
<Choose>
<When Condition="$(GitBranch) == 'master'">
<ItemGroup>
<PackageReference Include="Data.Account.Domain.Messaging" Version="1.0.0-rc*" IncludePrerelease="true" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="Data.Account.Domain.Messaging" Version="1.0.0-pre*" IncludePrerelease="true" />
</ItemGroup>
</Otherwise>
</Choose>
</Project>
You could read the git branch from the .git/HEAD file. Naive implementation like
<PropertyGroup>
<GitBranch>$([System.IO.File]::ReadAlltext('$(MsBuildThisFileDirectory)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
</PropertyGroup>
You might want to adjust how you get the path to that file, and perhaps use something more robust (e.g. if you just checkout a random commit in git, the file won't contain a branch name but a commit SHA)
You could also use variable $(GitRoot) from GitInfo itself to build the path, just a small adaption to the existing code but helped for my case where I had to deal with nested folders.
<PropertyGroup>
<GitBranch>$([System.IO.File]::ReadAlltext('$(GitRoot)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
</PropertyGroup>

How to Remove local nuget references

I added realm package to my project and it works fine but for some reason it also added some not valid local dependencies which i cannot remove. I tried to remove them manually from csproj file but there is no trace of them. How can i get rid of them?
You have added RuntimeIdentifier xml node on csproj file on a non-sdk net framework project.
That is the cause. And you should note that RuntimeIdentifier works for new sdk net core cross-platform project rather than your non-sdk net framework windows project.
RuntimeIdentifier does not work for non-sdk net framework projects.
So you have to remove these on csproj file.
<PropertyGroup>
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
</PropertyGroup>
When I remove it, all work well.
Update
It is a well-known issue which I have reported before.
The problem is here:
C:\Users\xxx\.nuget\packages\realm\10.1.1\build\Realm.props and then open that file, you will see:
You have two points which needed to care:
1) NativeReference works for ios apps rather than android apps, actually, you could just delete the NativeReference node but for the inclusiveness and comprehensiveness of the nuget package, it is not advisable to delete it.
2) NativeReference cannot recognize the value of MSBuild property. You can't pass a property value in there. Just as my link hinted.
First of all, the itemgroup condition will indeed be processed by vs according to the conditions when it is built, but when it is not built, it will ignore the condition to check its content to determine whether it is valid, but because your Android project has not been able to recognize the nativereference , So the problem has always existed.
In order to skip this detection mechanism, you'd better use choose, when. And in this scenario, you are using an Android project, so there is no need to consider the problem that the nativereference cannot identify the property.
Suggestion One
modify the Realm.props to:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_RealmNugetNativePath Condition="'$(_RealmNugetNativePath)' == ''">$(MSBuildThisFileDirectory)..\native\</_RealmNugetNativePath>
</PropertyGroup>
<Choose>
<When Condition="'$(TargetFrameworkIdentifier)' == 'Xamarin.iOS'">
<ItemGroup>
<NativeReference Include="$(_RealmNugetNativePath)ios\universal\realm-wrappers.framework">
<Kind>Framework</Kind>
<SmartLink>False</SmartLink>
</NativeReference>
</ItemGroup>
</When>
<When Condition="'$(TargetFrameworkIdentifier)' == 'Xamarin.Mac'">
<ItemGroup>
<NativeReference Include="$(_RealmNugetNativePath)..\runtimes\osx-x64\native\librealm-wrappers.dylib">
<Kind>Dynamic</Kind>
</NativeReference>
</ItemGroup>
</When>
</Choose>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'Xamarin.iOS'">
<Content Include="$(_RealmNugetNativePath)ios\Realm.dll.config">
<Link>Realm.dll.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'MonoAndroid'">
<AndroidNativeLibrary Include="$(_RealmNugetNativePath)android\armeabi-v7a\librealm-wrappers.so">
<Link>$(_RealmNugetNativePath)android\armeabi-v7a\librealm-wrappers.so</Link>
</AndroidNativeLibrary>
<AndroidNativeLibrary Include="$(_RealmNugetNativePath)android\x86\librealm-wrappers.so">
<Link>$(_RealmNugetNativePath)android\x86\librealm-wrappers.so</Link>
</AndroidNativeLibrary>
<!-- 64bit -->
<AndroidNativeLibrary Include="$(_RealmNugetNativePath)android\arm64-v8a\librealm-wrappers.so">
<Link>$(_RealmNugetNativePath)android\arm64-v8a\librealm-wrappers.so</Link>
</AndroidNativeLibrary>
<AndroidNativeLibrary Include="$(_RealmNugetNativePath)android\x86_64\librealm-wrappers.so">
<Link>$(_RealmNugetNativePath)android\x86_64\librealm-wrappers.so</Link>
</AndroidNativeLibrary>
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<None Include="$(_RealmNugetNativePath)..\runtimes\win-x86\native\realm-wrappers.dll">
<Link>lib\win32\x86\realm-wrappers.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(_RealmNugetNativePath)..\runtimes\win-x64\native\realm-wrappers.dll">
<Link>lib\win32\x64\realm-wrappers.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Suggestion Two
2) If you use an IOS app further, you have to try these:
a) delete two NativeReference nodes directly under Realm.props file
b) then add these on ios.csoroj file:
<Choose>
<When Condition="'$(TargetFrameworkIdentifier)' == 'Xamarin.iOS'">
<ItemGroup>
<NativeReference Include="C:\Users\xxx\.nuget\packages\realm\10.1.1\native\ios\universal\realm-wrappers.framework" Kind="Framework" SmartLink="False">
</NativeReference>
</ItemGroup>
</When>
<When Condition="'$(TargetFrameworkIdentifier)' == 'Xamarin.Mac'">
<ItemGroup>
<NativeReference Include="C:\Users\xxx\.nuget\packages\realm\10.1.1\runtimes\osx-x64\native\librealm-wrappers.dylib" Kind="Dynamic">
</NativeReference>
</ItemGroup>
</When>
</Choose>
Right click on your project, select Unload Project.
Select the unloaded project, you'll see a xml file opened.
Look for <ItemGroup> which holds the list of references.
Delete the items that you don't need anymore.
Save the file. Right click on the project and Reload it.

Visual Studio Solution(.sln) / C#: Start a project with another project's dll as parameter

is it possible to run a project with an argument of a dll from another project?
My project structure and dependencies look like this
As you can see there are no direct dependencies between a mod and the game implementation directly.
When I click on Debug -> Start New Instance, F5 or use the button () I want to run ./ExampleGameInEngineA.exe GameModC.dll.
I know that you can set an Executable in the project settings
But I am looking for a more generic way that is automatically compiling ExampleGameInEngineA and putting it in the same directory as GameModC.
Hardcoded directory paths are also not great (tho I could use relative paths for this).
For testing purposes we can safely ignore GameInEngineB but I still don't want any hard references to GameInEngineA.
Okay, I kinda solved it by myself by using a PreBuild-Event-Target:
GameModC.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="">
<MSBuild Projects="$(SolutionDir)ExampleGameInEngineA\ExampleGameInEngineA.csproj..." />
<ItemGroup>
<GameEngineAOutputFolder Include="$(SolutionDir)ExampleGameInEngineA\$(OutDir)*.*" />
</ItemGroup>
<Copy SourceFiles="#(GameEngineAOutputFolder)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="false" />
</Target>
<ItemGroup>
<ProjectReference Include="..\GameApi\GameModdingApi.csproj" />
</ItemGroup>
</Project>
GameInEngineA.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\GameApi\GameModdingApi.csproj" />
</ItemGroup>
</Project>
Please note the AppendTargetFrameworkToOutputPath to remove the netcoreapp3.1 or netstandard2.1.
But there are still problems with the solution:
It does not recognize changes made in ExampleGameInEngineA (manual rebuild required)
The Condition when to add ExampleGameInEngineA is always met (because I have no good idea for a condition)
I am still open for better solutions.

Asp.NET core project fails with NETSDK1061: The project was restored using Microsoft.NETCore.App version

One of my open source projects has just started failing to build with the errror, when previously it used to build successfully (if I trigger a build for a previously successful commit, I still get this error 😢 )
C:\projects\formfactory\FormFactory.AspNetCore.Example\FormFactory.AspNetCore.Example.csproj : error : NETSDK1061: The project was restored using Microsoft.NETCore.App version 2.2.4, but with current settings, version 2.2.1 would be used instead. To resolve this issue, make sure the same settings are used for restore and for subsequent operations such as build or publish. Typically this issue can occur if the RuntimeIdentifier property is set during build or publish but not during restore. For more information, see https://aka.ms/dotnet-runtime-patch-selection.
Full build log here here
The csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>FormFactory.AspNetCore.Example</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>FormFactory.AspNetCore.Example</PackageId>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>
<ItemGroup>
<None Update="wwwroot\**\*;Views\**\*;Areas\**\Views">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FormFactory\FormFactory.csproj" />
<ProjectReference Include="..\FormFactory.AspNetCore\FormFactory.AspNetCore.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.2.0" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="bower install" />
<Exec Command="dotnet bundle" />
</Target>
<ItemGroup>
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.2.301" />
</ItemGroup>
</Project>
from https://github.com/mcintyre321/FormFactory/blob/master/FormFactory.AspNetCore.Example/FormFactory.AspNetCore.Example.csproj
What do I need to do to fix this?
Try removing explicit version from Microsoft.AspNetCore.All package - the version should be determined by the SDK (implicit version), as you're also using TargetLatestRuntimePatch setting. Had similar issues caused when specifying explicit metapackage version version.
Also, you might want to consider swapping it to Microsoft.AspNetCore.App as it is recommended - less 3rd party dependencies. Read more here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/metapackage-app?view=aspnetcore-2.2
I've fixed this by changing my build server environment from VS2017 to VS2019

Antlr not working with VS2017

I am trying to set up a simple project with Antlr in .net core 1.0 project using VS2017.
Following https://github.com/sharwell/antlr4cs, added .g4 file to the project. The project file looks like this,
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework> </PropertyGroup>
<ItemGroup>
<None Remove="Calculator.g4" /> </ItemGroup>
<ItemGroup>
<PackageReference Include="Antlr4" Version="4.5.4-beta001" /> </ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Calculator.g4" />
</ItemGroup>
</Project>
But the document says,
Locate an existing XML element according to the MSBuild Property
column in the table above, or add one if it does not already exist.
For example, to generate both the parse tree listener and visitor
interfaces and base classes for your parser, update the project item
to resemble the following.
<Antlr4 Include="CustomLanguage.g4">
<Generator>MSBuild:Compile</Generator>
<CustomToolNamespace>MyProject.Folder</CustomToolNamespace>
<Listener>True</Listener> <Visitor>True</Visitor> </Antlr4>
There is no any Antlr4 tag in this proj file. Is Antlr not supported in VS2017?
is tehre a good example I can follow to use ANtlr with .net core?
This is simply all I need in my .NET Standard 1.3 class library project to hold the grammar file.
<ItemGroup>
<Antlr4 Include="Something.g4">
<Generator>MSBuild:Compile</Generator>
<Listener>False</Listener>
<Visitor>False</Visitor>
</Antlr4>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Antlr4" Version="4.6.1-beta001" />
</ItemGroup>
Note that you might use a newer Antlr4 package version as 4.6.1 was the only version available when this answer was created.
I was just looking for the same thing, for .NET Core 2.0.
The current ANTLR4 package version is 4.6.5 Beta 1. In this version the C# generator was ported to C# so the dependency to Java was removed. This is still experimental and has to be enabled manually with :
<Antlr4UseCSharpGenerator>True</Antlr4UseCSharpGenerator>
Files aren't generated when a .g4 file is modified. They will be generated when dotnet build is called.
File globbing works as expected BUT changing settings like <Visitor>false</Visitor> requires a call dotnet clean before dotnet build.
The default Antlr task options can be found in the source :
<Antlr4>
<Generator>MSBuild:Compile</Generator>
<CustomToolNamespace Condition="'$(Antlr4IsSdkProject)' != 'True'">$(RootNamespace)</CustomToolNamespace>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<Encoding>UTF-8</Encoding>
<TargetLanguage>CSharp</TargetLanguage>
<Listener>true</Listener>
<Visitor>true</Visitor>
<Abstract>false</Abstract>
<ForceAtn>false</ForceAtn>
</Antlr4>
Globbing works, so if I want to build all g4 files and disable visitors, all I have to write is :
<ItemGroup>
<Antlr4 Include="**/*.g4" >
<Visitor>false</Visitor>
</Antlr4>
</ItemGroup>
My entire csproj file looks like this :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Antlr4UseCSharpGenerator>True</Antlr4UseCSharpGenerator>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Antlr4">
<Version>4.6.5-beta001</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Antlr4 Include="**/*.g4" >
<Visitor>false</Visitor>
</Antlr4>
</ItemGroup>
</Project>

Categories