The problem- We can parse a csproj file in some ways, but most of the information is not in the file, but is either by default or affected by other properties.
I want to work against csproj files and solution- get project dependencies, get properties and items (things like 'TargetFramework', compiled files..)
The TargetFramework can be a tag with value, or 'TargetFrameworks' tag with multi-values that parsed to 'TargetFramework'.
The old solution- MSBuild provide a microsoft.build.evaluation library to work with csproj file, but this library compiled to net471, and cause errors when we use it in netcoreapp.
What will be the solution for the problem, in .net core projects?
For .Net Core Microsoft.Build NuGet Package works as below:
var projectRootElement = ProjectRootElement.Open(csprojPath);
projectRootElement.AddProperty("Version", "3.4.5");
projectRootElement.Save();
If Version exists it overrides it. If not exist adds new property name is "Version" and value is "3.4.5".
Also you can get all properties which defined in .csproj
var projectRootElement = ProjectRootElement.Open(csprojPath);
foreach (var property in projectRootElement.Properties)
{
Console.WriteLine($"Name: {property.Name} - Value: {property.Value}");
}
Tested in .NetCore 5.0
Related
ITNOA
I use cake build system to automate building my solution and I want to automate testing my project with cake in our CI,
My NUnit projects have many types such as asp.net dot net framework 4.6.1 or dot net core 2.1 or ...
my problem is when I want to run our unit test with NUnit3 cake dsl we need to know dll path of each project, so I need to know what is type of each project, because for example for dot net core 2.1 dll is under netcoreapp directory and for another project dll is under somewhere else.
for better demonstration please see below image
As you can see in Test Solution Folder we have many test projects with different type framework and ... (for example one of them is dotnetcore2.1 another one is dot net framework 4.6.1 and etc.)
So my question is how to find type of project?
Is there any solution to NUnit3 found dll by self?
my GitHub discussion about this question
thanks
You should use a project reference for your unit test projects as opposed to an explicit DLL reference.
When you're using .Net Core, Use XUnit testing for allow for near identical process for your test methods.
By using a project reference and having your test projects as part of the same Solution (sln) file, you'll greatly simplify your work.
It looks like what you are trying to do is to get a list of all the assemblies for your unit tests, across any targets that the project might have.
If that's the case, you could use the GetFiles alias to find the assemblies, and then inspect the FullPath of each assembly to check the TFM...
var files = GetFiles("./**/*.Tests.dll");
foreach(var file in files)
{
Information("File: {0}", file.FullPath);
if (file.FullPath.Contains("/net461/")
{
// ... Assembly is for .NET 4.6.1
}
else if (file.FullPath.Contains("/netcoreapp2.1/")
{
// ... Assembly is for .NET Core 2.1
}
// etc...
}
You could utilize a globber pattern to find all test projects, don't know you're exakt folder structure but you could do something like below
Task("Test")
.Does(() =>
{
var settings = new DotNetCoreTestSettings
{
Configuration = "Release"
};
var projectFiles = GetFiles("./**/Test/UnitTests/*.csproj");
foreach(var file in projectFiles)
{
DotNetCoreTest(file.FullPath, settings);
}
});
I am working on a build tool in C# that should work with Visual Studio / MSBuild. I want to enumerate all files that are part of a C# project. The project format is the new (.NET Core) .csproj.
The documentation describing the Project System points at using MSBuild (file format) or Common Project System (project tree). I'm unfamiliar with both APIs. Looking at documentation for those respective projects is not immediately helpful.
As the expert probably knows, the new .csproj file does not list every file that is implicitly part of the project. On the other hand it may list a 'linked' file that is outside the project folder. I want to make sure I get all files that are considered part of the project.
Ultimately I want to focus on a particular file type (.json), but I thought the general question was worth asking.
To sum up: How can I write a C# library that leverages the appropriate packages to (hopefully easily) enumerate all the files in a csproj?
Buildalyzer is the easiest package to use, and it targets .NETStandard 2.0 making it cross-platform. (Omnisharp does not currently offer a NuGet package for working with the workspace. And Microsoft.CodeAnalysis poses a challenge to get the correct references in place, and is limited to net46.)
using Buildalyzer;
private static IList<string> InlcudedProjectKeys = new[] { "None", "Compile", "Content", "EmbeddedResource" };
private static IEnumerable<string> EnumerateProjectFiles(string projectPath)
{
AnalyzerManager manager = new AnalyzerManager();
ProjectAnalyzer analyzer = manager.GetProject(projectPath);
AnalyzerResults results = analyzer.Build();
AnalyzerResult result = results.Single();
// If only interested in C# files, check out:
//string[] sourceFiles = result.SourceFiles;
IReadOnlyDictionary<string, ProjectItem[]> items = result.Items;
foreach (var item in items)
{
// Skip keys like ProjectReference that aren't for files
if (!InlcudedProjectKeys.Contains(item.Key))
continue;
ProjectItem[] projectItems = item.Value;
foreach (var projectItem in projectItems)
{
// The item spec for files will be the path relative to the project directory
yield return projectItem.ItemSpec;
}
}
}
And for bonus points, to get only *.json files:
var jsonFiles = EnumerateProjectFiles(projectPath)
.Where(path => path.EndsWith(".json"))
.ToArray();
Thanks Hitesh for linking to relevant resources.
You can use Roslyn Analyzer Libraries to load csproject and access it's content as well as properties in program. you can follow instructions from this previous SO post, or use OpenProjectAsync(projectFilePath) method to load instance of Project class in Microsoft.CodeAnalysis namespace.
using Microsoft.CodeAnalysis.MSBuild;
AnalyzerManager manager = new AnalyzerManager();
ProjectAnalyzer analyzer = manager.GetProject(#"C:\MyCode\MyProject.csproj");
You can find more information on roslyn at Github.
In this video from MSDN at the 3:34 second mark, the presenter shows how to append the Build ID to a nuget's version. In the MSBuild arguments, he specifies:
/t:pack /p:PackageVersion=1.0.$(Build.BuildId)
So, when the project is built by VSTS, the nuget assembly's revision number is using the build id.
I would like to do something similar. Instead of hard coding the 1.0 in the build definition, I'd like to retrieve that from .csproj file. I am using the new .csproj file which stores nuget information.
For example, I'd like to specify in the csproj:
<Version>0.0.1-beta</Version>
Then, VSTS would append the BuildID and generate the assembly version as 0.0.0.1-beta.49 (49 being the build id)
I ended up doing the opposite of what Shayki Abramczyk suggested.
I use a task called "Variables Task Pack". It can be found here (and is free at the time of this answer): https://marketplace.visualstudio.com/items?itemName=YodLabs.VariableTasks#qna
Using this task, I set two variable: $(BuildId) and $(ReleaseType). See the settings snapshots at the end of the answer.
Then, in my CSPROJ project file, I modified the nuget version to use the two environment variables. Here's a clip of the project file:
<PropertyGroup>
<Version>0.0.0.0$(BuildId)$(ReleaseType)</Version>
<FileVersion>0.0.0.0$(BuildId)$(ReleaseType)</FileVersion>
...
</PropertyGroup>
IMPORTANT: Notice the extra 0 in front of $(BuildId). I had to add that in order to build locally. Without it, the build failed with an incorrect version format error.
Now, after building, I get the buildid as my revision number and release type appended.
Here are the screen shots showing configuration of both variables.
You can create a Power Shell script that retrieves the version from csproj file, then add the version to a new environment variable with this command: Set-VstsTaskVariable
For Example:
$csprojId = $retrivedIdfromTheFile
Set-VstsTaskVariable -Name "CSPROJ_ID" -Value $csprojId
Now you can use the CSPROJ_ID variable on the MSBuild arguments:
/p:PackageVersion=$(CSPROJ_ID).$(Build.BuildId)
This one is giving me such a headache. We used to put things in the project properties under [assembly: AssemblyVersion("1.0.0.0")] I am totally fine with change so I do not care where it is. I understand they are going to a new standard for versions as well, also totally fine.
Plenty of documents out there point to the project.json file which is clearly a waste as this is no longer a legit file. More recent say add the following to your .csproj file:
<PropertyGroup>
<VersionPrefix>1.2.3</VersionPrefix>
<VersionSuffix>alpha</VersionSuffix>
</PropertyGroup>
Also a total waste. Only because I can not seem to be able to read it. The following always gives me 1.0.0.0.
PlatformServices.Default.Application.ApplicationVersion
Not to mention when I right-click in File Explorer and click Properties, then Details tab also always says 1.0.0.0.
So, how I can set the version of each assembly within my solution AND then read them later at runtime?
On method is to set either of these values in your project file:
<PropertyGroup>
<Version>1.3.5.7</Version>
<FileVersion>2.4.6.8</FileVersion>
</PropertyGroup>
And read them like this:
var fileVersion = Assembly.GetEntryAssembly()
.GetCustomAttribute<AssemblyFileVersionAttribute>()
.Version;
var informationalVersion = Assembly.GetEntryAssembly()
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
.InformationalVersion;
It's worth noting that setting these value in the .csproj file does autogenerate (so don't try to edit it) a file similar to the legacy AssemblyInfo.cs containing something like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
//snip
[assembly: System.Reflection.AssemblyFileVersionAttribute("2.4.6.8")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.2.3")]
// Generated by the MSBuild WriteCodeFragment class.
Turns out this started working when .Net Core 2.0 came out. When you right-click on the Project and then click Properties there is a UI for it as seen below:
The Package Version, Assembly Version and Assembly File Version correspond to the Version, AssemblyVersion and FileVersion settings in the .csproj file respectively:
<PropertyGroup>
<Version>1.1.0</Version>
<AssemblyVersion>1.1.0.9</AssemblyVersion>
<FileVersion>1.1.0.9</FileVersion>
</PropertyGroup>
I then created a utility method in each project of my solution that does the following:
public static VersionInformationModel GetVersionInformation() {
var Result = new VersionInformationModel {
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(),
BuildDate = System.IO.File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location),
Configuration = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyConfigurationAttribute>().Configuration,
TargetFramework = Assembly.GetExecutingAssembly().GetCustomAttribute<System.Runtime.Versioning.TargetFrameworkAttribute>().FrameworkName,
};
return Result;
}
So on an admin page of my site, I can know when version and other particulars about each project as it stands on whatever server I am looking at.
As the title says, I want to change the .NET Target Framework Version for my C++ project. I'm trying to compile with the /clr command which I think should enable it?
Here's a screenshot:
I'm trying to build a DLL for use in Unity and I want to be able to select the proper framework.
I've tried changing the information in the .vxproj file but I can't find the right tag and when I add it myself it throws errors.
EDIT:
this is the code that contains the methods that can be called in C# to use the C++ code I've written before. I only edited the .h file of the CLR Class library (so the .cpp file is only including the header which should be fine I think)
#pragma once
#include "PortAudioManager.h"
using namespace System;
namespace PortAudioWrapper {
public ref class PortAudioManaged
{
private:
PortAudioManager* audioManager;
public:
PortAudioManaged() : audioManager(new PortAudioManager()) {
}
virtual ~PortAudioManaged() {
this->!PortAudioManaged();
}
// = Object.Finalize
!PortAudioManaged() {
delete audioManager;
audioManager = nullptr;
}
void openStreamManaged() {
audioManager->openStream();
}
void stopStreamManaged() {
audioManager->stopStream();
}
};
}
You should be able to follow the guide at https://msdn.microsoft.com/en-us/library/ff770576.aspx
The .NET framework you can target in C++ is dependent on the toolset you choose. You may find it easier to just download an older version of VS that supports the framework you're looking to work with.
In project file I just created the section looks like the below:
<PropertyGroup Label="Globals">
<ProjectGuid>{48ACEC98-3369-486F-9033-8C433D408570}</ProjectGuid>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>ClassLibrary1</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
Using VS2015, I had to upgrade the .Net target of a managed C++ DLL from 3.5 to 4.5.1. In the Configuration Properties-General settings, the ".Net Target Framework Version" is greyed out and its value box is not editable.
Open the Name.vcxproj file in notepad.
Navigate to: "<"PropertyGroup Label="Globals" ""
Add: "<"TargetFrameworkVersion""v4.5.1"<"/TargetFrameworkVersion"
Save the updated project file, and reload into VSS2015.
NOTE: Remove the "" around the angle brackets.
Then when the project is reloaded into VS2015, you can see the .Net version listed in settings. In my case it was V4.5.1.