resharper code analysis using Command line tool (inspectcode.exe) - c#

In My C# language sln file contains two projects. first project has the actual code & second project has the unittest cases for the first project. but while am doing the resharper code analysis using Command line tool (inspectcode.exe).
for both project resharper doing the inspection in the unit test project only, not on the Actual code file.
'
package org.sonar.plugins.resharper;
import java.io.File;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.command.Command;
import org.sonar.api.utils.command.CommandException;
import org.sonar.api.utils.command.CommandExecutor;
public class ReSharperExecutor
{
private static final Logger LOG = LoggerFactory.getLogger(ReSharperExecutor.class);
public void execute(String executable, String project, String solutionFile, File rulesetFile, File reportFile, int timeout)
{
Command cmd = Command.create(getExecutable(executable)).addArgument("/output=" + reportFile.getAbsolutePath()).addArgument("/no-swea").addArgument("/project=" + project).addArgument("/profile=" + rulesetFile.getAbsolutePath()).addArgument("/no-buildin-settings").addArgument(solutionFile);
int exitCode = CommandExecutor.create().execute(cmd, TimeUnit.MINUTES.toMillis(timeout));
if (exitCode != 0) {
throw new CommandException(cmd, "ReSharper execution failed with exit code: " + exitCode, null);
}
}
private static String getExecutable(String propertyValue)
{
String execName = "inspectcode.exe";
if (!propertyValue.endsWith(execName)) {
return new File(propertyValue, execName).getAbsolutePath();
}
return propertyValue;
}
}'
Where I need to do the change to do the Resharper analysis for the Actual code.
Executing command: cd:/inspectcode.exe /output=cd:\resharper-report.xml /no-swea /project=* /profile=cd:.sonar\resharper-sonarqube.DotSettings /no-buildin-settings cd:\XXXX.sln

The above issue was caused bcoz the VS build version different in the
1.project built machine(VS2015) &
2.project analysis happening machine(VS2013),
so its not show any error details in log of the machine 2.
After testing the analysis in the built machine i got the root cause of the issue(Few of the dependency library of the project was missed which should be availble under MSBuild folder{Msbuildfolder->Microsoft->visualstudio->version}) & fixed it(by replacing the missing dll's).
Now Analysis running successfully.

Related

Codegeneration at runtime from a string to console exe is not working in C# .NET6

I have some code which must be able to generated a console application at runtime (Codegeneration with System.CodeDom). I did this already a lot, but in NET 6 now I am struggling with that and the new API. In the code below I try to compile simply from a string. See below the static class with method Start() which then should generates the application.
The compilations seems fine, no errors at the end. But when starting the generated AppCodegenerated.exe, it shows some reference exception with System.Runtime.
Please help, any Idea? Already researched a lot but could not find any useful solution..
//-
I used the Visual Studio 2022 / NET 6 and theses Nuget's:
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace CompilerSimplified
{
public static class Compiler
{
public static bool Start()
{
string FileName = "AppCodegenerated";
string ExePath = AppDomain.CurrentDomain.BaseDirectory + #"\" + FileName + ".exe";
string code = #"using System; Console.WriteLine(""Hello.""); Console.ReadLine(); ";
// ------- References -------------
// .net platform references
List<MetadataReference> References = new List<MetadataReference>();
foreach (var item in ReferenceAssemblies.Net60) // ReferenceAssemblies from Nuget: Basic.Reference.Assemblies;
References.Add(item);
// or tried this: loop manually through system platform
//string[] fileEntries = Directory.GetFiles(#"C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.0\ref\net6.0\", "*.dll");
//foreach (string fileName in fileEntries)
// references.Add(MetadataReference.CreateFromFile(fileName));MetadataReference.CreateFromFile(fileName));
// ------- References END -------------
// delete existing file
if (File.Exists(ExePath))
File.Delete(ExePath);
// compiler options
CSharpCompilationOptions DefaultCompilationOptions =
new CSharpCompilationOptions(outputKind: OutputKind.ConsoleApplication, platform: Platform.AnyCpu)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release);
// encode soucre code
string sourceCode = SourceText.From(code, Encoding.UTF8).ToString();
// CSharp options
var parsedSyntaxTree = Parse(sourceCode, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp10));
// compilation
var compilation = CSharpCompilation.Create(FileName, new SyntaxTree[] { parsedSyntaxTree }, references: References, DefaultCompilationOptions);
var result = compilation.Emit(ExePath);
// return
if (result.Success)
return true;
else
return false;
}
private static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions options = null)
{
var stringText = SourceText.From(text, Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(stringText, options, filename);
}
}
}
Above code runs fine without error and exports the AppCodegenerated.exe into the project /bin folder.
Execution of this generated AppCodegenerated.exe shows following on the output console:
Unhandled exception: System.IO.FileNotFoundException:
The file or assembly "System.Runtime, Version = 6.0.0.0, Culture = neutral,
PublicKeyToken = b03f5f7f11d50a3a" or a dependency on it was not found.
The system can not find the stated file.
It is not possible to codegenerate directly a console application like the initial approach above. One possible solution is to generate first a dll (what I mentioned above in the example code is working fine), and from there include that .dll into a .exe, from where the functionality can run.

xsd to class (C#) in visual studio 2019

I am following a tutorial, in one step it opens "VS2012 arm cross tools command prompt" and executes
xsd file.xsd /classes
I can't find "VS2012 arm cross tools command prompt" on my computer (my guess it's because I'm using VS2019) so I open the "Developer command prompt for VS 2019" instead, but when I run the command, I get an error:
"xsd" is not recognized as an internal or external command, program or executable batch file
Can someone tell me how I can create a class from an xsd file in VS 2019? Thank you for your time.
Once you have installed the Windows SDK. The following could be of help to you...it is .NET Core. Browse to the xsd.exe and add a reference to it in VS 2019.
class Program
{
static void Main(string[] args)
{
var rgs = new string[]
{
#"PathToYourDLL\My.dll",
"/type:ClassNameToGen"
};
AppDomain.CurrentDomain.FirstChanceException += (s, e) =>
{
string error = e.Exception.ToString();
var typeLoadException = e.Exception as ReflectionTypeLoadException;
if (typeLoadException != null)
{
foreach (var exception in typeLoadException.LoaderExceptions)
{
error += Environment.NewLine + Environment.NewLine + exception.ToString();
}
}
Console.WriteLine(error);
};
XsdTool.Xsd.Main(rgs);
Console.ReadLine();
}
}

Create solution file(.sln) and project files(.csproj) dynamically

I am creating code generation tool (auto code generation based on table structure) as a Windows forms application in Visual Studio 2012 using .NET Framework 4.0. It's generating the portable object, controller, WCF services and business logic code files.
All code files bundle in the appropriate project and all project bundle in one solution. The solution and projects need to create dynamically through program.
I have tried to create the solution and project using Visual Studio Add-in project. It is working fine in Add-In project (separate solution). The OnConnection method call automatically in Add-in project. Now I want to implements this in my code generation tool. While debugging in Add-In project the application variable shown like COM object.
I am tried to pass the value for OnConnection method from code generation tool, it throws an error (I passed this object for application variable). I really don't know how to call this method from my code generation tool. Anyone help this?
Code
private DTE2 _applicationObject;
private AddIn _addInInstance;
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
createProjectsFromTemplates(_applicationObject);
}
public void createProjectsFromTemplates(DTE2 dte)
{
try
{
Solution2 soln = (Solution2)dte.Solution;
string csTemplatePath;
string csPrjPath = "SamplePath\\TestCreateProject";
csTemplatePath = soln.GetProjectTemplate("WpfApplication.zip", "CSharp");
System.Windows.Forms.MessageBox.Show("C# template path: " + csTemplatePath);
soln.AddFromTemplate(csTemplatePath, csPrjPath, "NewWCFCSharpAutoGeneratorProject", false);
Project prj;
ProjectItem prjItem;
String itemPath;
// Point to the first project (the Visual Basic project).
prj = soln.Projects.Item(1);
prjItem = prj.ProjectItems.AddFromFileCopy("SampelCSharp.cs");
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("ERROR: " + ex.Message);
}
}
You can instantiate a VS from the host application and generate the files. Hope that will work. The below code works well for me.
Use the following namespaces to get work the below given code.
Namespaces:
using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
Code:
EnvDTE80.DTE2 dte2;
dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.11.0");
Connect objConnect = new Connect();
Array objArray = null;
objConnect.OnConnection(dte2, ext_ConnectMode.ext_cm_UISetup, null, ref objArray);
I got this reference it is really useful.
http://rcos.rpi.edu/projects/unmake/commit/programmatically-launch-devenv-generate-a-solution-and-save-it/
You can use this. This is for .cs project files and framewwork above .NET 2.0 versions. VB project sources are not compatible.
protected void Build(string project)
{
Engine engine = new Engine();
BuildPropertyGroup properties = new BuildPropertyGroup();
properties.SetProperty(#"Configuration", #"Debug");
// Point to the path that contains the .NET Framework 2.0 CLR and tools
engine.BinPath = #"c:\windows\microsoft.net\framework\v3.5";
// Instantiate a new FileLogger to generate build log
FileLogger logger = new FileLogger();
// Set the logfile parameter to indicate the log destination
string str = #"logfile=D:\temp";
str += project.Substring(project.LastIndexOf("\\"), project.LastIndexOf(".") - project.LastIndexOf("\\")) + ".log";
logger.Parameters = str;
// Register the logger with the engine
engine.RegisterLogger(logger);
// Build a project file
bool success = engine.BuildProjectFile(project, new string[] { "build" }, properties);
//Unregister all loggers to close the log file
engine.UnregisterAllLoggers();
using (BinaryWriter writer = new BinaryWriter(File.Open(#"D:\temp\Prj.log", FileMode.Append)))
{
if (success)
{
writer.Write("\nBuild Success :" + project.Substring(project.LastIndexOf("\\")));
}
else
{
writer.Write("\nBuild Fail :" + project.Substring(project.LastIndexOf("\\")));
}
}
}

Print the source filename and linenumber in C#

Is there any way to retrieve the current source filename and linenumber in C# code and print that value in the console output? Like LINE and FILE in C?
Please advise.
Many thanks
Anders Hejlsberg presented new API for that in BUILD keynote:
Print current file name, method name and line number
private static void Log(string text,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
Console.WriteLine("{0}_{1}({2}): {3}", Path.GetFileName(file), member, line, text);
}
Test:
Log(".NET rocks!");
Output:
Program.cs_Main(11): .NET rocks!
What's going on here?
You define a method with optional parameters and decorate them with special attributes. If you call method without passing actual arguments (leave defaults) - the Framework populates them for you.
This answer is outdated! See #taras' answer for more recent information.
No constant :(
What you can do is a lot uglier :
string currentFile = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName();
int currentLine = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileLineNumber();
Works only when PDB files are available.
You can use the StackTrace object from the System.Diagnostics namespace but the information will only be available if the PDB files are there.
PDB files are generated by default for both the Debug and Release builds the only difference is that Debug is setup to generate a full debug info where as the Release build is setup to only generate a pdb (full/pdb-only).
Console.WriteLine(new StackTrace(true).GetFrame(0).GetFileName());
Console.WriteLine(new StackTrace(true).GetFrame(0).GetFileLineNumber());
There are no constants defined for that as of now.
The .NET way of doing it is using StackTrace class.
It however works only for Debug builds. So in case you use it, you can have the code using StackTrace between
#if DEBUG
//your StackTrace code here
#endif
You can read about using #if preprocessors for your DEBUG vs. RELEASE builds in the following Stackoverflow thread.
C# if/then directives for debug vs release
EDIT: Just in case you still need this debugging information in release builds, read the following answer on Stackoverflow:
Display lines number in Stack Trace for .NET assembly in Release mode
If you want some more internal detail, but you don't specifically need filename and line number, you can do something like this:
System.Diagnostics.Debug.Print(this.GetType().ToString() + " My Message");
This has an advantage over printing out the filename in that if you put this in a parent class, it will print out the child class name that is actually running the code.
If you wanted to write your own version of Debug.Assert, then here's a more complete answer:
// CC0, Public Domain
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System;
public static class Logger {
[Conditional("DEBUG")]
public static void Assert(bool condition, string msg,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0
)
{
// Debug.Assert opens a msg box and Trace only appears in
// a debugger, so implement our own.
if (!condition)
{
// Roughly follow style of C# error messages:
// > ideone.cs(14,11): error CS1585: Member modifier 'static' must precede the member type and name
Console.WriteLine($"{file}({line}): assert: in {member}: {msg}");
// Or more precisely match style with a fake error so error-parsing tools will detect it:
// Console.WriteLine($"{file}({line}): warning CS0: {msg}");
}
}
}
class Program {
static void Main(string[] args) {
Logger.Assert(1+1 == 4, "Why not!");
}
}
Try it online.

How to deploy a visual studio custom tool?

I have my own custom tool for Visual Studio 2008 SP1. It consists of 5 assemblies: 3 assemblies with code that are used heavily in my other projects, 1 assembly-wrapper above VS2008 SDK and an assembly with the tool.
If I'd debug my tool from visual studio, using "Run external program" option with command line "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" and arguments "/ranu /rootsuffix Exp" all works perfectly.
After that I'm trying to deploy it to my working VS copy, not to experimental hive, doing: gacutil /i Asm1.dll for all my assemblies and doing RegAsm Asm1.dll only for assembly with custom tool. Neither of utils prints any error, all work as planned, even registry keys appear. But my tool doesn't work (error occurred "Cannot find custom tool 'TransportGeneratorTool' on this system") even after PC restart. What did I do wrong?
Wrapper looks like that:
[ComVisible(true)]
public abstract class CustomToolBase : IVsSingleFileGenerator, IObjectWithSite
{
#region IVsSingleFileGenerator Members
int IVsSingleFileGenerator.DefaultExtension(out string pbstrDefaultExtension)
{
pbstrDefaultExtension = ".cs";
return 0;
}
int IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
{
GenerationEventArgs gea = new GenerationEventArgs(
bstrInputFileContents,
wszInputFilePath,
wszDefaultNamespace,
new ServiceProvider(Site as Microsoft.VisualStudio.OLE.Interop.IServiceProvider)
.GetService(typeof(ProjectItem)) as ProjectItem,
new GenerationProgressFacade(pGenerateProgress)
);
if (OnGenerateCode != null)
{
OnGenerateCode(this, gea);
}
byte[] bytes = gea.GetOutputCodeBytes();
int outputLength = bytes.Length;
rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(outputLength);
Marshal.Copy(bytes, 0, rgbOutputFileContents[0], outputLength);
pcbOutput = (uint)outputLength;
return VSConstants.S_OK;
}
#endregion
#region IObjectWithSite Members
void IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppvSite)
{
IntPtr pUnk = Marshal.GetIUnknownForObject(Site);
IntPtr intPointer = IntPtr.Zero;
Marshal.QueryInterface(pUnk, ref riid, out intPointer);
ppvSite = intPointer;
}
void IObjectWithSite.SetSite(object pUnkSite)
{
Site = pUnkSite;
}
#endregion
#region Public Members
public object Site { get; private set; }
public event EventHandler<GenerationEventArgs> OnGenerateCode;
[ComRegisterFunction]
public static void Register(Type type)
{
using (var parent = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\VisualStudio\9.0", true))
foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
ourData.Register(x => parent.CreateSubKey(x), (x, name, value) => x.SetValue(name, value));
}
[ComUnregisterFunction]
public static void Unregister(Type type)
{
using (var parent = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\VisualStudio\9.0", true))
foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
ourData.Unregister(x => parent.DeleteSubKey(x, false));
}
#endregion
}
My tool code:
[ComVisible(true)]
[Guid("55A6C192-D29F-4e22-84DA-DBAF314ED5C3")]
[CustomToolRegistration(ToolName, typeof(TransportGeneratorTool))]
[ProvideObject(typeof(TransportGeneratorTool))]
public class TransportGeneratorTool : CustomToolBase
{
private const string ToolName = "TransportGeneratorTool";
public TransportGeneratorTool()
{
OnGenerateCode += GenerateCode;
}
private static void GenerateCode(object s, GenerationEventArgs e)
{
try
{
var serializer = new XmlSerializer(typeof (Parser.System));
using (var reader = new StringReader(e.InputText))
using (var writer = new StringWriter(e.OutputCode))
{
Generator.System = (Parser.System) serializer.Deserialize(reader);
Generator.System.Namespace = e.Namespace;
Generator.GenerateSource(writer);
}
}
catch (Exception ex)
{
e.Progress.GenerateError(ex.ToString());
}
}
}
Resulting registry keys:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\TransportGeneratorTool]
#="TransportGeneratorTool"
"CLSID"="{55a6c192-d29f-4e22-84da-dbaf314ed5c3}"
"GeneratesDesignTimeSource"=dword:00000001
"GeneratesSharedDesignTimeSource"=dword:00000001
Here is the code of my custom attribute (it is in wrapper assembly):
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class CustomToolRegistrationAttribute : RegistrationAttribute
{
public CustomToolRegistrationAttribute(string name, Type customToolType)
{
Name = name;
CustomToolType = customToolType;
}
/// <summary>
/// The type that implements the custom tool. This starts
/// as MyCustomTool by default in the template.
/// </summary>
public Type CustomToolType { get; set; }
public string Name { get; set; }
#region RegistrationAttribute abstract member implementations
public override void Register(RegistrationContext context)
{
Register(x => context.CreateKey(x), (x, key, value) => x.SetValue(key, value));
}
public void Register<T>(Func<string, T> keyCreator, Action<T, string, object> valueCreator)
{
var keyName = CreateKeyName(Name);
var key = keyCreator(keyName);
valueCreator(key, string.Empty, Name);
valueCreator(key, "CLSID", CustomToolType.GUID.ToString("B"));
valueCreator(key, "GeneratesDesignTimeSource", 1);
valueCreator(key, "GeneratesSharedDesignTimeSource", 1);
var disposable = key as IDisposable;
if (disposable != null)
disposable.Dispose();
}
private static string CreateKeyName(string name)
{
return string.Format(#"Generators\{0}\{1}", vsContextGuids.vsContextGuidVCSProject, name);
}
public override void Unregister(RegistrationContext context)
{
Unregister(context.RemoveKey);
}
public void Unregister(Action<string> keyRemover)
{
keyRemover(CreateKeyName(Name));
}
#endregion
}
My solution is to make a setup project. I get the registry settings from the pkgdef file by adding the following to the csproj file of the package:
<Target Name="GeneratePackageRegistryFiles">
<Exec Command=""$(VSSDK90Install)VisualStudioIntegration\Tools\Bin\RegPkg.exe" /root:Software\Microsoft\VisualStudio\9.0 /codebase "$(TargetPath)" /regfile:"$(OutDir)$(TargetName).reg"" />
</Target>
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn);GeneratePackageRegistryFiles;</BuildDependsOn>
</PropertyGroup>
When building look in the output directory you should find a .reg file which you can import in the setup project.
Obviously you can run the regpkg.exe from the command-line if modifying the project is not an option.
This is what I ended up with last time when I struggled to get my custom tool registered.
I hope this instruction is detailed enough and covers everything so you won't spend much time fighting it. The following MSDN article was used as a starting point. http://msdn.microsoft.com/en-US/library/bb166527(v=vs.80).aspx Unfortunately you cannot use it alone. What you really need to do is:
Make sure the assembly is signed. Why? Because otherwise you won't be able to put it into GAC at step 6 below.
To sign your assembly follow these steps:
1.1. Go to the Properties screen of the project.
1.2. Once there go to the Signing tab.
1.3. Once there check the Sign the assembly checkbox.
Make sure you know the version number of your assembly. You will need this number to specify the ASSEMBLY_VERSION parameter later.
In order to get this number open the AssemblyInfo.cs file in the Properties folder of your project and look for the line starting with: [assembly: AssemblyVersion(
Make sure you know the GUID of the generator class. You will need it to specify the GENERATOR_GUID parameter later.
In order to get this GUID open the file with the generator class and look for the Guid class-attribute that decorates this class, something like: [Guid("17799E85-421B-4684-B59E-650E34ECC718")]
Build the project
Get the public token key of the assembly. In order to do that you will have to run the following command:
sn.exe -T ASSEMBLY_FILE
You will need this information later when for PUBLIC_TOKEN_KEY.
The sn.exe file can be found in C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\sn.exe
Pay attention to the version number of the framework (v8.0A) in the filepath above. It needs to be consistent with the version of the framework used to compile the project.
Put the assembly to the GAC using the following command:
gacutil.exe /i ASSEMBLY_FILE /f
Getting registered in GAC requires administrative permissions.
The gacutil.exe file can be found in C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\gacutil.exe
Pay attention to the version number of the framework (v8.0A) in the filepath above. It needs to be consistent with the version of the framework used to compile the project.
Make the following changes to the .REG (see below) file. PLEASE NOTE: that both GENERATOR_GUID and PROJECT_TYPE_GUID need to be supplied WITH curly braces: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
7.1. Fix version number of Visual Studio is used (for example: 10.0 or 9.0): VS_VERSION
7.2. Fix the GUID of the generator: GENERATOR_GUID
7.3. Fix the namespace of the assembly: NAMESPACE_NAME
7.4. Fix the generator class name: GENERATOR_TYPE_NAME
7.5. In order to register the generator the Visual Studio needs to know to which project types this generator can be applied to. So you need to get GUID's of proper project types (C#, VB.NET, etc.).
To figure out the GUID's of the project types you need to open a visual studio project file (*.csproj) in a text editor and look for GUID's in the ProjectTypeGuids XML element.
For each of these GUIDs repeat the block of last 3 entries in the .REG file replacing the PROJECT_TYPE_GUID with the a GUID just found.
7.6. Fix the extension of the file associated with the custom tool: FILE_EXTENSTION
Run the .REG file. You may need to have administrative permissions for doing this.
.REG file:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\CLSID\GENERATOR_GUID]
#="COM+ class: NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"InprocServer32"="C:\\WINDOWS\\system32\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"Assembly"="NAMESPACE_NAME, Version=ASSEMBLY_VERSION, Culture=Neutral, PublicKeyToken=PUBLIC_TOKEN_KEY"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\\.FILE_EXTENSTION]
#="GENERATOR_TYPE_NAME"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\GENERATOR_TYPE_NAME]
#="Code generator for whatever you like"
"CLSID"="GENERATOR_GUID"
"GeneratesDesignTimeSource"=dword:00000001
PS.
Sorry for not being able to make placehoders in the REG file distinct, unfortunately the text editor that StackOverflow uses cannot distinguish its markup elements from the content.

Categories