I'm looking for ANY means of setting the file version for an exe file generated using codeDOM. Mine always comes out as 0.0.0.0. Programatically would obviously be preferred, but at this point anything would be better than nothing.
The version of the compiled assembly is controlled by the AssemblyFileVersion attribute. You just need to make sure this is included as part of your CodeDom tree when you compile.
You can set this by adding the attribute into the CodeCompileUnit AssemblyCustomAttributes member.
CodeCompileUnit unit = CreateMyUnit();
var attribute = new CodeAttributeDeclaration(
new CodeTypeReference(typeof(AssemblyFileVersionAttribute)));
attribute.Arguments.Add(
new CodeAttributeArgument(
new CodePrimitiveExpression("1.1.1.1")));
unit.AssemblyCustomAttributes.Add(attribute);
Related
I'm trying to use the new FxCop analyzers, but they're only available as NuGet packages or as VSIX extensions. I'd like to be able to run them directly, either from inside a C# program or from the command line. Anyone have any advice? Even general info on where you can find the executables for NuGet or VSIX would help.
(I know about fxcopcmd.exe, but that's the legacy version, and it works only on built .exes or .dlls. If at all possible, I need something that works before building.)
Answering my own question in case anyone else has to deal with this. I found a solution, but fair warning, it's not pretty.
I took an example C# solution from Github, loaded it up in Visual Studio, and used NuGet to install the FxCop analyzers. This installed the analyzers, and changed the solution's .csproj files to reference them. In my case, I found a copy of the analyzers in C:\users\myname.nuget\packages.
I compared the modified .csproj files to the originals, to see what changes had been made during installation. I recommend anyone following along make this comparison themselves, but in my case, the changes were:
Five Import elements at the top referencing various .props files.
An empty NuGetPackageImportStamp element.
Two new ItemGroups near the bottom, the first containing a single element named "None", the second containing various Analyzer elements referencing .dlls.
A new Target to ensure that the .props files actually existed.
I wrote a C# program that took an arbitrary solution, found all the .csproj files inside, and manually added those new XML elements to them. I skipped the one-element ItemGroup and the Target without any problems.
Ideally you would then (from inside the same C# program) call msbuild on the .sln file, save every output line matching the regex "): warning CA\d\d\d\d: " (i.e. the warnings that FxCop generated), and restore the original .csproj files. I did that all manually. Here's the code for the XML manipulation, though:
static void addAnalyzersToCsProj(string file)
{
string[] packages = new string[]
{
#"C:\users\myname\.nuget\packages\microsoft.codeanalysis.fxcopanalyzers\3.0.0\build\Microsoft.CodeAnalysis.FxCopAnalyzers.props",
#"C:\users\myname\.nuget\packages\microsoft.codeanalysis.versioncheckanalyzer\3.0.0\build\Microsoft.CodeAnalysis.VersionCheckAnalyzer.props",
#"C:\users\myname\.nuget\packages\microsoft.codequality.analyzers\3.0.0\build\Microsoft.CodeQuality.Analyzers.props",
#"C:\users\myname\.nuget\packages\microsoft.netcore.analyzers\3.0.0\build\Microsoft.NetCore.Analyzers.props",
#"C:\users\myname\.nuget\packages\microsoft.netframework.analyzers\3.0.0\build\Microsoft.NetFramework.Analyzers.props",
};
var root = XElement.Load(file);
var ns = "";
for (var i = 0; i < 5; i++)
{
XElement packageImport = new XElement(ns+"Import");
packageImport.SetAttributeValue("Project", packages[i]);
string condition = "Exists('" + packages[i] + "')";
packageImport.SetAttributeValue("Condition", condition);
root.AddFirst(packageImport);
}
var propertyGroup = root.Descendants(ns + "PropertyGroup").First();
var stamp = new XElement(ns+"NuGetPackageImportStamp", "");
propertyGroup.Elements().Last().AddAfterSelf(stamp);
var newGroup = new XElement(ns+"ItemGroup");
// do we need to include the "None Include="packages.config"" thing?
string[] libraries = new string[]
{
#"C:\users\myname\.nuget\packages\microsoft.codeanalysis.versioncheckanalyzer\3.0.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.VersionCheckAnalyzer.resources.dll",
#"C:\users\myname\.nuget\packages\microsoft.codeanalysis.versioncheckanalyzer\3.0.0\analyzers\dotnet\Microsoft.CodeAnalysis.VersionCheckAnalyzer.dll",
#"C:\users\myname\.nuget\packages\microsoft.codequality.analyzers\3.0.0\analyzers\dotnet\cs\Humanizer.dll",
#"C:\users\myname\.nuget\packages\microsoft.codequality.analyzers\3.0.0\analyzers\dotnet\cs\Microsoft.CodeQuality.Analyzers.dll",
#"C:\users\myname\.nuget\packages\microsoft.codequality.analyzers\3.0.0\analyzers\dotnet\cs\Microsoft.CodeQuality.CSharp.Analyzers.dll",
#"C:\users\myname\.nuget\packages\microsoft.netcore.analyzers\3.0.0\analyzers\dotnet\cs\Microsoft.NetCore.Analyzers.dll",
#"C:\users\myname\.nuget\packages\microsoft.netcore.analyzers\3.0.0\analyzers\dotnet\cs\Microsoft.NetCore.CSharp.Analyzers.dll",
#"C:\users\myname\.nuget\packages\microsoft.netframework.analyzers\3.0.0\analyzers\dotnet\cs\Microsoft.NetFramework.Analyzers.dll",
#"C:\users\myname\.nuget\packages\microsoft.netframework.analyzers\3.0.0\analyzers\dotnet\cs\Microsoft.NetFramework.CSharp.Analyzers.dll",
};
foreach (string lib in libraries)
{
XElement analyzer = new XElement(ns+"Analyzer");
analyzer.SetAttributeValue("Include", lib);
newGroup.AddFirst(analyzer);
}
Console.WriteLine(root.Elements().Last().ToString());
root.Elements().Last().AddAfterSelf(newGroup);
root.Save(file, SaveOptions.None);
// and do we need to include the error checking target?
}
As far as I can tell, it works, though I have no idea what would happen if you tried to do it on a solution that already has the analyzers installed normally.
Running the FxCop analyzers through msbuild seems inefficient, but I haven't found a better way to do it. They look like they're built to only work within a compiler. I hope I'm wrong, and I would still appreciate any advice on how to run the analyzers automatically without having to build the whole project.
This question is based in (ILSpy, how to resolve dependencies?)
Well, the ILSpy library changed and now we don't have Ast Builder, like the most answers about this.
The instance new ICSharpDecompiler have a overload that can take a ModuleDefinition of Mono.Cecil, but I don't know if this ModuleDefinition is the new "Resolver" for this issue.
In the resume I need to decompile a assembly (C#, .dll) that I don't have the dependecies (dll), I need to read the assembly using CSharpDecompiler decompiler = new CSharpDecompiler(dll.Name + ".dll", new DecompilerSettings()); without have the dependencies, how can I do that?
I got the solution making a simple:
CSharpDecompiler decompiler = new CSharpDecompiler("name.dll", new DecompilerSettings() {ThrowOnAssemblyResolveErrors = false})
This will ignore the dependencies but the types with references will not be read.
I'm trying to add custom properties to CodeDOM output, such as file version, author, etc. I'm unsure how.
For the file version, you have to use AssemblyFileVersion attribute.
See the example.
CodeCompileUnit unit = CreateMyUnit();
var attribute = new CodeAttributeDeclaration(
new CodeTypeReference(typeof(AssemblyFileVersionAttribute)));
attribute.Arguments.Add(
new CodeAttributeArgument(
new CodePrimitiveExpression("1.1.1.1")));
unit.AssemblyCustomAttributes.Add(attribute);
As for the author, you may do the similar thing. See the MSDN assembly attribute.
EDIT:
You need add the references.
using System.CodeDom;
using System.CodeDom.Compiler;
After having created a Typed DataSet for a given set of database tables (using System.Data.Design.TypedDataSetGenerator).
I can attach the generated C# file with
// VsProj is of type VsLangProj.VSProject for the current project
// artifactPath is the path to the newly created C# artifact with the
// typeddataset generated
// code.
VsProj.Project.ProjectItems.AddFromFile(artifactPath);
However when trying to open this in the designer it fails (it is certainly missing the .xsd, .xsc, .xss files).
Is there a documented way to get the .xsc / .xss files?
Ok, I found it, instead of using System.Data.Design.TypedDataSetGenerator, just set some magic properties for the ProjectItem and voila:
// xsdPath is a path to a .xsd file which was generated with System.Data.DataSet.WriteXmlSchema.
ProjectItem pi = _vsProj.Project.ProjectItems.AddFromFile(xsdPath);
// this little magic replaces having to use System.Data.Design.TypedDataSetGenerator
pi.Properties.Item("SubType").Value = "Designer";
pi.Properties.Item("CustomTool").Value = "MSDataSetGenerator";
(Of course if you were outside of Visual Studio, then it's better the previous method).
Is there a way to find out the assembly name at design-time (i.e. not using reflection or runtime APIs such as System.Reflection.Assembly.GetEntryAssembly) from within Visual Studio?
The scenario requires a tool to get the assembly name that a Visual Studio project will eventually compile into.
This is like parsing the AssemblyName property of the .csproj - I am wondering if there are any APIs that can give this information reliably.
Please do not respond back with runtime APIs that use reflection - there is no assembly file present at the time I need the assembly name - just the metadata of the assembly in the csproj file.
if you are calling the tool via a post/pre-build event, this data is very easy to access.
Just go to the "project properties->Build Events" tab, then select either "edit pre-build" or "edit post-build", depending on when you want the tool to run. This should bring up an edit window with the ever helpful "Macros >>" button. Press this and you will be given a heap of macros to use and should be pretty much everything you need.
The "API" you could use is LINQ to XML after all the .csproj file is just xml. (and you can get the location of the .csproj file if you need from the solution file which for some reason is not XML but can be easily parsed)
You can use "TargetName" available in Macros for Post-build events. It will give you the assembly name for your project.
After a quick run through MSDN I found this article which might be a good start for some further research:
Accessing Project Type Specific Project, Project Item, and Configuration Properties
I think you will need to write some regular expression that will give you the value of "AssemblyTitle" attribute in AssemblyInfo.cs file.
Something like this:
public class Assembly
{
public static string GetTitle (string fileFullName) {
var contents = File.ReadAllText (fileFullName); //may raise exception if file doesn't exist
//regex string is: AssemblyTitle\x20*\(\x20*"(?<Title>.*)"\x20*\)
//loading from settings because it is annoying to type it in editor
var reg = new Regex (Settings.Default.Expression);
var match = reg.Match (contents);
var titleGroup = match.Groups["Title"];
return (match.Success && titleGroup.Success) ? titleGroup.Value : String.Empty;
}
}