Dynamically created dll does not have version numbers - c#

I would like to know, how can i assign version numbers to dynamically created dlls. I have a mini application that creates dlls for my end users. But currently, all the dlls created are having 0.0.0.0 as their version numbers.
And it is difficult to keep track of the latest one. Is there are way to assign version numbers to dynamically created dlls. I tried searching the net but no avail.
Please do advise. I am using the following code create the dlls.
// Setup for compiling
var provider_options = new Dictionary<string, string>
{
{"CompilerVersion","v3.5"}
};
var provider = new Microsoft.CSharp.CSharpCodeProvider(provider_options);
var compiler_params = new System.CodeDom.Compiler.CompilerParameters();
string outfile = #"D:\EDUnit.dll";
compiler_params.OutputAssembly = outfile;
compiler_params.GenerateExecutable = false;
compiler_params.ReferencedAssemblies.Add("System.dll");
// Compile
var results = provider.CompileAssemblyFromSource(compiler_params, strbase)

You need to assign it to your source code file using reflection attributes. The code provider will look for it, extract it and add the required metadata. Decorate your source class as follows
using System.Reflection;
[assembly: AssemblyVersion("2.1.0.0")]
[assembly: AssemblyFileVersion("2.1.0.0")]
public class Your_Class{}

Related

How to display updated version Number Automatically in Windows form Application c#?

I have to display build version automatically without entering manually in windows form application, I have tried something like [assembly: AssemblyVersion("1.0.*")]
in assemblyInfo.cs but its show like below,
{1.0.7145.41554} its looks awkward
I want show something like this [1.0.0.13] after published, but it always takes [1.0.0.1]
see the below image I want to show that version in view page actually
This is how I'm getting version; but it is returning [1.0.0.1]
//Get Version of the currently executing Assembly
var anm = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
ExistingVersion = String.Format("{0}", anm);
EMajor = anm.Major;
EMinor = anm.Minor;
EBuildNo = anm.Build;
ERevisionNo = anm.Revision;
lblVersionv.Text = String.Format("Current Version : {0}", anm);
How I can do that?
It is a bit convoluted but you can reach this info from your own code and then decide to display it how you like.
First step is the most critical, you need to get a Type from one of your own classes.
You can use your main form class for example
Type myApp = Type.GetType("your-full-qualified-class-name-here");
So suppose your namespace is "MyApplication" and your main form class is named "MyStartupForm" then you should replace the string above with "MyApplication.MyStartupForm" (be precise with upper/lowercase letters)
Now with the type you could get the the Version information with
Version v = myApp.Assembly.GetName().Version;
And finally the version variable will have all the info you need.
(Look at the property Build, Version, Revision, MinorRevision, MajorRevision)
Note also that the override for the ToString method will return to you a single string with all the information required
I solve this by adding below code
if (ApplicationDeployment.IsNetworkDeployed)
{
lblVersionv.Text = string.Format("Version : {0}",ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString(4));
}

programmatically extract interface using roslyn

I am looking for a way to extract an interface from a document (c# class declaration) using Roslyn.
going from the reformatter example.
MSBuildWorkspace workspace = MSBuildWorkspace.Create();
// Open the solution within the workspace.
Solution originalSolution = workspace.OpenSolutionAsync(project).Result;
// Declare a variable to store the intermediate solution snapshot at each step.
MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Solution originalSolution = workspace.OpenSolutionAsync(project).Result;
Solution newSolution = originalSolution;
foreach (ProjectId projectId in originalSolution.ProjectIds)
{
// Look up the snapshot for the original project in the latest forked solution.
Project proj = newSolution.GetProject(projectId);
var comp = proj.GetCompilationAsync().Result;
///var bind = comp.
if (proj.Name.EndsWith("Core.DataLayer"))
{
foreach (DocumentId documentId in proj.DocumentIds)
{
Document document = newSolution.GetDocument(documentId);
if (IsRepositoryDocument(document))
{
//How to implement this?
var newinterface = GetInterfaceFromRespository(document);
}
}
}
}
I started out using the sample "reformat solution" that the Roslyn team provided. However I am unable to find a public API to extract an interface from a given class file.
When trying to find this functionality in the Roslyn source code I can only find internal classes. I found the relevant classes in
"src\Features\Core\Portable\ExtractInterface" of the roslyn source code, i could copy these into my project and get it working, but i would rather not.
TLDR; is there a public API that I can use from C# to extract an interface from a class programatically?
Note that this is done in a "regular" C# project and not in a visual studio extension or analyzer.
You can get all the interfaces from a C# file using the below code statements.
string code = new StreamReader(filePath).ReadToEnd();
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var syntaxRoot = syntaxTree.GetRoot();
IEnumerable<InterfaceDeclarationSyntax> interfaceDeclarations = syntaxRoot.DescendantNodes().OfType<InterfaceDeclarationSyntax>();
Then you can iterate the available interfaces in the file.

Including an embedded resource in a compilation made by Roslyn

I'm attempting to include an embedded resource into a dll that I am compiling using Roslyn. I've found something that helped put me on the right track here.
However, when I create the dll using the following code:
const string resourcePath = #"C:\Projects\...\Properties\Resources.resources";
var resourceDescription = new ResourceDescription(
"Resources.resources",
() => File.OpenRead(resourcePath),
true);
var result = mutantCompilation.Emit(file, manifestResources: new [] {resourceDescription});
I find that it will pass all of the unit tests that I have created for the project except for those that rely on the Resources file.
The error I'm getting looks like the following:
System.Resources.MissingManifestResourceException ... Make sure "[Project].Properties.Resources.resources" was correctly embedded or linked into
assembly "[Project]" at compile time, or that all the satellite assemblies required are loadable and fully signed.
The dll is supposed to be signed, and when it is emitted by roslyn it comes out with the correct public key. Also, the Resource.resx is included in my project directly in the Properties folder.
I would appreciate any help anyone could provide.
Ok, so while I was looking for answers, I came across this web page where it was commented that the resource stream was null until the he added the namespace.
So after adding the namespace I got somehting like this
const string resourcePath = #"C:\Projects\...\Properties\Resources.resources";
var resourceDescription = new ResourceDescription(
"[namespace].Resources.resources",
() => File.OpenRead(resourcePath),
true);
var result = mutantCompilation.Emit(file, manifestResources: new [] {resourceDescription});
which runs exactly like you'd expect.

Generating a diff report using NDepend during build

We are using TeamCity for continuous integration, our source control is Git, and we have 1 major repository that contains multiple .sln files (around 10).
All in all, this repository has about ~ 100 - 200 C# projects.
Upon a push to the master repository, TeamCity triggers a build that will compile all projects in the repository.
I'd like to be able to tell which projects were actually affected by a particular commit, and thus publish only those projects' outputs as artifacts of the current build.
For this, i've designed a solution to integrate NDepend into our build process, and generate a diff report between current and latest build outputs.
The outputs that were changed/added will be published as the build outputs.
I have little experience with NDepend; from what i've seen all of its true power comes from the query language that is baked into it.
I am wondering how (if possible) i can achieve the following:
Diff between a folder containing previous build's outputs and current folder of build outputs.
Have NDepend generate a report in a consumable format so i can determine the files that need to be copied.
Is this scenario possible? How easy/hard would that be?
So the simple answer is to do the Reporting Code Diff way as explained in this documentation. The problem with this basic answer is that, it pre-suppose two NDepend projects that always refers to the two same set of assemblies.
Certainly, the number and names of assemblies is varying in your context so we need to build two projects (old/new) on the fly and analyze them through NDepend.API.
Here is the NDepend.API source code for that. For a It-Just-Works experience, in the PowerTools source code (in $NDependInstallDir$\NDepend.PowerTools.SourceCode\NDepend.PowerTools.sln) just call the FoldersDiff.Main(); method after the AssemblyResolve registration call, in Program.cs.
...
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolverHelper.AssemblyResolveHandler;
FoldersDiff.Main();
...
Here is the the source code that harnesses NDepend.API.
Note that so much more can be done, through the two codeBase objects and the compareContext object. Instead of just showing the 3 lists of assemblies added/removed/codeWasChanges, you could show API breakings changes, new methods and types added, modified classes and methods, code quality regression... For that, just look at default code rules concerning diff, that are based on the same NDepend.CodeModel API.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NDepend;
using NDepend.Analysis;
using NDepend.CodeModel;
using NDepend.Path;
using NDepend.Project;
class FoldersDiff {
private static readonly NDependServicesProvider s_NDependServicesProvider = new NDependServicesProvider();
internal static void Main() {
var dirOld = #"C:\MyProduct\OldAssembliesDir".ToAbsoluteDirectoryPath();
var dirNew = #"C:\MyProduct\NewAssembliesDir".ToAbsoluteDirectoryPath();
Console.WriteLine("Analyzing assemblies in " + dirOld.ToString());
var codeBaseOld = GetCodeBaseFromAsmInDir(dirOld, TemporaryProjectMode.TemporaryOlder);
Console.WriteLine("Analyzing assemblies in " + dirNew.ToString());
var codeBaseNew = GetCodeBaseFromAsmInDir(dirNew, TemporaryProjectMode.TemporaryNewer);
var compareContext = codeBaseNew.CreateCompareContextWithOlder(codeBaseOld);
// So much more can be done by exploring fine-grained diff in codeBases and compareContext
Dump("Added assemblies", codeBaseNew.Assemblies.Where(compareContext.WasAdded));
Dump("Removed assemblies", codeBaseOld.Assemblies.Where(compareContext.WasRemoved));
Dump("Assemblies with modified code", codeBaseNew.Assemblies.Where(compareContext.CodeWasChanged));
Console.Read();
}
internal static ICodeBase GetCodeBaseFromAsmInDir(IAbsoluteDirectoryPath dir, TemporaryProjectMode temporaryProjectMode) {
Debug.Assert(dir.Exists);
var dotNetManager = s_NDependServicesProvider.DotNetManager;
var assembliesPath = dir.ChildrenFilesPath.Where(dotNetManager.IsAssembly).ToArray();
Debug.Assert(assembliesPath.Length > 0); // Make sure we found assemblies
var projectManager = s_NDependServicesProvider.ProjectManager;
IProject project = projectManager.CreateTemporaryProject(assembliesPath, temporaryProjectMode);
// In PowerTool context, better call:
// var analysisResult = ProjectAnalysisUtils.RunAnalysisShowProgressOnConsole(project);
var analysisResult = project.RunAnalysis();
return analysisResult.CodeBase;
}
internal static void Dump(string title, IEnumerable<IAssembly> assemblies) {
Debug.Assert(!string.IsNullOrEmpty(title));
Debug.Assert(assemblies != null);
Console.WriteLine(title);
foreach (var #assembly in assemblies) {
Console.WriteLine(" " + #assembly.Name);
}
}
}

How can I use MSBuild to update version information only when an assembly has changed?

I have a requirement to install multiple web setup projects (using VS2005 and ASP.Net/C#) into the same virtual folder. The projects share some assembly references (the file systems are all structured to use the same 'bin' folder), making deployment of changes to those assemblies problematic since the MS installer will only overwrite assemblies if the currently installed version is older than the one in the MSI.
I'm not suggesting that the pessimistic installation scheme is wrong - only that it creates a problem in the environment I've been given to work with. Since there are a sizable number of common assemblies and a significant number of developers who might change a common assembly but forget to update its version number, trying to manage versioning manually will eventually lead to massive confusion at install time.
On the flip side of this issue, it's also important not to spontaneously update version numbers and replace all common assemblies with every install, since that could (temporarily at least) obscure cases where actual changes were made.
That said, what I'm looking for is a means to update assembly version information (preferably using MSBuild) only in cases where the assembly constituents (code modules, resources etc) has/have actually changed.
I've found a few references that are at least partially pertinent here (AssemblyInfo task on MSDN) and here (looks similar to what I need, but more than two years old and without a clear solution).
My team also uses TFS version control, so an automated solution should probably include a means by which the AssebmlyInfo can be checked out/in during the build.
Any help would be much appreciated.
Thanks in advance.
I cannot answer all your questions, as I don't have experience with TFS.
But I can recommend a better approach to use for updating your AssemblyInfo.cs files than using the AssemblyInfo task. That task appears to just recreate a standard AssemblyInfo file from scratch, and loses any custom portions you may have added.
For that reason, I suggest you look into the FileUpdate task, from the MSBuild Community Tasks project. It can look for specific content in a file and replace it, like this:
<FileUpdate
Files="$(WebDir)\Properties\AssemblyInfo.cs"
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$(Major).$(ServicePack).$(Build).$(Revision)"
Condition="'$(Configuration)' == 'Release'"
/>
There are several ways you can control the incrementing of the build number. Because I only want the build number to increment if the build is completely successful, I use a 2-step method:
read a number from a text file (the only thing in the file is the number) and add 1 without changing the file;
as a final step in the build process, if everything succeeded, save the incremented number back to the text file.
There are tasks such as ReadLinesFromFile, that can help you with this, but I found it easiest to write a small custom task:
using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace CredibleCustomBuildTasks
{
public class IncrementTask : Task
{
[Required]
public bool SaveChange { get; set; }
[Required]
public string IncrementFileName { get; set; }
[Output]
public int Increment { get; set; }
public override bool Execute()
{
if (File.Exists(IncrementFileName))
{
string lines = File.ReadAllText(IncrementFileName);
int result;
if(Int32.TryParse(lines, out result))
{
Increment = result + 1;
}
else
{
Log.LogError("Unable to parse integer in '{0}' (contents of {1})");
return false;
}
}
else
{
Increment = 1;
}
if (SaveChange)
{
File.Delete(IncrementFileName);
File.WriteAllText(IncrementFileName, Increment.ToString());
}
return true;
}
}
}
I use this before the FileUpdateTask to get the next build number:
<IncrementTask
IncrementFileName="$(BuildNumberFile)"
SaveChange="false">
<Output TaskParameter="Increment" PropertyName="Build" />
</IncrementTask>
and as my final step (before notifying others) in the build:
<IncrementTask
IncrementFileName="$(BuildNumberFile)"
SaveChange="true"
Condition="'$(Configuration)' == 'Release'" />
Your other question of how to update the version number only when source code has changed is highly dependent on your how your build process interacts with your source control. Normally, checking in source file changes should initiate a Continuous Integration build. That is the one to use to update the relevant version number.
I have written one custome task you can refer the code below. It will create an utility to which you can pass assemblyinfo path Major,minor and build number. you can modify it to get revision number. Since in my case this task was done by developer i used to search it and again replace whole string.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace UpdateVersion
{
class SetVersion
{
static void Main(string[] args)
{
String FilePath = args[0];
String MajVersion=args[1];
String MinVersion = args[2];
String BuildNumber = args[3];
string RevisionNumber = null;
StreamReader Reader = File.OpenText(FilePath);
string contents = Reader.ReadToEnd();
Reader.Close();
MatchCollection match = Regex.Matches(contents, #"\[assembly: AssemblyVersion\("".*""\)\]", RegexOptions.IgnoreCase);
if (match[0].Value != null)
{
string strRevisionNumber = match[0].Value;
RevisionNumber = strRevisionNumber.Substring(strRevisionNumber.LastIndexOf(".") + 1, (strRevisionNumber.LastIndexOf("\"")-1) - strRevisionNumber.LastIndexOf("."));
String replaceWithText = String.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]", MajVersion, MinVersion, BuildNumber, RevisionNumber);
string newText = Regex.Replace(contents, #"\[assembly: AssemblyVersion\("".*""\)\]", replaceWithText);
StreamWriter writer = new StreamWriter(FilePath, false);
writer.Write(newText);
writer.Close();
}
else
{
Console.WriteLine("No matching values found");
}
}
}
}
I hate to say this but it seems that you may be doing it wrongly. Is much easier if you do generate the assembly versions on the fly instead of trying to patch them.
Take a look at https://sbarnea.com/articles/easy-windows-build-versioning/
Why I do think you are doing it wrong?
* A build should not modify the version number
* if you build the same changeset twice you should get the same build numbers
* if you put build number inside what microsoft calls build number (proper naming would be PATCH level) you will eventually reach the 65535 limitation.

Categories