In my AssemblyInfo.cs file, I have attributes like:
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyCopyright("Copyright © 2015")]
Now i want to get this informations in my OnLaunched(LaunchActivatedEventArgs e) Method in my App.xaml.cs.
When I search for this in the internet and on SO I always solutions like:
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fvi.FileVersion;
But this doesn´t work for Windows 10. So is there something similar for Windows 10?
Edit:
I am developing an Windows 10 UWP application.
If you need to get information about app version in general, you can use Package.Current property.
using Windows.ApplicationModel;
Package package = Package.Current;
PackageId packageId = package.Id;
PackageVersion version = packageId.Version;
String output = String.Format(
"Name: \"{0}\"\n" +
"Version: {1}.{2}.{3}.{4}\n" +
"Architecture: {5}\n" +
"ResourceId: \"{6}\"\n" +
"Publisher: \"{7}\"\n" +
"PublisherId: \"{8}\"\n" +
"FullName: \"{9}\"\n" +
"FamilyName: \"{10}\"\n" +
"IsFramework: {11}",
packageId.Name,
version.Major, version.Minor, version.Build, version.Revision,
packageId.Architecture,
packageId.ResourceId,
packageId.Publisher,
packageId.PublisherId,
packageId.FullName,
packageId.FamilyName,
package.IsFramework);
You can find attributes using this code:
var currentAsembly = typeof(App).GetTypeInfo().Assembly;
var customAttributes = currentAssembly.CustomAttributes;
CustomAttributes is IEnumerable object of available atttributes among them you can find information abut assembly and file version
Edit:
Here is complete code:
var currentAssembly = typeof(App).GetTypeInfo().Assembly;
var customAttributes = currentAssembly.CustomAttributes;
var list = customAttributes.ToList();
var res = list[0];
var result = list.FirstOrDefault(x => x.AttributeType.Name == "AssemblyFileVersionAttribute");
var ver = result.ConstructorArguments[0].Value;
Related
I’m using Roslyn CSharpCompilation to generate dll files for my plugins – files have OptimizationLevel.Debug and pdb file is generated. Next I’m loading those files to my program (UWP + .NET Standard 2.0 libs) using Assembly.Load and create instance of types I’m interested in. My problem is that I can’t get Visual Studio (version 2017 15.7.3) to find source code when I’m debugging – it is treading it like external library, so when exception is thrown inside I can't find where. I have tired to search solution on stackoverflow but all solution are not working. I have checked this:
Pdb is generated
Module window in VS shows that symbols are loaded
Tried different version of Assembly Load/LoadFrom
Setting “Use
Managed Compatibility Mode” in debug options
Is there any way to make the file debuggable? Maybe I have to use some roslyn option while compiling or change something in VS?
The code sample below should help you on your way. It`s based on the code generation part of thlamare IOC container lamar, the successor of StructureMap made by Jeremy D Miller.
I have only added debugging capabilities. The trick was to make the source text embeddable, choosing the right formats, and setting encoding values where needed.
Check out the original work for more details of e.g. adding references.
public Assembly CreateAssembly(string code)
{
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(code);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
var optimizationLevel = OptimizationLevel.Debug;
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOptimizationLevel(optimizationLevel)
.WithPlatform(Platform.AnyCpu)
);
using (var assemblyStream = new MemoryStream())
using (var symbolsStream = new MemoryStream())
{
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.PortablePdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText>
{
EmbeddedText.FromSource(sourceCodePath, sourceText),
};
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (!result.Success)
{
var errors = new List<string>();
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}");
throw new Exception(String.Join("\n", errors));
}
Console.WriteLine(code);
assemblyStream.Seek(0, SeekOrigin.Begin);
symbolsStream?.Seek(0, SeekOrigin.Begin);
var assembly = AssemblyLoadContext.Default.LoadFromStream(assemblyStream, symbolsStream);
return assembly;
}
}
Usage:
[Test]
public void Verify()
{
var code =
#"namespace Debuggable
{
public class HelloWorld
{
public string Greet(string name)
{
var result = ""Hello, "" + name;
return result;
}
}
}
";
var codeGenerator = new CodeGenerator();
var assembly = codeGenerator.CreateAssembly(code);
dynamic instance = assembly.CreateInstance("Debuggable.HelloWorld");
// Set breakpoint here
string result = instance.Greet("Roslyn");
result.Should().Be("Hello, Roslyn");
}
I want to programmatically install a NuGet package to a project, and update the .csproj file, and the packages.config file.
I am using the official Nuget.core framework which source code is available here: https://github.com/NuGet/NuGet2
I am not using the NuGet package: https://www.nuget.org/packages/NuGet.Core/
But the source code found on GitHub to be able to do some debugging.
Note: I am using the version 2.11 and not the 2.13
I am able to download a package at a desired directory and update the packages.config file:
// ---- Download and install a package at a desired path ----
string packageID = "Newtonsoft.json";
var sourceUri = new Uri("https://packages.nuget.org/api/v2");
// Return an IPackage
var package = GetNugetPackage(packageID, sourceUri);
IPackageRepository sourceRepository = PackageRepositoryFactory.Default.CreateRepository(sourceUri.ToString());
string packagesPath = "../../TestFiles/packages";
PackageManager packageManager = new PackageManager(sourceRepository, packagesPath);
packageManager.InstallPackage(packageID, SemanticVersion.Parse(package.Version.ToFullString()));
// ---- Update the ‘packages.config’ file ----
var packageReferenceFile = new PackageReferenceFile("../../TestFiles/packages.config");
// Get the target framework of the current project to add --> targetframework="net452" attribute in the package.config file
var currentTargetFw = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(TargetFrameworkAttribute), false);
var targetFrameworkAttribute = ((TargetFrameworkAttribute[])currentTargetFw).FirstOrDefault();
// Update the packages.config file
packageReferenceFile.AddEntry(package.GetFullName(), SemanticVersion.Parse(package.Version.ToFullString()), false, new FrameworkName(targetFrameworkAttribute.FrameworkName));
Now I need to update the .csproj and here is the tricky part...
Here's what I tried so far:
string csprojFilePath = "../../TestFiles/test.csproj";
var project = new MSBuildProjectSystem(csprojFilePath);
string pathToAnExistingNugetPackageDll = "../../TestFiles/packages/Newtonsoft.json/lib/net45/Newtonsoft.json.dll"
project.AddReference(pathToAnExistingNugetPackageDll, Stream.Null);
project.Save();
This piece of code update the .csproj file, it add a new reference node like this:
<Reference Include="Newtonsoft.json">
<HintPath>..\packages\Newtonsoft.json\lib\net45\Newtonsoft.json.dll</HintPath>
</Reference>
But I need a complete reference node like this:
<Reference Include="Newtonsoft.json, Version=9.0.8, Culture=neutral, PublicKeyToken=b03f4f7d11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.json\lib\net45\Newtonsoft.json.dll</HintPath>
<Private>True</Private>
</Reference>
How can I do it ?
Thanks to #MattWard and #bashis, i've written my own code generator:
So, to add properly a reference into a given .csproj here's what I do:
var CsprojDoc = new XmlDocument();
CsprojDoc.LoadXml("*your_csproj_content*");
var Nsmgr = new XmlNamespaceManager(CsprojDoc.NameTable);
Nsmgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");
IPackage packageInfos = GetNugetPackage(packageId, packageRepositoryUri);
XmlNode referenceNode = CsprojDoc.CreateNode(XmlNodeType.Element, "Reference", XmlNamespaceValue);
XmlAttribute includeAttribute = CsprojDoc.CreateAttribute("Include");
var targetFwProfile = CsprojDoc.SelectSingleNode("//x:TargetFrameworkProfile", Nsmgr);
string targetFrameworkProfile = string.Empty;
if (!string.IsNullOrEmpty(targetFwProfile?.InnerXml))
{
targetFrameworkProfile = targetFwProfile.InnerXml;
}
var targetFwAttribute = GetTargetFrameworkFromCsproj();
Regex p = new Regex(#"\d+(\.\d+)+");
Match m = p.Match(targetFwAttribute.FrameworkName);
Version targetFwVersion = Version.Parse(m.Value);
// Get the package's assembly reference matching the target framework from the given '.csproj'.
var assemblyReference =
packageInfos.AssemblyReferences
.Where(a => a.TargetFramework.Identifier.Equals(targetFwAttribute.FrameworkName.Split(',').First()))
.Where(a => a.TargetFramework.Profile.Equals(targetFrameworkProfile))
.Last(a => (a.TargetFramework.Version.Major.Equals(targetFwVersion.Major) && a.TargetFramework.Version.Minor.Equals(targetFwVersion.Minor)) ||
a.TargetFramework.Version.Major.Equals(targetFwVersion.Major));
DownloadNugetPackage(packageInfos.Id, packageRepositoryUri, packagesFolderPath, packageInfos.Version.ToFullString());
string dllAbsolutePath = Path.GetFullPath($"{packagesFolderPath}\\{packageInfos.GetFullName().Replace(' ', '.')}\\{assemblyReference.Path}");
var assemblyInfos = Assembly.LoadFile(dllAbsolutePath);
includeAttribute.Value = $"{assemblyInfos.FullName}, processorArchitecture=MSIL";
referenceNode.Attributes.Append(includeAttribute);
XmlNode hintPathNode = CsprojDoc.CreateNode(XmlNodeType.Element, "HintPath", XmlNamespaceValue);
XmlNode privateNode = CsprojDoc.CreateNode(XmlNodeType.Element, "Private", XmlNamespaceValue);
hintPathNode.InnerXml = $"$(SolutionDir)\\packages\\{assemblyReference.Path}";
privateNode.InnerXml = "True";
referenceNode.AppendChild(hintPathNode);
referenceNode.AppendChild(privateNode);
var itemGroupNode = CsprojDoc.SelectSingleNode("//x:Project/x:ItemGroup/x:Reference", Nsmgr).ParentNode;
itemGroupNode.AppendChild(referenceNode);
Here's my DownloadNugetPackage method:
private static void DownloadNugetPackage(string packageId, Uri repoUri, string packagesFolderPath, string version)
{
IPackageRepository packageRepository = PackageRepositoryFactory.Default.CreateRepository(repoUri.ToString());
PackageManager packageManager = new PackageManager(packageRepository, packagesFolderPath);
packageManager.InstallPackage(packageId, SemanticVersion.Parse(version));
}
My GetTargetFrameworkFromCsproj
public static TargetFrameworkAttribute GetTargetFrameworkFromCsproj()
{
XmlNode targetFrameworkNode = CsprojDoc.SelectSingleNode("//x:TargetFrameworkVersion", Nsmgr);
return new TargetFrameworkAttribute($".NETFramework, Version={targetFrameworkNode.InnerXml}");
}
And my GetNugetPackage method:
public static IPackage GetNugetPackage(string packageId, Uri repoUri, string version = null)
{
IPackageRepository packageRepository = PackageRepositoryFactory.Default.CreateRepository(repoUri.ToString());
IPackage package;
if (!string.IsNullOrEmpty(version))
{
package = packageRepository.FindPackagesById(packageId).SingleOrDefault(p => p.Version.ToFullString().Equals(version));
}
else
{
package = packageRepository.FindPackagesById(packageId).SingleOrDefault(p => p.IsLatestVersion);
}
return package;
}
Note: This time, i'm using the official NuGet package: Nuget.core 2.14: https://www.nuget.org/packages/NuGet.Core/
Note 2: When I add a new Reference node, in the processorArchitecture attribute, I've hard coded the value: MSIL
If you want to test it, you might tweak it a bit.
This work fine for me.
(Assuming you are writing the code generator on your own)
I am not sure this is the best solution but you could try something like this:
var assembly = Assembly.LoadFile("path_to_dll");
string info = assembly.FullName; // contains something like "AssemblyName, Version=0.0.0.0, Culture=neutral, PublicKeyToken=foobar"
which will add some overhead by loading the assembly, but will presumably do the job.
I am attempting to create a PCL assembly using Roslyn (Microsoft.CodeAnalysis).
I'm referencing PCL assemblies located at "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETPortable\v4.5\Profile\Profile259". Here is my code that compiles the actual assembly.
var assemblyName = string.Concat("ODataHQ.SDK.", accountKey, ".dll");
var source = GenerateAccountSource(accountKey, workspace);
var assemblyInfoSource = GetAssemblyInfo(assemblyName);
var assemblyTree = CSharpSyntaxTree.ParseText(assemblyInfoSource);
var tree = CSharpSyntaxTree.ParseText(source);
// Lets add PCL framework assemblies.
var frameworkFiles = new[] {"mscorlib.dll", "Microsoft.CSharp.dll", "System.dll", "System.Core.dll", "System.Runtime.dll"};
var references = frameworkFiles
.Select(file => Path.Combine(Settings.PCLProfilePath, file))
.Select(fullPath => MetadataReference.CreateFromFile(fullPath))
.Cast<MetadataReference>()
.ToList();
// Lets add third-party dependent assemblies.
references.AddRange(Directory.GetFiles(Settings.SDKDependencyPath, "*.dll")
.Select(file => MetadataReference.CreateFromFile(file)));
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
var compilation = CSharpCompilation.Create(assemblyName, new [] { assemblyTree, tree }, references, options);
var ms = new MemoryStream();
var result = compilation.Emit(ms);
if (result.Success)
{
// Reset stream position to read from beginning.
ms.Position = 0;
return ms;
}
// Destroy memory stream since it didn't compile successfully.
ms.Dispose();
var firstError = result.Diagnostics
.Where(d => d.Severity == DiagnosticSeverity.Error)
.Select(d => d.GetMessage())
.FirstOrDefault();
throw new CompilationException(firstError);
Here is my GetAssemblyInfo method:
private string GetAssemblyInfo(string assemblyName)
{
return #"using System.Reflection;
using System.Runtime.Versioning;
[assembly: AssemblyTitle(""" + assemblyName + #""")]
[assembly: AssemblyVersion(""1.0.*"")]
[assembly: AssemblyFileVersion(""1.0.*"")]
[assembly: TargetFramework("".NETPortable,Version=v4.5,Profile=Profile259"", FrameworkDisplayName="".NET Portable Subset"")]";
}
I take the assembly that is generated and save it to disk. Then reference it in another console app project. However, when I run the console app and try to use a type from the dynamically generated PCL assembly, I get the following error.
An unhandled exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll
Additional information: Could not load file or assembly 'ODataHQ.SDK.dvester.dll, Version=1.0.5635.36199, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Can someone help me figure out what's going wrong?
Check the FusionLog property of the exception (you may need to enable that in the registry).
This will tell you why it failed.
Where can I set the file version comments..?
We can get it by
FileVersionInfo fv =
System.Diagnostics.FileVersionInfo.GetVersionInfo(
Assembly.GetExecutingAssembly().Location);
var comment = fv.Comments;
Then how can I set it so that I can show the same somewhere..
For .NET Assemblies you can set the File Version Comments using the AssemblyDescriptionAttribute, which you usually put in the AssemblyInfo.cs file in your project when using Visual Studio.
[assembly: AssemblyDescription("The assembly does xxx by yyy")]
For other types of executables the file version is set using a resource in the file.
The different assembly level File Version attributes maps as follows:
FileVersionInfo.Comments = AssemblyDescription
FileVersionInfo.CompanyName = AssemblyCompany
FileVersionInfo.FileDescription = AssemblyTitle
FileVersionInfo.FileVersion = AssemblyFileVersion
FileVersionInfo.LegalCopyright = AssemblyCopyright
FileVersionInfo.LegalTrademarks = AssemblyTrademark
FileVersionInfo.ProductName = AssemblyProduct
FileVersionInfo.ProductVersion = AssemblyInformationalVersion
Nowadays in .Net 6
you can set comments in*.csproj
<Description>My Comment</Description>
And get
public static string GetComments()
{
var fileName = Assembly.GetEntryAssembly()?.Location;
if (fileName == null) return String.Empty;
var versionInfo = FileVersionInfo.GetVersionInfo(fileName);
return versionInfo?.Comments ?? String.Empty;
}
To set this value, you can edit the AssemblyInfo.cs file of your project.
This line is what you are looking for:
[assembly: AssemblyDescription("This is the comment")]
How can I print in my log the version of the program that is running?
In other words, can I access AssemblyFileVersion using Console.WriteLine?
Thanks
Tony
It looks like something like this would work:
public static string Version
{
get
{
Assembly asm = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);
return String.Format("{0}.{1}", fvi.ProductMajorPart, fvi.ProductMinorPart);
}
}
From another post on SO.
// Get the version of the current application.
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName assemName = assem.GetName();
Version ver = assemName.Version;
Console.WriteLine("{0}, Version {1}", assemName.Name, ver.ToString());
More on MSDN:
Version Class
FileVersionInfo.GetVersionInfo(asm.Location) doesn't work for embedded assemblies (e.g. using Fody's Costura to ship a single EXE instead of the executable and all of it's dependent assemblies). In which case, the following works as a fallback:
var assembly = Assembly.GetExecutingAssembly();
var fileVersionAttribute = assembly.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(AssemblyFileVersionAttribute));
if (fileVersionAttribute != null && fileVersionAttribute.ConstructorArguments.Any())
return fileVersionAttribute.ConstructorArguments[0].ToString().Replace("\"","");
return string.Empty;