I have a Visual Studio 2010 extension, a .vsix file. I can obtain the DTE instance for my particular instance of Visual Studio, which I confirm by printing the dte_instance.Solution.Fullname. But for my DTE2 instance it appears to be giving me information about the wrong Visual Studio instance.
Here is the work flow: Visual Studio development IDE open, has code for the extension. Launch the project, which causes a new Visual Studio instance to launch which has the extension installed in it. Click my menu button (in the new IDE) that runs the following code:
DTE dte;
DTE2 dte2, dte2Macros;
dte = (DTE)GetService(typeof(DTE));
dte2 = (DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
dte2Macros = (DTE2)dte2.MacrosIDE;
//this returns what I expect, the solution name in the newer IDE.
MessageBox.Show("solution name: " + dte.Solution.FullName);
//code to get the startup project from MSDN
//http://msdn.microsoft.com/en-us/library/ms228782.aspx
SolutionBuild2 sb = (SolutionBuild2)dte2.Solution.SolutionBuild;
string msg = "";
Int32 configs = sb.SolutionConfigurations.Count;
foreach (String item in (Array)sb.StartupProjects)
{
msg += item;
}
//this returns a project from the development IDE, the one I don't want.
System.Windows.Forms.MessageBox.Show("startup project is: " + msg);
Project startupProject = dte2.Solution.Item(msg);
I found several references to acquiring the DTE2 object in an addin with the connect() method, but I could not locate a similar callback for extensions.
The question: how does one get the DTE2 instance for the IDE an extension is executing in?
Try this, which uses an imported service provider, or just use Package.GetGlobalService:
DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;
I had the problem that on some machines Package.GetGlobalService(typeof(DTE)) returned null.
Now I am using (DTE2)base.GetService(typeof(DTE)) in the Initialize() method of the Package (which is similar to the connect() method of an add-in).
Related
In earlier versions of Visual Studio, you could change the way that results from Find are presented by altering the value of HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\{VSVersion}\Find\Find result format. In particular, I would set it to $f$e($l): $t\\r\\n which removes the full path from the entry.
Making the same change to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\15.0\Find\Find result format doesn't seem to do anything. Is there another way to address this in VS2017?
VS 2017 now uses private registry (see Where does Visual Studio 2017 RC store its config?). One way to access it directly is from a running Visual Studio 2017 instance with my Visual Commander extension. For example, you can use the following C# command:
public class C : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
#"Software\Microsoft\VisualStudio\" + DTE.Version + #"\Find");
key.SetValue("Find result format", #"$f$e($l): $t\r\n");
}
}
Notification window is a new added feature in visual studio 2013. I have an isolated shell application created using visual studio 2013 shell.
Is it possible to extend the Notification window and show notification or information related to our isolated shell application ?
The answer to your question would be yes, however Microsoft does not expose the functionality officially. You can expose these structures yourself, if you're super interested.
The way you can do it, is kind of hackish, but it will work, at least for VS2013. Basically, you need to either reference an internal dll (C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Microsoft.VisualStudio.Shell.UI.Internal.dll), or just copy/paste the relevant structures into your own program, as Kevin has done: User Notifications in the Visual Studio 2013 SDK.
If that is done, you can exploit the interfaces: https://github.com/kevfromireland/visual-studio-2013-notifications-example/blob/master/UserNotificationDemo/UserNotificationDemoPackage.cs
var notificationService = (IVsUserNotificationsService)GetService(
typeof(SVsUserNotificationsService));
var notifcationManager = notificationService.
GetUserNotificationsManagerAsync()
.GetResult();
var vsUserNotificationsManager = (IVsUserNotificationsManager) notifcationManager;
var pic = new RedditPicProvider().GetAwwPicture();
vsUserNotificationsManager.
AddUserNotification(ExampleProvider.Guid,
pic.Url,
pic.Title,
pic.Url,
(uint) NotificationServerity.Critical, isTransient: true);
RegisterNotificationProvider(vsUserNotificationsManager);
I wrote my own Debugger Visualizer.
It, and the attributes, are in their own assembly. There is no references or attributes in the assembly containing the class to be debugged - I want to make a drop-in dll that is optional for people to use.
The class I am trying to debug is a generic.
[Serializable]
public class FinCellTable<S> : IFinCellTable, IEnumerable<List<FinCell.IFinCell>>
where S : class, FinCell.IFinHeaderCell, FinCell.IFinCell, new()
Here is the visualizer:
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(Financials.Debugging.CellTableVisualizer),
typeof(VisualizerObjectSource),
Target = typeof(Financials.Transformation.IFinCellTable),
Description = "FinCell Table Visualizer")]
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(Financials.Debugging.CellTableVisualizer),
typeof(VisualizerObjectSource),
Target = typeof(Financials.Transformation.FinCellTable<Financials.FinCell.FinHeaderCell>),
Description = "FinCell Table Visualizer")]
namespace Financials.Debugging
{
public class CellTableVisualizer : DialogDebuggerVisualizer
{
protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
if (windowService == null) throw new ArgumentNullException("windowService");
if (objectProvider == null) throw new ArgumentNullException("objectProvider");
var data = (IFinCellTable)objectProvider.GetObject();
using (var displayForm = new CellTableVizForm())
{
displayForm.PopulateForm(data);
windowService.ShowDialog(displayForm);
}
}
}
}
I am running Visual Studio 2010, and the following directory contains the .dll and .pdb of the Visualizer Assembly:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\Visualizers
I place a breakpoint on an instance of IFinCellTable that is specifically FinCellTable. It does not show the magnifying glass.
I debugged Visual Studio using another Visual Studio as the first VS was debugging. I watched the output window as the first VS loaded dll's. When I triggered a visualizer on a datatable, the second VS outputted that it loaded Microsoft.VisualStudio.DebuggerVisualizers.dll and Microsoft.VisualStudio.Debugger.DataSetVisualizer.dll (the latter from the correct directory I said above). (The Modules window behaves/shows the same.)
So obviously my Debugger Visualizer Drop-In assembly is not be loaded by VS, so it doesn't know to show the magnifying glass.
How do you get visual studio to load Visualizers up-front, so drop-in visualizers work and you don't need to edit your original code?
Wild guess: are you sure the correct files are in C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\Visualizers, not in C:\Users\<you>\AppData\Local\VirtualStore\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\Visualizers?
If yes, that's due to UAC Virtualization.
This question is over 5 years old, so I assume it's no longer relevant to the original poster, but for anyone else trying to do something similar:
System.Diagnostics.DebuggerVisualizer does not work when target is an interface. You have to specify a concrete type. You have to specify the attribute on every single concrete type you want to visualize:
[System.Diagnostics.DebuggerVisualizer("Financials.Debugging.CellTableVisualizer, Financials.Debugging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=...")]
[Serializable]
public class FinCellTable<S> : IFinCellTable, IEnumerable<List<FinCell.IFinCell>>
where S : class, FinCell.IFinHeaderCell, FinCell.IFinCell, new()
{
I believe this can be disabled in Tools > Options:
If you do not see the effects of DebuggerDisplay or DebuggerTypeProxy ensure that Tools > Options > Debugging > General > Show raw structure of objects in variables windows is NOT checked.
The correct folder to place it is:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Packages\Debugger\Visualizers. Once you place this DLL there and restart visual studio then you should get a "magnifying glass" over "Expression" type of variables (in debugging mode you will get it in watch window and also when you move your mouse cursor over the variable)
is it possible to have a way to clear the Visual Studio OUTPUT window, programmatically? For example, the SysInternal's debugger app called DebugView has the specific command called DBGVIEWCLEAR .. which clears the log window.
Please don't say: right-click, clear window .. with the mouse. I know that, but that's not what i'm after.
For VS 2008 try this code
EnvDTE80.DTE2 ide = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.9.0");
ide.ExecuteCommand("Edit.ClearOutputWindow", "");
System.Runtime.InteropServices.Marshal.ReleaseComObject(ide);
"VisualStudio.DTE.9.0" will change from VS version to version.
For VS 2010 :
//Add reference EnvDTE100
static void ClearOutput()
{
EnvDTE80.DTE2 ide = (EnvDTE80.DTE2)Marshal.GetActiveObject("VisualStudio.DTE.10.0");
ide.ToolWindows.OutputWindow.ActivePane.Clear();
}
The first answer works on any release after Visual Studio 2005, but it seems a little flaky. I had to put a 1 second delay before clearing the console and couldn't get it any better than that. No idea why, but it's better than nothing. It also only works if you're only running one instance of Visual Studio. Maybe I"ll make an extension that looks at the RunningObjectTable to pick the right version.
At any rate, this works more or less.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace VisualStudioHelper {
public class VstHelper {
// Add a Project Reference to "Microsoft Development Environment Properties 8.0"
// (the one for Visual Studio, not SQL Server)
public static void VstClearOutputWindow() {
if (!Debugger.IsAttached)
return;
Application.DoEvents();
Thread.Sleep(1000);
EnvDTE80.DTE2 ide = (EnvDTE80.DTE2)Marshal.GetActiveObject("VisualStudio.DTE.10.0");
ide.ExecuteCommand("Edit.ClearOutputWindow", "");
Marshal.ReleaseComObject(ide);
}
}
}
For VS 2019 try this code
//Add reference to Interop.EnvDTE100
EnvDTE80.DTE2 ide = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE");
ide.ExecuteCommand("Edit.ClearOutputWindow", ""); System.Runtime.InteropServices.Marshal.ReleaseComObject(ide);
What about Console.Clear()?
I need help as to how I can find the path where Microsoft visual Studio is installed. I need to use that path in my program. What is the function that has to be called to get the path where Microsoft Visual Studio is installed ?
Depending on the app, it's probably best to ask the user, but here's some C# code that should do the trick for VS2008.
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VS");
string vsInstallationPath = regKey.GetValue("ProductDir").ToString();
regKey.Close();
It is probably possible to find it by searching the registry, but as I wanted a solution for build scripts I have been using environment variables to do this.
N.B. The name of the environment variable to query is version specific.
For VS2005 you can use VS80COMNTOOLS
For VS2008 you can use VS90COMNTOOLS
If you type SET VS90COMNTOOLS at a command prompt you should see:
VS90COMNTOOLS=C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\
so go up two folders to get to the root of the install path.
This is the quickest way to know the folder where VS is installed or any other program.
Open VS code and when it is running; open the Windows Task Manager and navigate to the Details tab.
Right-click on the Code.exe application that should be running by now and choose the option to Open File Location:
Windows Task Manager > Details Tab > RIGHTCLICK Code.exe > Open File Location
From the registry, HKLM\Software\Microsoft\VisualStudio\9.0\InstallDir for Visual Studio 2008
Is this for an add-in of some sort for Visual Studio?
Because otherwise, you need to be aware that someone running your program may not actually have Visual Studio installed.
If it is installed, you can generally find it at a known location in the registry, such as HKCR/Applications/devenv.exe/shell/edit/command for VS2008.
For newer versions of VS it is better to use from Microsoft provided APIs, because install information is no longer maintained in registry correctly.
install Nuget package Microsoft.VisualStudio.Setup.Configuration.Native
do the trick (returned is tuple with version and path of all VS instances):
private const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154);
public static IEnumerable<(string, string)> GetVisualStudioInstallPaths()
{
var result = new List<(string, string)>();
try
{
var query = new SetupConfiguration() as ISetupConfiguration2;
var e = query.EnumAllInstances();
int fetched;
var instances = new ISetupInstance[1];
do
{
e.Next(1, instances, out fetched);
if (fetched > 0)
{
var instance2 = (ISetupInstance2)instances[0];
result.Add((instance2.GetInstallationVersion(), instance2.GetInstallationPath()));
}
}
while (fetched > 0);
}
catch (COMException ex) when (ex.HResult == REGDB_E_CLASSNOTREG)
{
}
catch (Exception)
{
}
return result;
}
Regards