How can my add-in detect when a solution is loaded? I know there must be some event somewhere in the DTE model, but I can't find it. My add-in loads when Visual Studio loads, but it depends on a solution being open. I don't want to make it a solution add-in until MS loses their sick fixation on COM, as solution add-ins have to be COM components.
Here's how to register for event handling using C#:
_solutionEvents = _applicationObject.Events.SolutionEvents;
_solutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(SolutionOpened);
_solutionEvents.AfterClosing += new _dispSolutionEvents_AfterClosingEventHandler(SolutionClosed);
Also note that when user opens Visual Studio by double clicking on a solution file, you won't get an event for solution opening. You should check whether _applicationObject.Solution is not null in OnStartupComplete method to handle this situation correctly.
The SolutionEvents class on MSDN includes event:
Opened: Occurs immediately after opening a solution or project.
You have in the DTE2 class a property called Events it gives a lots kind of events, for what you need you have to use:
DTE2 _applicationObject
_applicationObject.Events.SolutionEvents.Opened+=new _dispSolutionEvents_OpenedEventHandler(SolutionEvents_Opened);
Related
I find myself enabling and disabling the "Common Language Runtime Exceptions" checkbox in Exception Settings with considerable regularity. I'm tired of having to open the window every time. Is there a keyboard shortcut?
EDIT: as the answer as of June 2020 appears to be "no", I've requested a feature here: https://developercommunity.visualstudio.com/idea/1073035/keyboard-shortcut-to-enabledisable-the-common-runt.html
Is there a keyboard shortcut to enable/disable “Common Language
Runtime Exceptions” in Visual Studio exception settings?
I think there is no such quick shortcut to do that.
Actually, the shortcut for the Exception window is Ctrl+Alt+E, you can call such window by that.
However, VS only has a shortcut key to open a window, and there is no shortcut key to enable or disable an exception, and there are many different types of exceptions in the exception window. So it can be a bit difficult.
So you should use shortcut Ctrl+Alt+E to open Exception and then set the exception manually.
Besides, if you still want that feature to have a keyboard shortcut to enable/disable Common Language Runtime Exceptions, you can suggest this feature on our User Voice Forum.
After that, you can share the link with us here and anyone who is interested in this feature will vote it so that it will get more attention from Microsoft.
It is managed by the DebuggerServiceHelper class in VSDebugCoreUI.dll:
ExceptionSettingsBatchOperation{_operationDepth=3} DebuggerServiceHelper.BeginExceptionBatchOperation()
DebuggerServiceHelper.UpdateException(EXCEPTION_INFO150{bstrProgramName=null, bstrExceptionName="Common Language Runtime Exceptions", dwCode=0, dwState=16418})
ExceptionSettingsBatchOperation.EndBatchOperation()
But these are all internal classes and not easily accessible from external code.
Another approach is to find this WPF CheckBox on screen (by the TextBlock following it with the given Text property) and click it programmatically.
I really wish Exception Breaker worked for later versions of Visual Studio.
In combination with this answer to a similar question, I was able to get something to work. It is not ideal, but you might give this a try.
Note: I am using Visual Studio 2019
Tool required
The free version of the Visual Commander extension that allows Visual Studio macros in later versions.
Note: I tried (a little) to use the Macros for Visual Studio extension, but with no luck
Steps
Using Visual Commander, add a new command with the code below, save and compile.
Run with one of:
Run directly from the Visual Commander UI
Modify a toolbar and add the Extensions/Command01 command to it
Add a Keyboard shortcut via Options and select VCmd.Command01
Code
Notes:
I tried toggling the <All Common Language Runtime Exceptions not in this list> item, but did not have luck with it.
I tried looping through all of the Exceptions in the group but it was really slow (i.e. 15 seconds :-( ) so I picked the most important exceptions for my project.
I was unsuccessful finding a away to toggle the parent Common Language Runtime Exceptions, but if you find it, please leave a comment.
using EnvDTE;
using EnvDTE80; // DTE2 type
using EnvDTE90; // Debugger3
public class M : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
var lDebugger = DTE.Debugger as Debugger3;
var lExceptionSettings = lDebugger.ExceptionGroups.Item("Common Language Runtime Exceptions");
// Use this Exception as the master toggle
bool lExceptionsEnabledToSet = !lExceptionSettings.Item("System.ArgumentException").BreakWhenThrown;
// 2 examples
lExceptionSettings.SetBreakWhenThrown(lExceptionsEnabledToSet, lExceptionSettings.Item("System.ArgumentException"));
lExceptionSettings.SetBreakWhenThrown(lExceptionsEnabledToSet, lExceptionSettings.Item("System.OutOfMemoryException"));
// This does not work to set the whole group on/off:
//lExceptionSettings.SetBreakWhenThrown(true, lExceptionSettings.Item("<All Common Language Runtime Exceptions not in this list>"));
// This is really slow
//foreach (var lExceptionSetting in lExceptionSettings)
//{
// lExceptionSettings.SetBreakWhenThrown(lExceptionsEnabledToSet, lExceptionSetting as ExceptionSetting);
//}
}
}
I'm creating an ActiveX using VS and MFC. Initialisation is done in constructor of my control. There the m_hWND window handle is not valid, it is still NULL.
So: is there some kind of "initialisation complete" function available in COleControl() that is called as soon as m_hWnd is valid and additional controls can be added to it?
Thanks!
It's been a while since I've written an ActiveX control, but, I seem to remember using OnResetState, or, one of the other events shown in the link to handle initialization.
Remember that there are windowless ActiveX controls. For such controls you never get a window handle!
So normally after the creation a ActiveX Control is "initialized", and you can use it.
ActiveX controls usually reside in the same Thread so there is nothing that can run beside your code and do further initialization.
If this doesn't help you Need to refine your question.
See discussion here too about ActiveX controls without a window handle.
I think OnActivate is what you are looking for.
I am writing an extension to Visual studio 2012 using VSPackage. I need to add a context menu entry to Test Explorer and on click of this menu item, I need to get the selected unit test(s). I tried to add an item using
((CommandBars)DTE.CommandBars)["Test Window Context Menu"].Controls.Add(Type: MsoControlType.msoControlButton);
and adding an event handler by subscribing to the event
DTE.Events.CommandBarEvents[command].Click
I succeeded in adding an item to Context menu but the Click event handler never gets fired. MSDN said, I needed to set the OnAction property of the command to a valid string value for the Click event handler to get fired. It didn't work either.
Then, I figured out I needed to add a command through the VSCT file in a VSPackage. However, I am not able to find the Test Window Context menu so that I can attach the command to it. Also, I need to get all the unit tests (TestCase objects) listed in the Test Explorer.
Any help is greatly appreciated!
Usually these are the files I look for Visual Studio shell GUIDs or command, context menu, group, etc IDs:
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Inc\stdidcmd.h
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Inc\vsshlids.h
Actually they are included in the top of your newly created .vsct file (<Extern href="vsshlids.h" />). I guess you've already checked them. I did a quick search, but what I found for "Test" is just a test ribbon and a test dialog. Probably now that you're looking for. It might be still useful for someone finding this post.
You might also want try it brute force style:
Search your Program Files (x86)\Visual Studio [VERSION] for regexp: ^#define.*TEST.*$
This shall give you the defines containing TEST.
Also you might want to consider asking Microsoft directly.
I wrote some exploratory code to loop over commands in that context menu. I also played around with registering a priority command target and seeing what group GUID and command ID I got. The GUID for that context menu appears to be {1e198c22-5980-4e7e-92f3-f73168d1fb63}. You can probably use that to add a command via the .vsct file without using the DTE.CommandBars to add it dynamically.
Here's my experiment code which lists the GUID and command ID of the commands currently in that context menu, in case it helps anyone.
var bars = ((Microsoft.VisualStudio.CommandBars.CommandBars)DTE.CommandBars);
var teContextMenu = bars["Test Window Context Menu"];
var ctls = teContextMenu.Controls;
foreach (var ctl in ctls)
{
var cmdCtl = ctl as Microsoft.VisualStudio.CommandBars.CommandBarControl;
string guid; int id;
DTE.Commands.CommandInfo(ctl, out guid, out id);
Debug.WriteLine($"{cmdCtl?.accName} {guid} {id}");
}
This article on command routing was helpful to me:
https://learn.microsoft.com/en-us/visualstudio/extensibility/internals/command-routing-algorithm
My experimental priority command target, where I set a breakpoint to see what GUID and command IDs were sent, is registered as follows. The TestCommandInterceptor class is a bare-bones implementation of IOleCommandTarget.
var cmdService = GetService(typeof(SVsRegisterPriorityCommandTarget)) as IVsRegisterPriorityCommandTarget;
var target = new TestCommandInterceptor();
cmdService.RegisterPriorityCommandTarget(0, target, out _testCmdInterceptorRegistrationCookie);
I would still like to know the answer to the second part of this question about how to determine the selected tests.
I've just built an MS Outlook Add In using Visual Studio and Office 2010. I've installed it ok on 4 machines, but one user is getting the following error -
Error found in Custom UI XML of "...."
...
...
Failed to find Office control by ID
Everyone is running Windows 7 and Outlook 2010 - not sure why this person is having a problem. Can anyone suggest how to diagnose this?
For those having similar issues, you don't have to remove any add-in.
What is happening is: Outlook will try to load all ribbons (found in your ribbon xml) into any window the user goes to. Then it'll complain about not finding ID x or y.
Just make sure your GetCustomUI method in Ribbon.cs does not load the entire ribbon XML at once but rather loads it per fragment.
If you're not sure what IDs you need to target, use a breakpoint in GetCustomUI then start Outlook, surf different views (main, new email, new appointment, calendar...etc) in order to gather the IDs for the views wherein you need to show you add-in.
In my case, I needed Microsoft.Outlook.Explorer, Microsoft.Outlook.Mail.Compose and Microsoft.Outlook.Appointment.
Therefore I changed my GetCustomUI to:
public string GetCustomUI(string ribbonID)
{
switch (ribbonID)
{
case "Microsoft.Outlook.Explorer":
return GetResourceText("MyAddin.RibbonsForOutlookExplorer.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("MyAddin.RibbonForOutlookMailCompose.xml");
case "Microsoft.Outlook.Appointment":
return GetResourceText("MyAddin.RibbonForOutlookAppointment.xml");
default:
return null;
}
}
Of course, I had to break down my Ribbon.xml into the three XML files mentioned above. The result: Outlook will ONLY load the fragment needed for a given screen (appointment, new email ...) and will not complain about "not finding an ID on screen X or Y".
Finally, for those who are not sure why some users get that error while others don't: it's because of "Show add-in user interface errors" option (in Options -> Advanced). If that is unchecked then Outlook will ignore the malformed ribbon XML errors. If it checked, users will get related errors about your add-in (if any exists) and also about other add-ins.
If it works for everyone except one user. As #Brijesh Mishra mentioned check if the user has got any other addin and if he is having own quick access tool bar customized.
If he has got any of this then, remove the other addins and try to install or reset the quick access tool bar customization.
For all of you that use a Designer-based VSTO plugin, and not the XML solution.
I searched all the web for this problem, but only found XML-based solutions.
There's nothing for Visual Designer on the web, because in this case you don't have to override the "GetCustomUI" method.
Ribbons designed by using the Visual Designer return a RibbonManager by default.
This RibbonManager object represents all Ribbon (Visual Designer) items in the project and is automatically handled in background through the active window inspector.
So you don't have to write any special code to handle different windows.
To configure it correctly you just have to:
Add one extra Visual Designer Ribbon for every window the user goes to
in the Ribbon Object go under "RibbonType", open the checkbox list an only activate the corresponding window, where the ribbon should appear.
If there is more than one window checked in the list, Outlook trys to insert the ribbon in all the marked windows. Even if the corresponding window is currently not opened. That's the reason, why the error "Failed to find control ID" appears.
the actual fix for me was to separate the ribbon XML files containing the customUI and redirecting to the correct one in the GetCustomUI method (implemented using Office.IRibbonExtensibility)
in example:
public string GetCustomUI(string RibbonID)
{
switch (RibbonID)
{
case "Microsoft.Outlook.Mail.Read":
return GetResourceText("namespace.type1.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("namespace.type2.xml");
default:
return null;
}
}
I used the VS 2010 SDK to create and show a custom ToolWindowPane with a WPF control as content. I create a new instance and show it each time a Tool menu item is clicked (the ProvideToolWindow attribute has MultiInstances = true).
When the user attaches the debugger (e.g., hits F5 while in C# project) my ToolWindowPane suddenly hides. I'd like to make sure my tool window is always visible while open, no matter what context the user is in. Is there a way I can enforce that?
I've tried using the ProvideToolWindowVisibility attribute but that automatically shows a new instance of my tool window rather than keeping a remaining one open.
For VS 2010 SDK Microsoft added a new flag __VSCREATETOOLWIN2.CTW_fDocumentLikeTool
You can use this way:
public override void OnToolWindowCreated()
{
IVsWindowFrame windowFrame = Frame as IVsWindowFrame;
object varFlags;
windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_CreateToolWinFlags, out varFlags);
int flags = (int)varFlags | (int)__VSCREATETOOLWIN2.CTW_fDocumentLikeTool;
windowFrame.SetProperty((int)__VSFPROPID.VSFPROPID_CreateToolWinFlags, flags);
}
This way Tool Window persist open at "Document Well" when you go Debugging
However I have to say this give us some problems when debugging projects, avoiding us to open code files while debugging, like if Visual Studio document management was 'block', there are not so much information for this new flag...
So we preferred to hook to EnvDTE.DebuggerEvents and show the ToolWindow if hide when a debugging session start...
(our ToolWindow has MultiInstances = false)
Implement QueryShowTool
public:
int QueryShowTool(Guid % rguidPersistenceSlot, System::UInt32 dwId, [Runtime::InteropServices::Out] int % pfShowTool);
Enables the VSPackage to control whether to show or hide the tool
window. The shell calls this method when the user switches views or
contexts, for example Design, Debugging, Full Screen.
See https://learn.microsoft.com/en-us/visualstudio/extensibility/opening-a-dynamic-tool-window?view=vs-2017