I'm building a project with the following in the CSPROJ file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<PlatformTarget>AnyCPU</PlatformTarget>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>basic_example</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings>
<StartupObject>basic_example.LoopThroughInvalidFileChars</StartupObject>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.14.0" />
</ItemGroup>
</Project>
I'm interested in debugging a source file in this project using Visual Studio 2019. Here are the details:
When I start the project without debugging, it compiles and runs fine. However when I place a breakpoint in my source code and I try to start with debugging, it basically runs my program and never stops at the breakpoint.
In my output window in Visual Studio, the following message appears:
The target process exited without raising a CoreCLR started event. Ensure that the target > process is configured to use .NET Core. This may be expected if the target process did not > run on .NET Core.
The program '[25444] basic-example.dll' has exited with code 0 (0x0).
However, I am intentionally setting the target framework to netstandard2.0. I.e. I would really like to debug it with the current project file.
Why won't Visual Studio allow me to debug this project?
Thanks to #LukeBriner's and #Dai's comments I was able to solve the problem.
As #LukeBriner mentions:
If you want to debug into it as a netstandard library then just create a dotnet core console app and call into the library in a normal way.
So that's what I did.
I had to rename all methods named Main in my class library to something else (I used Run).
I added a console app to the solution adjacent to the class library and added a project reference to the class library.
I imported the class library in my console apps' Program.cs with a using statement. I called the class I wanted to debug in the Main method of Program.cs
I modified the project file of the console application to look like the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>call_basic_example</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\openxml-exceptions\basic-example.csproj" />
</ItemGroup>
</Project>
I modified the project file for the class library to look like the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PlatformTarget>AnyCPU</PlatformTarget>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>basic_example</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.14.0" />
</ItemGroup>
</Project>
I was then finally able to debug into whichever method I wanted in the class library.
Related
MSBuild is strange
I already tried this and another answer and I also tried this one
After that, I changed <IntermediateOutputPath> and <BaseIntermediateOutputPath> and <OutputPath> in the .csproj file but...
It keeps creating this piece of strange stuff in the old obj folder (I don't use nuget)
project.assets.json
project.nuget.cache
project.packagespec.json
...
I have already read about Visual Studio legacy workflow causes this behaviour but do any workarounds exist?
My current .csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<StartupObject>Program</StartupObject>
<IntermediateOutputPath>..\..\obj\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\</BaseIntermediateOutputPath>
<OutputPath>..\..\bin\Build\</OutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="foo\dependency.csproj" />
</ItemGroup>
</Project>
Solved by creating Directory.Build.props file in the root of project with:
<Project>
<PropertyGroup>
<MSBUildProjectExtensionsPath>..\..\obj\</MSBUildProjectExtensionsPath>
</PropertyGroup>
</Project>
Very dirty and non-obvious microsoft-style hack
Found here
Is there any good .NET compiler for windows without penetrating youself?
The issue:
If I change the file extension from the visual studio, the file Build Action will be according to the previous Build Action and not according to the new file extension.
There is a way to enforce the visual studio always takes the Build Action from the file extension?
Example:
Create a new .Net Core 3.1 Class library. There is a single file (Class1.cs) The csproj will be like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
Change the name of Class1.cs to Class1.txt from the visual studio. The result, Class1.txt is with Build Action Compile although it is a text file. The content of csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Remove="Class1.txt" />
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.txt" />
</ItemGroup>
</Project>
Additional information:
I'm using Visual Studio 2019.
If I change the file extension from the file system the issue doesn't appear.
Update:
A possible solution is to change the file Build Action after each file rename, but I want an automatic way.
I have code for a bunch of CLI utilities made to test/showcase a network library. The library is compiled into an assembly - DotNet Core DLL.
I have several CLI examples showing how to use the library, for example, one search is using paging functionality and another returns everything etc. Basically, each is a short standalone CLI program.
I have CS source files and csproj file targeting dotnet core. Below is the configuration:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="mylib>
<HintPath>../../bin/Debug/netstandard2.0/publish/mylib.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
I want to have one executable for each source file e.g. PGSample.cs will get compiled into PGSample.exe etc. How would I about achieving this?
I'm afraid you can have only one output per csproj, but there are some tricks to manage multiple projects easier.
You can put common build settings into a file named Directory.build.props in the root project folder, e.g.:
<Project>
<PropertyGroup>
<Authors>Your name here</Authors>
<Company>Your company</Company>
<Product>The project name</Product>
<Version>1.6.18</Version>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<!-- e.g. bin/Release_net48/foo_cli/ -->
<OutputPath>$(SolutionDir)bin\$(Configuration)_$(TargetFramework)\$(MSBuildProjectName)</OutputPath>
<TargetFrameworks>net48</TargetFrameworks>
</PropertyGroup>
</Project>
Then, add one subdirectory and minimal csproj file per output, e.g.
libfoo/libfoo.csproj: <Project Sdk="Microsoft.NET.Sdk" /> (really, that's it!)
foo_cli/foo_cli.csproj:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><OutputType>Exe</OutputType></PropertyGroup>
<ItemGroup><ProjectReference Include="..\libfoo\libfoo.csproj" /></ItemGroup>
</Project>
Iff you have only one library and a lot of executables, you might even add your executable settings to the Directory.build.props:
[..]
<PropertyGroup Condition=" $(MSBuildProjectName) != 'libfoo'">
<OutputType>exe</OutputType>
</PropertyGroup>
<ItemGroup Condition=" $(MSBuildProjectName) != 'libfoo'">
<ProjectReference Include="..\libfoo\libfoo.csproj" />
</ItemGroup>
I created a task in our C# Projects to auto-version projects when they are built (changes are made) in release mode. The versioning part works perfectly. However, all the projects are being built regardless if the project actually changed when done from command line. This causes projects to be versioned unnecessarily. Building in Visual Studio works, unchanged projects are not built, however we made a tool to do automated build using msbuild.exe and are using this as a temporary fix while we work on Bamboo and that method always does a blind build, even if there are no changes to the project. I need to be able to identify if changes were made to the project.
Something like
'$(wasSourceUpdated)' == 'true' or some kind of target condition to use on my custom versioning target.
Here is a sample of my versioning task in our projects
<Import Project="..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets" Condition="Exists('..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets') And '$(Configuration)|$(Platform)' == 'Release|AnyCPU' And '$(DeployOnBuild)' != 'true'" />
I also checked this and this articles to no avail.
EDIT
I need the task to run before the build is actually executed in order to stamp the generated assemblies with the new versions
EDIT 2
What I'm really looking for is the condition to run CoreCompile or to run CoreCompile again when I detect that the assembly was updated
What I've tried so far:
<Project>
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<_AssemblyTimestampBeforeCompile>%(IntermediateAssembly.ModifiedTime)</_AssemblyTimestampBeforeCompile>
</PropertyGroup>
<PropertyGroup>
<_AssemblyTimestampAfterCompile>%(IntermediateAssembly.ModifiedTime)</_AssemblyTimestampAfterCompile>
</PropertyGroup>
<PropertyGroup>
<_ProjectVersioned Condition="'$(_ProjectVersioned)'==''">false</_ProjectVersioned>
</PropertyGroup>
<Target Name="IncrementVersionBeforeBuild" AfterTargets="CoreCompile" Condition="'$(_AssemblyTimestampBeforeCompile)'!='$(_AssemblyTimestampAfterCompile)' and '$(_ProjectVersioned)' == 'false'">
<Message Text="Before $(_AssemblyTimestampBeforeCompile) After $(_AssemblyTimestampAfterCompile)" Importance="High"/>
<IncrementVersion
ProjectPath="$(MSBuildProjectFullPath)"
VersionRule="3.3.0.+"
FileName="Properties\AssemblyInfo.cs">
</IncrementVersion>
</Target>
<PropertyGroup>
<TaskPath>$(MSBuildThisFileDirectory)..\Tasks\AutoVersionTask\AutoVersionTask\bin\Debug</TaskPath>
</PropertyGroup>
<!-- Sample import for projects
<Import Project="..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets" Condition="Exists('..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets') And '$(Configuration)|$(Platform)' == 'Release|AnyCPU' And '$(DeployOnBuild)' != 'true'" />
-->
<UsingTask AssemblyFile="$(TaskPath)\AutoVersionTask.dll" TaskName="AutoVersionTask.IncrementVersion" />
<PropertyGroup>
<_ProjectVersioned>true</_ProjectVersioned>
</PropertyGroup>
Thanks in advance
So Thanks to Lance for getting me to understand MSBuild to the point that I understand the issue way better.
After a long time researching the default task, I ran upon this question that had the perfect solution to my issue. After applying the fix the versioning task now only runs when changes are made to the msbuild code.
The inputs and outputs are the same as the CoreCompile target and ensures that the task is only run if there were changes to the source
Here is the target I ran that works:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<CoreCompileDependsOn>
$(CoreCompileDependsOn);
IncrementVersionBeforeBuild
</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="IncrementVersionBeforeBuild"
Inputs="$(MSBuildAllProjects);
#(Compile);
#(_CoreCompileResourceInputs);
$(ApplicationIcon);
$(AssemblyOriginatorKeyFile);
#(ReferencePath);
#(CompiledLicenseFile);
#(EmbeddedDocumentation);
$(Win32Resource);
$(Win32Manifest);
#(CustomAdditionalCompileInputs)"
Outputs="#(DocFileItem);
#(IntermediateAssembly);
#(_DebugSymbolsIntermediatePath);
$(NonExistentFile);
#(CustomAdditionalCompileOutputs)"
>
<Message Text="Version Task running" Importance="High"/>
<IncrementVersion
ProjectPath="$(MSBuildProjectFullPath)"
VersionRule="3.3.0.+"
FileName="Properties\AssemblyInfo.cs">
</IncrementVersion>
</Target>
<PropertyGroup>
<TaskPath>$(MSBuildThisFileDirectory)..\Tasks\AutoVersionTask\AutoVersionTask\bin\Debug</TaskPath>
</PropertyGroup>
<UsingTask AssemblyFile="$(TaskPath)\AutoVersionTask.dll" TaskName="AutoVersionTask.IncrementVersion" />
<PropertyGroup>
<_ProjectVersioned>true</_ProjectVersioned>
</PropertyGroup>
</Project>
Normaly, we can add the script below into .csproj file:
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<Target Name="AutoVersionWhenBuild" AfterTargets="CoreBuild"
Condition="'$(_AssemblyTimestampBeforeCompile)'!='$(_AssemblyTimestampAfterCompile)'">
<Message Importance="high" Text="Auto-version begins when changes are made!"/>
<!--<AutoVersionTask>Do your auto-version task here.</AutoVersionTask>-->
</Target>
It will be called during the build when changes are really made to the project. See this similar issue.
As for your situation:
It seems your tasks and target comes from the targets file DXTAutoIncrementVersion.targets,you can open that file and change the target in it to the format above.
In addition: Please check the relationship between tasks, targets and .targets file.
1.MSBuild uses tasks to perform these actions.
2.Targets group tasks together.
3.MSBuild includes several .targets files that contain items, properties, targets, and tasks for common scenarios.
So you can either modify your auto-version target in the xx.targets file, or use the script above, and call the auto-version task in the AutoVersionWhenBuild target. Hope it helps:)
I'm trying to compile a small project, which was created with Visual Studio 2017 as a normal .Net project, using Visual Studio Code. One of the class, ConfigurationPropertyAttribute, cannot be found and I wonder which reference I should add to make it compile.
I tried searching for this class using reverse search in NuGet but it doesn't seem to exist.
Here is my .Net Core project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net462</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="microsoft.extensions.configuration" Version="1.1.2" />
</ItemGroup>
</Project>
My ultimate goal is simply to be able to compile and debug an old project using Visual Studio Code instead of Visual Studio 2017 without necessarily using .Net Core as it is still lacking many features. I thought that by targeting net462 I would get access to everything from .Net 4.6.2 but it doesn't seem so. Did I miss something or is there something I didn't understand properly ?
Your .csproj file needs to add a Reference System.Configuration not a PackageRefrence Microsoft.Extensions.Configuration
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net462</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Configuration" />
</ItemGroup>
</Project>