I am trying to create a visual studio package, specifically I want to create a new menu option in the items context menu. As this one:
http://www.diaryofaninja.com/blog/2014/02/18/who-said-building-visual-studio-extensions-was-hard
I already got the menu option display:
But now I want to configure the callback to create a file based on a template (custom visual studio template) like when we we click in Add > Class
But instead of use the class template, use one that I got created in my custom list. Avoiding the time to search the template in the list.
In the example that I follow to create the 'Add new service' buttom, in the first example is showed how to create a popup with:
IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell));
Guid clsid = Guid.Empty;
int result;
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
0,
ref clsid,
"NewService",
string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.ToString()),
string.Empty,
0,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
OLEMSGICON.OLEMSGICON_INFO,
0, // false
out result));
I guess that there should be more services to use with this VSPackages, but I don't found a method like that in the referece: https://msdn.microsoft.com/en-us/library/bb166217.aspx
Can you tell me from where I can found a method to perform this operation. Or how to archive my goal.
Update:
I am trying with this:
var dte = (DTE)GetService(typeof(DTE));
dte.ItemOperations.NewFile(#"General\Text File", "file.txt","7651A701-06E5-11D1-8EBD-00A0C90F26EA");
But i am getting this exception:
An exception of type 'System.Runtime.InteropServices.COMException' occurred in NewService.dll but was not handled in user code
Additional information: Invalid class string Exception from HRESULT: 0x800401F3 (CO_E_CLASSSTRING)
Solved!
I used the following piece of code:
private void MenuItemCallback(object sender, EventArgs e)
{
var dte = (DTE)GetService(typeof(DTE)) as EnvDTE80.DTE2;
var template = #"C:\Users\JuanAntonio\Documents\Visual Studio 2013\Templates\ItemTemplates\MyTemplate.vstemplate";
dte.Solution.Projects.Item(1).ProjectItems.AddFromTemplate(template, "Template.cs");
}
Related
Is there anyway that a reference can be added to a solution programmatically?
I have an add-in button, when the user presses it, I want a reference to be added.
The reason is, I have created a piece of software that I want to be integrated into any given VS program (if the developer wants it), they would simply click the add-in button and the reference would be loaded in the current solution.
Is this possible?
Something like this I haven't tested it
get the environment
EnvDTE80.DTE2 pEnv = null;
Type myType = Type.GetTypeFromProgID("VisualStudio.DTE.8.0");
pEnv = (EnvDTE80.DTE2)Activator.CreateInstance(myType, true);
get the solution.
Solution2 pSolution = (Solution2)pEnv.VS.Solution;
get the project that you want
Project pProject = pSolution.Projects[0];
add the reference
pProject.References.Add(string referenceFilePath);
There is an example on CodeProject.
The functionality is contained within a single class elRefManager and the method to call is CheckReferences. The code can be looked at here by selecting the elRefManager.cs file on the left hand side.
As seen in the article you could do...
private void button1_Click(object sender, System.EventArgs e)
{
int ec;
ec=elRefManager.CheckReferences(null, new string[] {textBox1.Text});
if (ec<0)
MessageBox.Show("An error occurred adding this reference");
if (ec>0)
MessageBox.Show("Could not add " + textBox1.Text +
"\nCheck its spelling and try again");
}
System.Assembly.load Allows you to call functions in a library that were not built with your program.
If you want to add a reference to the project so that its in the solution you can use the following. Basically the same as #Scots answer.
I did it in a macro which is vb but I'm sure you can get the idea
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
Dim objProject As EnvDTE.Project
Dim i As Long
i = DTE.Solution.Projects.Count
For Each objProject In DTE.Solution.Projects
If (objProject.Name() = "csCA") Then
Dim vsproj As VSLangProj.VSProject
vsproj = objProject.Object
vsproj.References.Add("C:\Users\test.dll")
End If
Next
I have a VS 2017 extension and have tried using my own custom Project Template, by adding it programmatically, but things aren't going so well.
In my endeavour to find the mistake, I would like to see whether it is my custom Project Template causing the problem or not. Therefore I want to programmatically add any other existing built-in VS project such as a ClassLibrary type project template.
It seems to be located here:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\ProjectTemplates\CSharp\Windows\1033\
But there isn't a zip folder and I can't create one in that directory according to Windows.
I will be using something similar to the following code:
Solution2 soln = (Solution2)visualStudioInstance.Solution;
string templatePath = soln.GetProjectTemplate("ClassLibrary.zip", "CSharp");
soln.AddFromTemplate(templatePath, projPath, "MyProjectName", false);
Am I on the right track?
I've tried it and I got an exception, but perhaps it was just because the zip folder doesn't exist.
UPDATE
The exception I get is:
"Object reference not set to an instance of an object."
I get it in the last line of the following code, when I try to add a reference to calcEngineProject. calcEngineProject is null even though it enters the if-statement and should be assigned the value of projCS.Object as VSProject2.
The code is as follows:
templatePath = soln.GetProjectTemplate("ClassLibrary.zip", "CSharp");
soln.AddFromTemplate(templatePath, prjPath, "ClassLibrary1", false);
foreach (Project p in soln.Projects)
{
if (String.Compare(p.Name, "ClassLibrary1") == 0)
{
projCS = p;
break;
}
}
if (projCS != null)
{
calcEngineProject = projCS.Object as VSProject2;
}
calcEngineProject.References.Add(Path.Combine(Config.Engine.EngineBinPath, "Engines.Calculation.dll"));
Also, I saw that templatePath is this:
"C:\PROGRAM FILES (X86)\MICROSOFT VISUAL
STUDIO\2017\PROFESSIONAL\COMMON7\IDE\EXTENSIONS\EYXTAMKA.FB4\ProjectTemplates\CSharp\.NET
Standard\1033\ClassLibrary\ClassLibrary.vstemplate"
and not
\%USERPROFILE%\Documents\My Exported Templates\
as mentioned in Upgrading custom project template
How can I create a command in a VSPackage that creates a new solution with a new project (C# Class Library) in it, containing 1 .cs file?
It is not very straighforward but there is an interesting guide on MSDN that explains how to do it. It is for an Add-in but in a VSPackage you have the same set of Visual Studio DTE objects available (the DTE application).
You can define a method that uses GetProjectTemplate and AddFromTemplate to create two console projects. You can define in the method Initialize of your VSPackage class a OLE menu command (if that is what you are looking for):
protected override void Initialize()
{
//// Create the command for the menu item.
var aCommand = new CommandID(GuidList.GuidCmdSet, (int)PkgCmdIdList.CmdId);
var menuItemEnable = new OleMenuCommand((s, e) => createProjectsFromTemplates(), aCommand);
}
And then define a method associated to the command (createProjectsFromTemplates in this case) that creates a solution with a project:
private DTE2 _mApplicationObject;
public DTE2 ApplicationObject
{
get
{
if (_mApplicationObject != null) return _mApplicationObject;
// Get an instance of the currently running Visual Studio IDE
var dte = (DTE)GetService(typeof(DTE));
_mApplicationObject = dte as DTE2;
return _mApplicationObject;
}
}
public void createProjectsFromTemplates()
{
try
{
// Create a solution with two projects in it, based on project
// templates.
Solution2 soln = (Solution2)ApplicationObject.Solution;
string csTemplatePath;
string csPrjPath = "C:\\UserFiles\\user1\\addins\\MyCSProject";
// Get the project template path for a C# console project.
// Console Application is the template name that appears in
// the right pane. "CSharp" is the Language(vstemplate) as seen
// in the registry.
csTemplatePath = soln.GetProjectTemplate(#"Windows\ClassLibrary\ClassLibrary.vstemplate",
"CSharp");
System.Windows.Forms.MessageBox.Show("C# template path: " +
csTemplatePath);
// Create a new C# console project using the template obtained
// above.
soln.AddFromTemplate(csTemplatePath, csPrjPath, "New CSharp
Console Project", false);
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("ERROR: " + ex.Message);
}
}
For Visual Studio versions after 10.0 the zip for template projects is not available anymore. The .vstemplate must be referenced and it is possible to find all the project templates under the folder:
C:\Program Files (x86)\Microsoft Visual Studio 1x.0\Common7\IDE\ProjectTemplates\
More info on this MSDN link.
The method should create a solution with one C# project based on the c# project template (e.g. containing class1.cs as initial file).
You can define your own template as well if you wish and create a solution based on that custom template. Here is a guide from MSDN on how to create custom templates.
hope it helps.
When I try to build my WPF project I get the folowing error:Samotorcan.Client.WPF.Windows8\Views\MainWindow.xaml(1,17): error MC3074: The tag 'Window' does not exist in XML namespace 'clr-namespace:Samotorcan.Client.WPF.Windows8.Controls'. Line 1 Position 17.The problem only occurs when I try to use linq. If I have a line like this new List<object>().ToArray<object>(); somewhere in the MainWindow.xaml.csfile I get the above error and if I change it to new List<object>().ToArray(); the error disappears and the project builds successfully.I also checked the build log and it contains the same error at task MarkupCompilePass2.I am using .NET Framework 4.5 and Visual Studio 2012.EDITAfter playing with it a bit I managed to find out that it's not specificly related to linq an random changes like removing an unused file from a project or just removing parts of code like a simple string creating string s = new String(); fixes the error.At one point a simple change in a constructor from this
public LoggedEventArgs(string message)
{
Message = message;
}
to this
public LoggedEventArgs(string message)
{
// Message = message;
}
fixed the error.
Managed to find a workaround for the above error by moving all my controls from the project into a separate project just for controls.
Now there are no random errors on build because as it looks like it can always find the window and other controls that are now in a separate assembly.
I've been trying to run the sample project provided with the tutorial at stockbotprogramming http://www.stockbotprogramming.com/sharpcibtutorial1.php , but I keep getting a COMException every time I run the application.
I have the TWS Client running and the sample VB projects provided with the API are able to connect just fine, but when I try to use the C# sample provided by the tutorial then I get the following exception:
An unhandled exception of type
'System.Runtime.InteropServices.COMException'
occurred in System.Windows.Forms.dll
Th exception happens when I try to add the TWS ActiveX control:
namespace CSharpTutorial1
{
public partial class Form1 : Form
{
private AxTWSLib.AxTws tws;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
tws = new AxTWSLib.AxTws();
tws.BeginInit();
tws.Enabled = true;
tws.Location = new System.Drawing.Point(32, 664);
tws.Name = "tws";
Controls.Add(tws); // <-- EXCEPTION HERE!
tws.EndInit();
tws.connect("127.0.0.1", 7496, 0);
String msg = "Connected to TWS server version " + tws.serverVersion + "at " + tws.TwsConnectionTime;
MessageBox.Show(msg);
}
}
}
The original project was probably done with Visual Studio 2005, but I have Visual Studio 2008 and it automatically converted the project (I've been reading that there are some problems there). Does anybody know what could be causing this exception? Any ideas on how to fix it?
Important: Make sure you add the component to the IDE using the visual designer. First right click in the toolbox, click "choose items", click the COM tab, then check the TWS control. Now using the visual IDE drag this item to the surface of your form. It must be visible in your app. (Don't create it in the Form1_Load())
Do something like this... (don't use an IP Address of 127.0.0.1, leave it blank):
axTws1.connect("", 7496, 0);
axTws1.reqMktData(0, "AMD", "STK", "", 0, "", "", "SMART", "ISLAND", "USD", "", 0);
Last (if you're using 64-bit Windows) compile the project in 32-bit code. Go to the configuration manager and then create a new profile "x86" and set all the configurations to x86.