SolutionEvents for Visual studio 2010 addin does not fire - visual-studio-2010

I'm building an visual studio 2010 addin and trying to hook into an event when the solution is loaded.
Basically what I have found is that SolutionEvents.Opened seems to be what I'm looking for, however listening to it in OnConnection does not seem to be working:
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
applicationObject = (DTE2)application;
var outputWindow = (OutputWindow)applicationObject.Windows.Item(Constants.vsWindowKindOutput).Object;
outputWindowPane = outputWindow.OutputWindowPanes.Add("My Pane");
applicationObject.Events.SolutionEvents.Opened += SolutionEventsOnOpened;
outputWindowPane.OutputString("Connected");
}
private void SolutionEventsOnOpened()
{
outputWindowPane.OutputString("SolutionEventsOnOpened");
}
The only thing outputed is "Connected".
I have tried to listen to SolutionItemsEvents.ItemAdded and SolutionEvents.ProjectAdded and also they do not fire.
Should I init the events elsewhere? (Note I have R# installed, perhaps it is knowed to cause issues?)

Found the solution here: http://blogs.microsoft.co.il/blogs/kolbis/archive/2007/11/22/hooking-up-to-the-solution-events.aspx
Basically, you need to declare members at your add-in class scope for the SolutionEvents and Events variables, and assign them, and then reference the eventhandlers through that. E.g.
private Events2 m_events;
private SolutionEvents m_solutionEvents;
then in the OnConnection handler (when your plugin gets initialised) do this:
m_application = Application as DTE2;
m_events = (Events2)m_application.Events;
m_solutionEvents = m_events.SolutionEvents;
and finally, wire up the solution Opened/AfterClosing events, as follows:
m_solutionEvents.Opened += m_openSolution;
m_solutionEvents.AfterClosing += m_closeSolution;
Then the events will fire.
I presume the reason for doing this is because otherwise the Events/SolutionEvents objects get changed or GC'd (or both ;-).
HTH

With VS2010, when opening a .sln file that leads to start a new VS2010 instance, it is worth noting that SolutionEvents.Opened is fired before EventsObj.OnStartupComplete is fired. So if you register SolutionEvents.Opened during EventsObj.OnStartupComplete it won't fire in this situation.
As far as I know all VS versions post-2010 [2012-2019] fire SolutionEvents.Opened after EventsObj.OnStartupComplete is fired.

Related

Open DTE solution from another program (not add-in)

Is it possible to modify a solution, and use envdte tools, from a command-line project ?
I have an add-in that modifies a solution. But... the changes are required for over a hundred projects... So I'd like to make a c# program that has the same logic, only it iterates through all solution files.
The add-in starts with
EnvDTE.Solution solution = (EnvDTE.Solution)application.Solution;
where DTE2 application is passed from the add-in...
How can I get the same solution, which then I query for projects...
From a separate program, that will only know the solutionPath ?
Is it possible to open the solution, process it, and close it - to move on to the next solution ?
Microsoft gives this example http://msdn.microsoft.com/en-us/library/envdte._solution.open(v=vs.100).aspx
But I don't know what dte is in the context...
Thank you...
VS 2010
edit: I did what the answer below suggests.
Slightly modified, using the link:
http://msdn.microsoft.com/en-us/library/ms228772(v=vs.100).aspx
Thank you
Yes you can. You just need to activate an instance using the COM CLSID for Visual Studio. An example is below. It actually creates a solution and adds two projects to it but the same initialization applies when opening an existing solution.
A couple of caveats:
Mind the COM threading model. The code created from the console app template is sufficient:
[STAThread]
static void Main()
If you have a powerful VS extension like ReSharper installed, you might be better off suspending it if you don't need it for the VS automation. ReSharper had VS commands that control it.
Console.WriteLine("Opening Visual Studio");
var dte = (DTE)Activator.CreateInstance(Type.GetTypeFromProgID("VisualStudio.DTE.10.0",true),true);
Console.WriteLine("Suspending Resharper");
dte.ExecuteCommand("ReSharper_Suspend");
Console.WriteLine("Working with {0}, {1} edition", dte.FullName, dte.Edition);
dte.SuppressUI = true;
dte.UserControl = false;
foreach (var solution in mySolutionInfoList)
{
try
{
dte.Solution.Create(solution.directory, solution.name);
dte.Solution.AddFromTemplate(csharpTemplatePath, solution.directory + "ClassLibrary1", "ClassLibrary1");
dte.Solution.AddFromTemplate(vcTemplatePath, solution.directory + "Win32Dll", "Win32Dll");
Directory.CreateDirectory(solution.directory); // ensure directory exists. Otherwise, user will be asked for save location, regardless of SupressUI value
dte.Solution.Close(true);
Console.WriteLine();
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}
}
Console.WriteLine("Resuming Resharper");
dte.ExecuteCommand("ReSharper_Resume");
try
{
dte.Quit();
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}

Caliburn Micro: taking photo in Mango

I'm trying to use a task launcher in WP7.1 Mango with the latest version of Caliburn Micro, but my code is not getting called back once the task has completed. Probably I'm doing something stupid somewhere, but I cannot see where. Here is what I did for a sample repro application you can download from:
http://www.filesonic.com/file/2750397005/PhoneTaskTest.zip
1) create a new WP7.1 application;
2) add a Lib folder in the solution, add there CM dll's, and add a reference to them;
3) change the generated files as specified by CM documentation and add a bootstrapper.
Now up to this point everything is OK and the application starts with no issues. I then do the following for taking a photo:
4) add a button in the main page to the view and a corresponding method in its VM, named TakePhoto.
5) change the VM as follows:
a) add a readonly IEventAggregator member injected in the constructor;
b) add OnActivate/OnDeactivate overrides to let the aggregator subscribe and unsubscribe this VM;
c) add the TakePhoto method which is just:
_aggregator.RequestTask<CameraCaptureTask>();
d) derive the VM from interface IHandle<TaskCompleted<CameraCaptureTask>> and implement it:
public void Handle(TaskCompleted<CameraCaptureTask> message)
{
if (message.Result.TaskEventArgs.TaskResult != TaskResult.OK) return;
SetPhoto(message.Result.TaskEventArgs.ChosenPhoto);
}
Now, when I click the button the camera task starts in the emulator and I can take a photo; then I'm taken back to my application, but nothing happens and my Handle method is NEVER called. You can just place a breakpoint there to confirm this.
So, what I'm doing wrong here?
You need to handle TaskCompleted<PhotoResult> instead of TaskCompleted<CameraCaptureTask>. Because Caliburn.Micro creates theTaskCompleted<T> message with the event args of the Task's Completed event which is in the case of CameraCaptureTask is PhotoResult. So you should implement IHandle<TaskCompleted<PhotoResult>> and your Handle method should look like this
public void Handle(TaskCompleted<PhotoResult> message)
{
if (message.Result.TaskResult != TaskResult.OK) return;
SetPhoto(message.Result.ChosenPhoto);
}

Create a solution and add a project using "VisualStudio.DTE.10.0"

I'm trying to create a VS2010 solution and add a project from a stand-alone app (not an add-in). I can create an instance of VS2010, but I'm not able to determine how to create a project properly...I can only find an example of how to create a project using the EnvDTE80 object, which later causes an exception because the project file is in an earlier format and needs to be upgraded. I have this:
EnvDTE80.DTE2 dte2;
object obj;
System.Type t;
t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0", true);
obj = System.Activator.CreateInstance(t, true);
dte2 = (EnvDTE80.DTE2)obj;
What I'm looking for is the equivalent of something like "EnvDTE100.DTE2" but don't know how to get there.
Thanks
You do not have to go via DTE object. The treatment to the object solution4 it's different you should do this
Type latestSolution = Type.GetTypeFromProgID("VisualStudio.10.0", true);
EnvDTE100.Solution4 vsSolution = (EnvDTE100.Solution4)Activator.CreateInstance(latestSolution, true);
I think I'm doing something similar, I have a application that creates a solution and loads two projects from templates that I created in VS2010. You're right in that it seems everything still uses the EnvDTE80, even in VS2010, but then we use it to create a 2010 solution:
System.Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0");
Object obj = System.Activator.CreateInstance(type, true);
EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)obj;
EnvDTE100.Solution4 soln = (EnvDTE100.Solution4)dte2.Solution;
Then you can call methods on the soln object to create your project (in my case its AddFromTemplate).

Break when a value changes using the Visual Studio debugger

Is there a way to place a watch on variable and only have Visual Studio break when that value changes?
It would make it so much easier to find tricky state issues.
Can this be done?
Breakpoint conditions still need a breakpoint set, and I'd rather set a watch and let Visual Studio set the breakpoints at state changes.
In the Visual Studio 2005 menu:
Debug -> New Breakpoint -> New Data Breakpoint
Enter:
&myVariable
You can also choose to break explicitly in code:
// Assuming C#
if (condition)
{
System.Diagnostics.Debugger.Break();
}
From MSDN:
Debugger.Break:
If no debugger is attached, users are
asked if they want to attach a
debugger. If yes, the debugger is
started. If a debugger is attached,
the debugger is signaled with a user
breakpoint event, and the debugger
suspends execution of the process just
as if a debugger breakpoint had been
hit.
This is only a fallback, though. Setting a conditional breakpoint in Visual Studio, as described in other comments, is a better choice.
In Visual Studio 2015, you can place a breakpoint on the set accessor of an Auto-Implemented Property and the debugger will break when the property is updated
public bool IsUpdated
{
get;
set; //set breakpoint on this line
}
Update
Alternatively; #AbdulRaufMujahid has pointed out in the comments that if the auto implemented property is on a single line, you can position your cursor at the get; or set; and hit F9 and a breakpoint will be placed accordingly. Nice!
public bool IsUpdated { get; set; }
Imagine you have a class called A with the following declaration.
class A
{
public:
A();
private:
int m_value;
};
You want the program to stop when someone modifies the value of "m_value".
Go to the class definition and put a breakpoint in the constructor of A.
A::A()
{
... // set breakpoint here
}
Once we stopped the program:
Debug -> New Breakpoint -> New Data Breakpoint ...
Address: &(this->m_value)
Byte Count: 4 (Because int has 4 bytes)
Now, we can resume the program. The debugger will stop when the value is changed.
You can do the same with inherited classes or compound classes.
class B
{
private:
A m_a;
};
Address: &(this->m_a.m_value)
If you don't know the number of bytes of the variable you want to inspect, you can use the sizeof operator.
For example:
// to know the size of the word processor,
// if you want to inspect a pointer.
int wordTam = sizeof (void* );
If you look at the "Call stack" you can see the function that changed the value of the variable.
Change the variable into a property and add a breakpoint in the set method. Example:
private bool m_Var = false;
protected bool var
{
get {
return m_var;
}
set {
m_var = value;
}
}
Update in 2019:
This is now officially supported in Visual Studio 2019 Preview 2 for .Net Core 3.0 or higher. Of course, you may have to put some thoughts in potential risks of using a Preview version of IDE. I imagine in the near future this will be included in the official Visual Studio.
https://blogs.msdn.microsoft.com/visualstudio/2019/02/12/break-when-value-changes-data-breakpoints-for-net-core-in-visual-studio-2019/
Fortunately, data breakpoints are no longer a C++ exclusive because they are now available for .NET Core (3.0 or higher) in Visual Studio 2019 Preview 2!
If you are using WPF, there is an awesome tool : WPF Inspector.
It attaches itself to a WPF app and display the full tree of controls with the all properties, an it allows you (amongst other things) to break on any property change.
But sadly I didn't find any tool that would allow you to do the same with ANY property or variable.
I remember the way you described it using Visual Basic 6.0. In Visual Studio, the only way I have found so far is by specifying a breakpoint condition.
Right click on the breakpoint works fine for me (though mostly I am using it for conditional breakpoints on specific variable values. Even breaking on expressions involving a thread name works which is very useful if you're trying to spot threading issues).
As Peter Mortensen wrote:
In the Visual Studio 2005 menu:
Debug -> New Breakpoint -> New Data Breakpoint
Enter: &myVariable
Additional information:
Obviously, the system must know which address in memory to watch.
So
- set a normal breakpoint to the initialisation of myVariable (or myClass.m_Variable)
- run the system and wait till it stops at that breakpoint.
- Now the Menu entry is enabled, and you can watch the variable by entering &myVariable,
or the instance by entering &myClass.m_Variable. Now the addresses are well defined.
Sorry when I did things wrong by explaining an already given solution. But I could not add a comment, and there has been some comments regarding this.
You can use a memory watchpoint in unmanaged code. Not sure if these are available in managed code though.
You can probably make a clever use of the DebugBreak() function.
You can optionally overload the = operator for the variable and can put the breakpoint inside the overloaded function on specific condition.

Is there a way to specify outlining defaults in Visual Studio 2008 so that a file opens up with members collapsed by default?

What I would like to do is have VS2008, when I open a code file, collapse all members of the classes/interfaces in the file by default (including, crucially, any XML documentation and comments).
I do not want to use regions, at all.
I would also like to be able to use the ctrl+m, ctrl+l chord to toggle all member outlining (for example, if everything is collapsed, I would like it to expand all of the members, but not the comments or XML documentation).
Possible? How?
Yes to part 1.
Unsure about part 2.
To have VS2008 automatically open files in a Collapsed state you'll need to create an addin to run the "Edit.CollapsetoDefinition" when each document opens.
This isn't overly tricky - The difficult parts seems to be the that you have to run the code a few milliseconds after the document is actually opened so you need to use the threed pool to do that.
Create an Addin project for VS2008.
Add this code (see following) to the end of the OnConnection Method of the Connect class.
switch (connectMode)
{
case ext_ConnectMode.ext_cm_UISetup:
case ext_ConnectMode.ext_cm_Startup:
//Do nothing OnStartup will be called once IDE is initialised.
break;
case ext_ConnectMode.ext_cm_AfterStartup:
//The addin was started post startup so we need to call its initialisation manually
InitialiseHandlers();
break;
}
Add this method to the Connect class
private void InitialiseHandlers()
{
this._openHandler = new OnOpenHandler(_applicationObject);
}
Add a call to InitialiseHandlers() to the OnStartupComplete method of the Connect class.
public void OnStartupComplete(ref Array custom)
{
InitialiseHandlers();
}
Add this class to the project.
using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE80;
using EnvDTE;
using System.Threading;
namespace Collapser
{
internal class OnOpenHandler
{
DTE2 _application = null;
EnvDTE.Events events = null;
EnvDTE.DocumentEvents docEvents = null;
internal OnOpenHandler(DTE2 application)
{
_application = application;
events = _application.Events;
docEvents = events.get_DocumentEvents(null);
docEvents.DocumentOpened +=new _dispDocumentEvents_DocumentOpenedEventHandler(OnOpenHandler_DocumentOpened);
}
void OnOpenHandler_DocumentOpened(EnvDTE.Document document)
{
if (_application.Debugger.CurrentMode != dbgDebugMode.dbgBreakMode)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Collapse));
}
}
private void Collapse(object o)
{
System.Threading.Thread.Sleep(150);
_application.ExecuteCommand("Edit.CollapsetoDefinitions", "");
}
}
}
And now all opened files should be fully collapsed.
It would be much easier to use the Visual Studio Macros to do the same thing. Editing the "EnvironmentEvents" Macro file in MyMacros and adding a handler for DocumentEvents.DocumentOpened with :
DTE.ExecuteCommand("Edit.CollapsetoDefinitions")
A quick way to collapse all outlining to function-definitions is to press:
Contextmenu-button*(next to your right windows button)*, L, O
I use it all the time. If there is a real hotkey for this please tell me :)
I had tried working out some Visual Basic code for a macro myself, borrowing from different places, and couldn't get anything to work. So what did I do? Why, I asked a question on StackOverflow of course! It got answered, I added the suggested code to my EnvironmentEvents macro, and now when I open CS files, after about a second, all my definitions are collapsed. :)

Resources