We have created solution like the one below and added the default project after creating solution. Please refer code below
Type visualStudioType = Type.GetTypeFromProgID("VisualStudio.DTE.12.0", true);
DTE env = Activator.CreateInstance(visualStudioType, true) as DTE;
ServiceProvider serviceProvider = new ServiceProvider(env as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
DTE dte = (DTE)serviceProvider.GetService(typeof(DTE));
Object obj = System.Activator.CreateInstance(visualStudioType, true);
EnvDTE80.DTE2 dte8Obj = (EnvDTE80.DTE2)obj;
Solution2 soln = (Solution2)dte8Obj.Solution;
1.I get exception like below, When create project solution.
2.After create project, We cannot able to convert project as VSProject. Its showing exception like below.
Please give solution for resolve above mention issues .
Your code can be simplified to:
Type visualStudioType = Type.GetTypeFromProgID("VisualStudio.DTE.12.0", true);
EnvDTE80.DTE2 dte2 = Activator.CreateInstance(visualStudioType, true) as EnvDTE80.DTE2;
EnvDTE80.Solution2 soln = dte2.Solution as EnvDTE80.Solution2;
Regarding the error locating EnvDTE version 7.0.3300.0 see:
Error When EnvDTE Is Used with VSLangProj Assemblies
Related
I am trying to compile razor html templates for the usage in a webbrowser control in Microsoft .net Framework 4 Development. Everything is fine until I want to call "codeProvider.GenerateCodeFromCompileUnit". The IDE says that the type reference to type CodeCompileUnit is mssing in System, even though I am able to declare a CodeCompileUnit on my own ...
I already checked the references, cleaned the solution, tried to restart the IDE and stuff like that but nothing seems to fix the problem.
I don't really know how to go on. Here is the current code:
public static Assembly Compile(IEnumerable<RazorTemplateModel> models)
{
var builder = new StringBuilder();
var codeProvider = new CSharpCodeProvider();
using (var writer = new StringWriter(builder))
{
foreach (var razorTemplateModel in models)
{
GeneratorResults generatorResults = GenerateCode(razorTemplateModel);
codeProvider.GenerateCodeFromCompileUnit(generatorResults.GeneratedCode, writer, new CodeGeneratorOptions());
}
}
var result = codeProvider.CompileAssemblyFromSource(BuildCompilerParameters(), new[] { builder.ToString() });
if (result.Errors != null && result.Errors.Count > 0)
throw new RazorTemplateCompileException(result.Errors, builder.ToString());
return result.CompiledAssembly;
}
The following error message is shown for Line 10 of the code:
ErrorMessage
Here is a screenshot of my System references in the project:
SystemReferences
Can anybody help?
Edit: Forgot to mention that I am using the references in an Mono.Android Project with Xamarin.Android.Support.v4
That's present under System.CodeDOM namespace and so you will have to add using System.CodeDOM; probably. See https://msdn.microsoft.com/en-us/library/system.codedom.codecompileunit(v=vs.110).aspx
Also, can you check the version of System dll you have referenced.
I created one console application to create visual studio project pragmatically, here i am not able install Nuget packages, always
var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel)); statement returns null values. for your reference i added my code below. Help me to resolve this issue.
static void Main(string[] args)
{
//InstallNuGetPackages.InstallNuGet("");
string ProjectName = "WebAPIProj";
string SolutionName = "EmptyTemplate";
System.Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.11.0");
Object obj = System.Activator.CreateInstance(type, true);
EnvDTE.DTE dte = (EnvDTE.DTE)obj;
dte.MainWindow.Visible = true; // optional if you want to See VS doing its thing
// create a new solution
dte.Solution.Create("C:\\"+ SolutionName + "\\", SolutionName);
var solution = dte.Solution;
// create a C# WinForms app
solution.AddFromTemplate(#"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ProjectTemplatesCache\CSharp\Web\1033\EmptyWebApplicationProject40\EmptyWebApplicationProject40.vstemplate",
#"C:\NewSolution\"+ ProjectName, ProjectName);
InstallNuGetPackages.InstallNuGet(dte);
foreach (var p in dte.Solution.Projects)
{
InstallNuGetPackages.InstallNuGet((Project)p, "Microsoft.AspNet.WebApi version1.1");
}
// save and quit
dte.ExecuteCommand("File.SaveAll");
dte.Quit();
}
Code to install Nuget Packages
public bool InstallNuGetPackage(Project project, string package)
{
bool installedPkg = true;
try
{
var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel)); //Always this statement returns null
IVsPackageInstallerServices installerServices = componentModel.GetService();
if (!installerServices.IsPackageInstalled(project, package))
{
var installer = componentModel.GetService();
installer.InstallPackage(null, project, package, (System.Version)null, false);
}
}
catch (Exception ex)
{
installedPkg = false;
}
return installedPkg;
}
(Turned this into an answer for better readability and more room)
created one console application - you only have access to the ServiceProvider from Visual Studio if you run your code inside of it, i.e. from an extension and/or package.
Running this from a console application cannot work. Visual Studio internally does a lot more setup for all the services and general environment than creating an instance of DTE.
To persue your route, although I'm not sure how feasible that is, invoke nuget.exe or NuGet.Core code to achieve similar.
Is it possible to allow dynamically generated assemblies to access dependencies that exist in the project that generates the new assembly? I am working with Unity and C#, and I add an assembly that contains dependencies that exist in the project it now belongs to, but I get this error: FileNotFoundException: Could not load file or assembly 'ModAssembly000.dll' or one of its dependencies . I get this error because I try to put 'using UnityEngine' at the top of the script. This is the code that already exists in the project that gets the new assembly and invokes a method:
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
parameters.OutputAssembly = generatedName;
CompilerResults r = CodeDomProvider.CreateProvider("CSharp").CompileAssemblyFromFile(parameters, filePath);
r.CompiledAssembly.GetType("ModData").GetMethod("Run").Invoke(null, BindingFlags.Static, null, null, null);
This is the source for the dynamically created assembly:
using UnityEngine;
public class ModData {
public static string modName = "Super kool mod";
public static string modVersion = "1.2.1";
public static void Run() {
Debug.Log("it worked :D");
}
}
UnityEngine (thus, Debug.Log) exists in the code that is generating this assembly. Is there a way I can get the new created assembly to use the UnityEngine that exists above it so that I could allow the new code to do anything in the project above it? I know ModAssembly000.dll exists because if I remove the 'using UnityEngine' line, then I can access the static string filds of the dynamic assembly without issue.
My guess is that you need to add Unity to the list of referenced assemblies:
parameters.ReferencedAssemblies.Add("UnityEngine.dll");
Here is what I'm trying to do:
Create an executable that loads the Visual Studio DTE
Access methods of an Addin that is loaded
Here is my code, as followed loosely from this blog.
[STAThread]
static void Main(string[] args)
{
EnvDTE80.DTE2 dte;
object obj = null;
System.Type t = null;
MessageFilter.Register();
// Get the ProgID for DTE 10.0.
t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0", true);
obj = System.Activator.CreateInstance(t, true);
var addin = GetAddInByProgID(dte, "MyAddin");
if (addin != null)
{
addin.Connected = true;
var connectObj = addin.Object;
var conObjType = connectObj.GetType();
var methods = conObjType.GetMethods(); // mscorlib methods
var asm = conObjType.Assembly; // is mscorlib
}
...
}
The problem I'm running into is I can't get access to the Addin's assembly. It appears that conObjType's assembly is mscorlib - but I want access to Myaddin.dll. Any ideas?
Any 3rd party add-in may not expose any method at all other than those required to implement the add-in interface (OnConnection, etc.). Its methods can be internal (not public) or even can be obfuscated.
If it is your add-in, a better approach would be that the add-in provides commands to perform actions, and given your external DTE instance, you can call DTE.ExecuteCommand("MyAddIn.MyCommand").
<## template debug="true" hostspecific="true" language="C#" #>
<## assembly name="EnvDTE80" #>
<## include file="T4Toolbox.tt" #>
<#
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)serviceProvider.GetService(typeof(EnvDTE.DTE));
//add a file to a project and add its dependupon build property.
//I want to refresh teh solution explorer window to show the hierarchy between 2 files
//You will see this kind of relationship between Forms.cs and Form1.Designer.cs files.
EnvDTE.UIHierarchy solExplorer = dte.ToolWindows.SolutionExplorer;
solExplorer.Parent.Activate();
dte.ExecuteCommand("View.Refresh", string.Empty);
I am trying to refresh the solution explorer's tool window so I can see the newly created files nested. I know that T4 templates are executed in one application domain and calls are made into Visual Studio Appdomain using remoting. I am getting this error about serialization.
So is there a way I can refresh solution explorer tool window (solExplorer.Parent) by first activating it (I was told).
Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase' in Assembly 'Microsoft.VisualStudio.Platform.WindowManagement, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.
Update: Based on Gereth's comment.
Thanks, Gereth I tried this, but it returns COMException,
I don't have an error about Serialization of Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase class and Activate method seems to have succeded. The error is now on dte.ExecuteCommand method.
//object dteObject = GetCOMService(serviceProvider, typeof(EnvDTE80.DTE2));
object dteObject1 = GetCOMService(serviceProvider, typeof(EnvDTE.DTE));
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)dteObject1;
COMException raised when executing this line:
dte.ExecuteCommand("View.Refresh", string.Empty);
Message "Error HRESULT E_FAIL has been returned from a call to a COM component."
Source "EnvDTE80"
StackTrace "at EnvDTE80.DTE2.ExecuteCommand(String CommandName, String CommandArgs)
ErrorCode -2147467259
What to try next?
Thanks
Rad
There's a section of DTE commands that don't stay with COM marshaling once the CLR notices that both ends of the remoting pipe are written in managed code. However, given these components are not actually set up to be .Net remotable, but ARE set up to be COM remotable, this type of error occurs.
In general, if the COM marshaling on the particular DTE object in question is set up correctly, you should be able to use the following code to get moving again.
Call it instead of your vanilla service call to get the DTE.
public static Object GetCOMService(IServiceProvider provider, Type type)
{
Object ret;
ret = provider.GetService(type);
if (ret == null)
{
return ret;
}
try
{
return Marshal.GetObjectForIUnknown(Marshal.GetIUnknownForObject(ret));
}
catch (Exception)
{
return ret;
}
}
I finally got this to work by unloading and reloading the project. The project has to be selected in the Solution Explorer otherwise you'll get a COMException.
IServiceProvider hostServiceProvider = (IServiceProvider)Host;
// see #GarethJ's answer for the following
DTE2 dte2 = GetCOMService(hostServiceProvider, typeof(EnvDTE.DTE)) as DTE2;
object dteObject1 = GetCOMService(hostServiceProvider, typeof(EnvDTE.DTE));
EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)dteObject1;
var solExplorer = dte2.ToolWindows.SolutionExplorer;
solExplorer.Parent.Activate();
ProjectItem containingProjectItem = dte2.Solution.FindProjectItem(templateFile);
Project project = containingProjectItem.ContainingProject;
UIHierarchy solExplorerHierarchy = solExplorer.Parent.Object as UIHierarchy;
string projectSolutionPath = Path.Combine(dte2.Solution.Properties.Item("Name").Value.ToString(), project.Name);
var projectItem = solExplorerHierarchy.GetItem(projectSolutionPath);
projectItem.Select(vsUISelectionType.vsUISelectionTypeSelect);
dte2.ExecuteCommand("Project.UnloadProject", "");
dte2.ExecuteCommand("Project.ReloadProject", "");
And then any newly created nested items appear. I'm using VS2012 and T4Toolbox 11.7.
Thank you Gareth. Your solution works very well.
I have extended my "GetService" method:
private T GetService<T>(Type type) where T : class
{
IServiceProvider hostServiceProvider = (IServiceProvider)Host;
if (hostServiceProvider == null)
{
throw new Exception("Host property returned unexpected value (null)");
}
object serviceObj = hostServiceProvider.GetService(type);
try
{
serviceObj = Marshal.GetObjectForIUnknown(Marshal.GetIUnknownForObject(serviceObj));
}
catch (Exception) { }
T service = serviceObj as T;
if (service == null)
{
throw new Exception("Unable to retrieve service");
}
return service;
}