I'm new to Visual Studio Extensibility Framework to use VSPackage Extension. I want to obtain a DTE Object inside the user-control which is called inside MyToolWindow class.
I tried all the below possibilities:
1.EnvDTE80.DTE2 dte2;
dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
string solutionPath=dte2.Solution.FullName;
The above trial gives only SolutionPath of the 1st instance of the visual studio which is opened.
For EX: If Math1.sln and Math2.sln is opened,only Math1.sln path is assigned to solutionPath.
From the MSDN link, "this.GetService" cannot be recognized in the button1.click (Am I missing any thing here)
Once, DTE object is obtained I shall be easily be able to obtain solution Name of the current instance.
I must be able to obtain appropriate EnvDTE80.DTE object inside the click of the button which is inside User-control. This User-Control is called inside MyToolWindow.cs
Any help on this would be greatly appreciated.
First of all, Marshal.GetActiveObject("VisualStudio.DTE.10.0") is problematic because it will just give you a DTE of a random Visual Studio instance. You can obtain correct instance of DTE through the GetService call.
Then just enumerate the DTE.Solution.Properties, one of the properties should be the solution name. Probably DTE.Solution.Properties.Item("Name"), though I cannot check this at the moment.
As for your "GetService cannot be recognized", method is defined on an IServiceProvider which ToolWindowPane implements. If you want to use that in your control, you should pass the tool window instance to your control. Example:
public class MyToolWindow: ToolWindowPane {
void SomeMethod() {
var myControl = new MyControl(this);
}
}
public class MyControl: UserControl {
public MyControl(IServiceProvider serviceProvider) {
// Now you can call serviceProvider.GetService
}
}
I have an abstract VsPackage class I use within all my home-brewed extensions; and I obtain the application instance this way...
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
public abstract class VsPackage : Package
{
...
protected DTE2 GetApplication()
{
return this.GetService(typeof(SDTE)) as DTE2;
}
...
}
Related
I'm developing a Visual Studio Extension to replace text in the current active .cs file using a custom command that is invoked from the right click context menu in the Code Window.
Accessing the document works so far, but if I start more than one instance of VS2017, then changes which I expect to be done in the new instance are made in the first opened instance.
Is there a possibility to get the right instance to access only the current active Document no matter how many instances are open?
At the moment I get the instance with following code:
dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal
.GetActiveObject("VisualStudio.DTE.15.0");
Does anybody have an idea how to solve this?
You need to use in the class of your package (that inherits from the AsyncPackage base class):
EnvDTE.DTE dte = (EnvDTE.DTE) base.GetService(typeof(Microsoft.VisualStudio.Shell.Interop.SDTE));
The code that you were using returns some DTE instance running on your system, not necessarily the one where your extension is hosted.
As Carlos Quintero already said, you should get the DTE Object by using his example.
Lets say your extension name is YourExtension:
In my case, I added a Property in my YourExtension.cs
public EnvDTE.DTE DTEObject { get; set; }
Then in YourExtensionPackage.cs you can get the desired DTEObject right after your package got initialized:
protected override void Initialize ()
{
YourExtension.Initialize (this);
base.Initialize ();
YourExtension.Instance.DTEObject = (EnvDTE.DTE)base.GetService (typeof (Microsoft.VisualStudio.Shell.Interop.SDTE));
}
Now you can work with the DTEObject within your extension and get any Object via GetObject. In My case for example I'm getting the current instance of the VersionControlEx.
I have a Ribbon1 class which was created by the Visual Studio.
public Microsoft.Office.Tools.Ribbon.RibbonEditBox IDBox;
I would like to access one of the ribbon controls from within a different class.
using MyRibbon = ExcelAddIn1.Ribbon1;
xlTextID = MyRibbon.IDBox.Text;
I got the error message.
An object reference is required for non-static field, method,
property.
I can't make IDBox static because it's initialized as an instance of a class via 'InitializeComponent()' method.
this.IDBox = this.Factory.CreateRibbonEditBox();
I have also tried to create a property.
private Microsoft.Office.Tools.Ribbon.RibbonEditBox IDBox;
public Microsoft.Office.Tools.Ribbon.RibbonEditBox IDBoxProperty
{
get { return IDBox; }
set { IDBox = value; }
}
Doing this I have seen exactly the same error.
How can I keep IDBox non-static and still access it from outside class?
I can found the answer - see it below.
Instances of the all Ribbon controls derived from Microsoft.Office.Tools.Ribbon can be accessed via Globals.Ribbons.Ribbon1.
Therefore, in order to access public Microsoft.Office.Tools.Ribbon.RibbonEditBox IDBox; which is created by InitializeComponent()method, you would do Globals.Ribbons.Ribbon1.IDBox.
More information about accessing Ribbon Controls at Run-Time:
https://msdn.microsoft.com/en-us/library/bb772088.aspx
I have successfully added a service reference to my Visual Studio 2013 project.
I cannot however reference it in code.
For example, given the project name "myproject", and the service reference name "thirdpartyasmx", I cannot use this using directive...
using myproject.thirdpartyasmx
I cannot instantiate the class directly either...
thirdpartyasmx test = new thirdpartyasmx();
I have tried building the solution before trying to reference the service reference.
This is not something I do regularly, so I'm afraid I'm missing a step.
UPDATED based on OP feedback
When you click on Add Service Reference, click on the Advanced button in the bottom left of the dialog box:
Clear the Reuse types in referenced assemblies checkbox (by default it's checked).
You don't need to use the using directive at the top of the class, you can just instantiate the service reference inside the class using the name you gave to the service when referencing it:
public class MyClassName
{
protected void SomeMethod()
{
thirdpartyasmx.ThirdpartyasmxServiceClient service = new thirdpartyasmx.ThirdpartyasmxServiceClient();
}
}
is there a way to subscribe to Test Explorer events in visual studio extension?
I didn't find anything like that in DTE2 interface. My goal is to trigger some function from extension when Test run completed (for the test that were ran from Test Explorer)
Thank you!
Thanks 280Z28 for your answer. Working code by using application object DTE:
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.TestWindow.Extensibility;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TestTools.Execution;
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
Microsoft.VisualStudio.OLE.Interop.IServiceProvider InteropServiceProvider = application as Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
_ServiceProvider = new ServiceProvider(InteropServiceProvider);
_ComponentModel = (IComponentModel)_ServiceProvider.GetService(typeof(SComponentModel));
_OperationState = _ComponentModel.GetService<IOperationState>();
_OperationState.StateChanged += _OperationState_StateChanged;
}
void _OperationState_StateChanged(object sender, OperationStateChangedEventArgs e)
{
}
It is also possible to access currently discovered test by ITestsService.
_TestsService = _ComponentModel.GetService<Microsoft.VisualStudio.TestWindow.Extensibility.ITestsService>();
var GetTestTask = _TestsService.GetTests();
GetTestTask.ContinueWith(Task =>
{
var DiscoveredTests = Task.Results.ToList();
});
The interfaces you need are available through MEF in the Microsoft.VisualStudio.TestWindow.Interfaces.dll assembly.
You need to expose your extension through MEF and [Import] an instance of IOperationState, or use the IComponentModel interface (returned for the SComponentModel service) to access the IOperationState. From there, you want to add an event handler to the IOperationState.StateChanged event, and look for the State property to include the TestOperationStates.TestExecutionFinished flag.
I'm terribly sorry for the lack of links, but I couldn't find any information about this in MSDN.
Edit: Two remarks about compatibility.
This is only available in Visual Studio 2012 and newer.
The necessary assembly (mentioned above) has a different strong name in the two versions of Visual Studio, and there is no bindingRedirect in Visual Studio 2013. What this means is you will be forced to deploy separate extensions for Visual Studio 2012 and Visual Studio 2013, or get "clever" about the way you dynamically load your extension code (the latter is way beyond the scope of this answer, but I've used it for some cases like Inheritance Margin extension that requires access to version-specific IntelliSense resources).
Sample VS 2017
A sample using MEF and the ITestContainerDiscoverer exported type. But be aware this may be gone in VS 2019!
[Export(typeof(ITestContainerDiscoverer))]
[Export(typeof(Testything))]
internal class Testything : ITestContainerDiscoverer
{
[ImportingConstructor]
internal Testything([Import(typeof(IOperationState))]IOperationState operationState)
{
operationState.StateChanged += OperationState_StateChanged;
}
public Uri ExecutorUri => new Uri("executor://PrestoCoverageExecutor/v1");
public IEnumerable<ITestContainer> TestContainers
{
get
{
return new ITestContainer[0].AsEnumerable();
}
}
public event EventHandler TestContainersUpdated;
private void OperationState_StateChanged(object sender, OperationStateChangedEventArgs e)
{
if (e.State == TestOperationStates.TestExecutionFinished)
{
var s = e.Operation;
}
}
}
Some more things could be found here
https://www.fuget.org/packages/Microsoft.VisualStudio.TestWindow.Interfaces/
I've had serious problems on how to solve this: I don't know where the OnAfterInstall event goes.
Let me explain myself. I created a C# project which compiles perfectly and built in Release mode. After that, I've created a Setup Project using the wizard. I have added an extra dialog, which lets the user choose between two languages. Now, my problem is that I want to store that language into the registry (or app.config file, the easier the better), and I've read that you need to detect it within the OnAfterInstall method in an inherited class of Installer.
Now, where should I put that class? Logic tells me it goes in the C# project, but it complains that neither Context nor Installer class exist. When I add this class to the Setup Project, it doesn't complain, but it doesn't work after that. Here's the class.
using System;
using System.Configuration.Install;
public class Install : Installer
{
public Install()
{
}
protected override void OnAfterInstall(IDictionary savedState)
{
string lang = Context.Parameters["lang"];
RegistryKey key = Registry.LocalMachine;
using (key = key.CreateSubKey(#"SOFTWARE\MyCompany\MyApp"))
{
key.SetValue("lang", lang);
key.Close();
}
base.OnAfterInstall(savedState);
}
}
PS: I'm already passing lang as CustomActionData using /lang=[LANG] (where LANG is the radio value)
First, you should add the RunInstallerAttribute to you class.
[RunInstaller(true)]
public class Install : Installer
...
Next, put the installer in a separate project (class library), e.g. MyCustomInstaller.
Finally, add the primary output of this project to a custom action in the custom actions editor of the setup project.
It's up to you in which custom action you want to use.