I have read in the documentation that if I want to compile using AoT (ahead of time) I have to add this settings in the .csproj file of the application.
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
But I have another property group, is this:
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
So my doubt if I have to create a new prperty group or I can set the setting in the existing propery gorup, for example below UseWPF.
Thanks.
It does not matter if you have one or multiple PropertyGroup elements. Normally you would only create more than one if you either want to separate elements explicitly or you want them only used depending on (e. g.) the current configuration. In that case you would annotate them like this:
<PropertyGroup Condition="'$(Configuration)' == 'DEBUG'" >
<OutputPath>$(OutputPath)\debug</OutputPath>
</PropertyGroup>
Related
this is my .csproj file and I want to use the custom class to build the version number I need.
for example:
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
<Deterministic>false</Deterministic>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<myver>$([myClass]::get_myVersion())</myver>
<Version>$(myver)</Version>
</PropertyGroup>
<ItemGroup>
<Reference Include="myClass">
<HintPath>..\lib\myClass.dll</HintPath>
</Reference>
</ItemGroup>
......
how can I reference myClass to PropertyGroup?
Property functions are supported for a fixed set of known types. You cannot use your own custom type. Custom types are not supported. You can't call the myVersion property getter on your myClass type as a property function.
You can write a custom MSBuild task and invoke your task from within a target. Tasks can be written inline. See "MSBuild inline tasks with RoslynCodeTaskFactory".
A note on Assembly attribute properties: The $(Version) property, if set, may be used to set the values of the $(AssemblyVersion) and $(FileVersion) properties.
I removed my IsExternalInit definition, as we are now using .net 5.0:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>
However I still get this error
CS0518 Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported
In files like this
public sealed record TestDTO
{
public string SomePropert{ get; private init; } = default!; // error occurs here
}
I can see this is expected behaviour when targeting older frameworks, but shouldn't it work in my case? What am I doing wrong?
I think this is happening because one of the projects I reference has a dependency on some library using .net standard
To avoid adding IsExternalInit.cs to every project, I just added one to the solution root folder and also added a file called Directory.Build.Props with these contents
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)IsExternalInit.cs" Visible="false" />
</ItemGroup>
</Project>
I'm learning C#. (sorry I'm not native English speeker.)
I'm creating multi platform library in dotnet core.
I want to switch platform in one method.
I tryed RuntimeInformation.IsOSPlatform() then successed I want to do.
I heard that I can change the code to be executed for each OS by the property of project.csproj.
but I couldn't do that.
I want to do this.
project.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>MemoryInfo</PackageId>
<Version>1.0.0</Version>
<Authors>foobar</Authors>
<Company>foobar</Company>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
//(add comment) Switch Native Code
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<Compile Include="Linux/native.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsLinux)' == 'true'">
<Compile Include="Windows/native.cs" />
</ItemGroup>
</Project>
Program.cs
~~
public long GetMemorySize() //library method
{
NativeMemoryinfo mem = new NativeMemoryinfo();
return mem.GetMemorySize(); //access to each platform code
}
~~
Linux/native.cs
~~
class NativeMemoryinfo
{
public long GetMemorySize()
{
Code for Linux(/proc/meminfo...)
}
}
~~
Windows/native.cs
~~
class NativeMemoryinfo
{
public long GetMemorySize()
{
Code for Windows(Kernel32....)
}
}
~~
Maybe, I think I'm misunderstood or in the wrong way.
Can I do this way?
my research, I found something called "interop" this, but what is the relationship with this?
Thank you.
The feature you are trying to use with csproj is normally used to target the different frameworks in .NET, not to target different OS. See this: https://learn.microsoft.com/en-us/dotnet/standard/frameworks
What you are trying to do can be achieved by interfaces. Have an interface INativeMemoryinfo and initialize it to the windows or linux version based on if (RuntimeInformation.IsOSPlatform() == "").
Side note: since you are working o a library, I suggest using .net standard instead of .net core.
if (RuntimeInformation.IsOSPlatform() == "").
I have these build configurations:
These platform configurations:
And these compiler conditionals:
NET40
NET45
My solution is a huge API that consists in 20 solutions, some of those solutions consumes Async keywords and other beneffits that are available only from .NetFx 4.5.
That part of the code I have it in a conditional in this way:
#If NET45 then
Sub Async
...
End Sub
#Else
Sub
...
End Sub
#End If
Then, what I'm trying to do is clear, the .NetFx 4.5 build configurations should compile the block of the NET45 conditional, and the .NetFx 4.0 build configurations should compile the block of the #Else part.
The problem I found is that if I change the application target framework in the project settings, the change persist in all the other build configurations, and I would like to avoid that persistance.
So how I can do this?.
Note:
I marked this question with the C# tag because is a general Visual Studio environment question, but I will clarify that my solutions are written in Vb.Net, because I know there are some big differences between the C# project settings and also their compiler params so maybe a C# advanced answer could not help me.
My suggestion is to get rid of conditional statements in code by moving platform/target/etc sencitive code in partial files. Then I would go to project file and would make the icluded files sensitive on particular condition using all the fuctionality ms-build provides
Example:
Create brand new VB Console App in Visual Studio
add three class files ClassDotNetFeatures40.vb, ClassDotNetFeatures45.vb, GenericClass.vb
Add the following code
in GenericClass.vb
Partial Public Class GenericClass
Public Sub Hello()
Console.Write("Hello ")
End Sub
End Class
in ClassDotNetFeatures40.vb
Partial Public Class GenericClass
Public Sub Word()
Console.Write("4.0 Word!")
End Sub
End Class
in
ClassDotNetFeatures45.vb
Public Class GenericClass
Public Sub Word()
Console.Write("4.5 Word!")
End Sub
End Class
Put the following code in Module1.vb
Sub Main()
Dim o = New GenericClass()
o.Hello()
o.Word()
End Sub
Save all
Right click on your solution and press Unload Project
Right click on the project file and press Edit Project
Find the following lines:
<Compile Include="ClassDotNetFeatures40.vb" />
<Compile Include="ClassDotNetFeatures45.vb" />
and replace them with
<Compile Condition="'$(Configuration)' == 'Debug'" Include="ClassDotNetFeatures40.vb" />
<Compile Condition="'$(Configuration)' == 'Release'" Include="ClassDotNetFeatures45.vb" />
press save
right click on project file and press Reload
now when you run the project undo debug you will get:
Hello 4.0 Word!
undo release you willl get:
Hello 4.5 Word!
You will need to change project files manually (I've played with csproj - hopefully vbproj works in the same way).
All project configurations properties described in the sections like this one:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
</PropertyGroup>
Please notice Condition statement - that describes that this particular property set specified for Debug, AnyCPU configuration.
What you need to do is to move TargetFrameworkVersion property from general top level to configuration-specific levels, something like this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<!-- general properties here - removing framework related... -->
<!--<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>-->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<!-- Use 4.0 for Debug -->
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<!-- other properties here... -->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<!-- Use 4.5 for Release -->
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<!-- other properties here... -->
</PropertyGroup>
Please notice that VS.Net GUI does NOT support this, and will not display correct values in the project Properties window; though it will use these values for build.
Depending on complexity of your solution, you might found some other artifacts, as VS.Net will not reload project properly, but at least that should work with build from console.
Additionally, you might need to use similar conditional "hacks" to reference correct libraries.
I'm trying to copy multiple files from a deep source tree that have the same file name. For example TestResults.trx. I want to copy them into a single directory (i.e. flattened). Problem is they just overwrite each other and I just end up with a single TestResults.trx in the directory.
<ItemGroup>
<SilverlightTestResults Include=".\**\*.trx" Exclude=".\TestResults\*" />
</ItemGroup>
<Copy SourceFiles="#(SilverlightTestResults)" DestinationFolder=".\TestResults">
I thought I could do a transform using some well known metadata but there doesn't seem to be anything unique in there to do it (the test results I'm trying to copy live in directories like this: .\SomeProject\bin\debug\TestResults.trx).
Copying to a directory like this like this would be ideal:
.\TestResults\TestResults1.trx
.\TestResults\TestResults2.trx
.\TestResults\TestResults3.trx
I don't care about the actual names as long as they are unique.
Any ideas, looks like a custom task is required?
I can't provide a solution that just uses msbuild - you could either use msbuildtasks
to use the <Add /> task for incrementing a counter.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<FileCounter>0</FileCounter>
</PropertyGroup>
<ItemGroup>
<MySourceFiles SilverlightTestResults Include=".\**\*.trx" Exclude=".\TestResults\*"/>
</ItemGroup>
<Target Name="CopyFiles">
<Math.Add Numbers="$(FileCounter);1">
<Output TaskParameter="FileCounter" PropertyName="FileCounter" />
</Math.Add>
<Copy
SourceFiles="#(MySourceFiles)"
DestinationFiles="#(MySourceFiles->'.\TestResults\%(Filename)_$(FileCounter)%(Extension)')"
/>
</Target>
However you might do better with a custom task or probably executing a powershell script.
Yes, a custom task will be required.
You could look to see what functionality the Move task from the community task project (link here) offers, but if it doesn't do what you want then it is open source, so it will be trivial to check the source and modify it to suit your needs.