I've been doing some work recently involving manual changes to Visual Studio 2010 C# projects or rather the .csproj files themselves (more on that in later posts).
Its a bit of a pain really, involving checking the file out of source control first. As I use Visual Studio 2010 and Team Foundation Server 2010, this means navigating to the Source Control pane from Team Explorer and checking out the .csproj file itself, rather than checking out the whole project from Solution Explorer. Then navigating to the file in Windows Explorer, making the required changes with Notepad, hoping I've not made any syntax errors, saving the file and then finally reloading the project in Visual Studio 2010.
As I want to do this to several .csproj files I decided to investigate the possibility of using a macro and also adding an entry to any Visual Studio Project's Context Menu that would call that macro. So here are the steps I took.
Firstly, how do you create a macro? Well there are lots of articles and posts out there that show you how to record a macro but here is what I did:
- Open Visual Studio 2010 and then ALT+F11 to open the Macro IDE.
- Right-click 'My Macros' in the Project Explorer then Add->Add Module… and give the module a decent name. Mine is called ContextMenu
- Create a sub (Visual Basic is the language of macros) to do the work. I called mine DoSomething.
- You should end up with something that looks like this:
Now for some content. I want this macro to be called against a Visual Studio Project, so the code needs to check that the selected item in the Solution is actually a .csproj file. Here's the code to do that:
Public Sub DoSomething()
Dim itemName As String
Dim project As EnvDTE.Project
If DTE.ActiveSolutionProjects.Length <> 1 Then
MsgBox("Select one project within the Solution Explorer, then re-run this macro.")
project = DTE.ActiveSolutionProjects(0)
itemName = project.FullName()
If itemName.EndsWith("csproj") Then
MsgBox("Have a csprojfile. Filename = " + itemName)
MsgBox("Don't have a csprojfile. Filename = " + itemName)
By the way, if you want to reference additional assemblies in a Macro Module, because you have written some custom code for example, you will have to copy the dlls to C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies. Then add a reference to the Macro Project by right-clicking the project and then Add Reference… Oh, and don't forget to add an Imports statement to the top of the code Module.
Now having created your Macro, how do you make it available from a Visual Studio Project's Context Menu? Well here's how I did it:
- Go back to Visual Studio 2010
- Select Customize… from the Tools menu. Then click on the Commands Tab.
- Select the Toolbar Option and using the Drop Down to the right of the Option select 'Context Menus | Project and Solution Context Menus | Project'.
- The Controls list should now show you the contents of the Project Context Menu.
- Click on the Add Command… button and from the Categories list, select Macros.
- Then select the required macro from the list, in my case Macros.MyMacros.ContextMenu.DoSomething, and then click OK.
- Use the Move Up and Move Down buttons to place the macro where looks good.
- If you want to rename it or put it in its own group, click on Modify Selection.
- It should look something like this (Note I've left the command at the top). Click on Close to save the changes.
So, debugging the macro, how do we do that?
- Open the Macro IDE again (open Visual Studio then ALT + F11).
- Set breakpoints where required (place the cursor somewhere in the code and press F9).
- In Visual Studio, open a Solution and right-click a Project to display the context menu, then click the new entry.
- The code should stop at the break point, use F10 advance through the macro code, line by line.
- If it doesn't stop at the breakpoint, close Macro IDE and Visual Studio, reopen both and try again.
In my next post I'll talk about developing the code to edit a .csproj file to add an Import tag, and hooking that code into my macro.
Jul 12 2011, 10:05 AM
Now, I realise that those of you who use blog comments such as these to
spread your worthless spam are not the cleverest people on the face of the planet.
So, I thought I'd make it clear that you're wasting your time posting your pointless
garbage here. Quite simply, it will never be published. Thankfully, unlike yourselves,
I'm blessed with an inherent ability to identify irrelevant content and it's every bit
as easy for me to toss your contribution into the virtual waste bin as it is to publish it.
So, guess what? Unless your comments are relevant (and I mean, really relevant, not
some thinly veiled attempt to get me to link to your site) they're never going to appear
on here. So, they're never go to appear in a search engine, never going to boost your
customer's Google page rank and never going to achieve anything in terms of Search
Engine Optimisation. Please, practice being a parasite elsewhere. Oh, and I'm confident
that my genuine readers are perfectly well endowed and enjoy a full and healthy lifestyle
without help from you. Thanks for reading.