Category Archives: Other

Red Gate Blog Guest post: Using .NET Reflector to understand and debug Visual Studio assemblies

After I wrote this post about using .NET Reflector to debug Visual Studio assemblies,

Guest post: Using .NET Reflector to understand and debug Visual Studio assemblies
http://reflectorblog.red-gate.com/2012/10/guest-post-using-net-reflector-to-understand-and-debug-visual-studio-assemblies/

No Macros IDE in Visual Studio 11 Developer Preview

According to this post in the MSDN VSX forum, the next version of Visual Studio after 2010, currently named Visual Studio 11, will not have macros (the Macros IDE, macros Explorer, etc.)

Macros in Visual Studio 11 Developer Preview
http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/d8410838-085b-4647-8c42-e31b669c9f11

In VS 2010 the Macros IDE was actually the VS 2008 Macros IDE (it didn’t use the look and feel of VS 2010 and the About window showed Visual Studio 2008 Macros). It seems that macros aren’t very used (not providing C# as a language option to write them didn’t help) and Microsoft has decided to remove them completely. It is somewhat unfortunate because the closest extensibility approach is add-ins, which require to learn the IDTExtensibility2 interface and the quirks of its OnConnection method, not to mention how to add commands and buttons.

“The system administrator has set policies to prevent this installation” on Windows Server

I am these days creating setups of add-ins for Visual Studio using MSI and today when executing a setup intended for the current user (not for all users), not requiring admin rights, on Windows 2008 Server with a standard user account I have got the following error:

“The system administrator has set policies to prevent this installation”

I was not familiar with Windows Server and those policies but I needed a clean machine to test several setups and it happens that I had a clean virtual machine with Windows Server, SharePoint 2007 and Visual Studio 2010 so I used that. After searching the web I have learned that this problem is caused by the value DisableMSI (or lack of it) in the registry entry:

HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer

See:

DisableMSI (Windows)
http://msdn.microsoft.com/en-us/library/aa368304.aspx

Creating that registry entry and name and setting its value to 0 solves the problem and a standard user can install a MSI setup that doesn’t require administrator privileges on Windows Server. Client Windows have a different behavior as explained in that article.

Visual Studio 2010 Productivity Power Tools crashing when add-in calls Application.DoEvents

I had three bug reports from customers of my MZ-Tools add-in for Visual Studio 2010 with a “System.NullReferenceException: Object reference not set to an instance of an object.” that happened “when closing Visual Studio”. The stack trace is something like this:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.VisualStudio.Text.Editor.Implementation.DefaultScrollMap.TranslatePosition(SnapshotPoint bufferPosition)
   at Microsoft.VisualStudio.Text.Editor.Implementation.DefaultScrollMap.GetCoordinateAtBufferPosition(SnapshotPoint bufferPosition)
   at Microsoft.PowerTools.OverviewMargin.Implementation.OverviewMargin.SimpleScrollBar.GetYCoordinateOfBufferPosition(SnapshotPoint bufferPosition)
   at Microsoft.PowerTools.CaretMargin.CaretMarginElement.InvalidateIfChanged(Boolean highlightsChanged)
   at Microsoft.PowerTools.CaretMargin.CaretMarginElement.<UpdateMarginMatches>b__1(Object )
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 uReason, Int32 pvLoopData)
   at System.Windows.Forms.ComponentManagerProxy.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.DoEvents()
   …

And indeed my add-in calls Application.DoEvents() in the event handler that sets to get notified when a solution is closed (that’s why the exception can happen “when closing Visual Studio”). I patched my add-in to ignore that exception, but the other day I got that exception too when calling DoEvents in other parts of the add-in, so it seems that any call to Application.DoEvents() can cause that exception in the Visual Studio 2010 Productivity Power Tools. I am using the latest version 10.0.20318.14 at the time of this writing.

6 months without blogging

I haven’t written a new post in this blog since 6 months and 2 days ago. If you are subscribed through RSS you may have notice it 🙂 The reason is that the IT department of the company where I worked for “suffered” an outsourcing at May 15th, which included me as part of the “pack”, and during these months my life has been under a lot of pressure during day hours and even on nights and weekends, specially the first months. It seems that management is not the same in a final client than in a IT provider ;-). Since I wanted to keep my commitment to MZ-Tools (there will be a new major version 7.0 next year) and of course to my family, the two resulting casualties have been this blog and the Microsoft Most Valuable Professional (MVP) tittle that won’t be awarded to me next January like the past 7 years (I haven’t written new articles of the MZ-Tools Series and I haven’t answered questions in the Visual Studio Extensibility MSDN Forum either). Nonetheless I will try to write new posts from time to time since there are still areas of add-in development that I haven’t covered, such as unit testing add-ins within Visual Studio (that I have invested a lot of time lately).

Visual Studio and the International Settings, Language combobox

I was intrigued about where Visual Studio was getting the languages to fill the Language combobox in the Tools, Options dialog, Environment, International Settings section. After some investigation I discovered that the list is not stored in the registry or in some file. Visual Studio just scans the subfolders of the C:Program FilesMicrosoft Visual Studio <version>Common7IDE folder and checks which ones are LCID numbers!

So, you can copy the 1033 folder (which is English) and paste it as 3082 (which is Spanish) and you get the Spanish language in the combobox. Of course the user interface and everything else is in English because you didn’t get really the Spanish resources (that would require to install the full Spanish version of Visual Studio) but it is useful to test if the managed satellite dll for custom pictures will be loaded when the IDE is not in English (the problem that I am investigating now) without installing a full localized version (and its service pack and its security patches…)

Creating setups for Visual Studio add-ins using Windows Installer XML (WiX)

Although as I have posted many times I personally use and recommend the free InnoSetup script-based tool to create the setup of my MZ-Tools family of add-ins (see HOWTO: Create a setup for a Visual Studio 2005 / 2008 add-in using Inno Setup), there are people who prefer MSI-based setups.

The tricky part of installing XML-based add-ins is always to decide where to put the .AddIn file (see INFO: Default .AddIn file locations for Visual Studio add-ins) and then to modify the <Assembly> value to point to the location where the user has decided to install the add-in dll (typically in the C:Program Files folder). This second part is always omitted from the Microsoft documentation and posts, because it requires a custom action, which is complicated because it requires code.

For this purpose, Windows Installer XML (Wix) greatly simplifies the task. WiX is a toolset that builds Windows installation packages from XML source code. Although I haven’t started to play with WiX yet, I have found that Alex Shevchuk has a great article series about moving from MSI to WiX, and specially interesting is the part 25 about updating XML files using XmlFile, which can be used to change the <Assembly> value.

I will try to find time to write a HOWTO article about this some day, but meantime, if you are interested, you can download the VS 2008 SDK 1.1 and go to the file C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioTeamSystemIntegration\Test Tool Extensibility\VsIdeHostAdapter\Installer\VsIdeTestHost.wxs, which uses this approach (bold line):

<!-- Directories -->
<DirectoryRef Id="TARGETDIR">
   <!-- One of the per-machine directories Visual Studio searchings for .Addin files -->
   <Directory Id="CommonAppDataFolder">
      <Directory Id="MSCommonAppData" Name="MS" LongName="Microsoft">
         <Directory Id="MSEnvCommonAppData" Name="MSEnvSH" LongName="MSEnvShared">
            <Directory Id="DIR_ADDINS" Name="Addins" />
         </Directory>
      </Directory>
   </Directory>
   <!-- VS install dir replaced by RegistrySearch -->
   <Directory Id="VSINSTALLDIR" Name="VS2005" />
</DirectoryRef>

<!-- Components: files and registry entries -->
<DirectoryRef Id="DIR_ADDINS">
   <Component Id="C_VsIdeTestHostAddinXml" Guid="$(var.C_VsIdeTestHostAddinXml_Guid)">
      <Condition>VSIDETESTHOST_TEAMSUITE OR VSIDETESTHOST_TEAMDEV OR VSIDETESTHOST_TEAMTEST</Condition>
      <File Id="VsIdeTestHostAddinFile" Name="HAAddin.ADD" Vital="yes" DiskId="1" LongName="$(var.AddinName).AddIn" Source="$(var.InstallerSources)\VsIdeTestHost.AddIn" />
      <XmlFile Id="AddAssemblyElement" Action="setValue" File="[#VsIdeTestHostAddinFile]" ElementPath="/Extensibility/Addin/Assembly" Value="[#VSIdeAddinDllFile]" Sequence="1" />
      <XmlFile Id="AddinNameElement" Action="setValue" File="[#VsIdeTestHostAddinFile]" ElementPath="/Extensibility/Addin/FriendlyName" Value="$(var.AddinName)" Sequence="1" />
   </Component>
</DirectoryRef>

BTW, notice that the sample uses the “CommonAppDataFolder” variable, which is localized on Windows, while Visual Studio has a bug hardcoding the English name (%ALLUSERSPROFILE%\Application Data\Microsoft\MSEnvShared\AddIns) so the sample doesn’t work on non-English machines, as explained in the article INFO: Default .AddIn file locations for Visual Studio add-ins.

Different template names for text files in C# and VB.NET to use with Solution2.GetProjectItemTemplate

When you execute the following macro that gets the file templates for classes, forms and text files in C# and VB.NET:

Sub Macro1()

   Dim objSolution2 As EnvDTE80.Solution2

   objSolution2 = CType(DTE.Solution, EnvDTE80.Solution2)

   MsgBox(objSolution2.GetProjectItemTemplate("Class.zip","VisualBasic"))
   MsgBox(objSolution2.GetProjectItemTemplate("Form.zip", "VisualBasic"))
   MsgBox(objSolution2.GetProjectItemTemplate("Text.zip","VisualBasic"))

   MsgBox(objSolution2.GetProjectItemTemplate("Class.zip", "CSharp"))
   MsgBox(objSolution2.GetProjectItemTemplate("Form.zip", "CSharp"))
   MsgBox(objSolution2.GetProjectItemTemplate("Text.zip", "CSharp"))

End Sub

It fails for the 6th case:

objSolution2.GetProjectItemTemplate("Text.zip", "CSharp")

I thought it was a bug but it happens that the symmetric beauty of the code is broken because the actual name for the C# case is “TextFile.zip”, not  “Text.zip”:

objSolution2.GetProjectItemTemplate("TextFile.zip", "CSharp")

It seems that C#/VB.NET parity didn’t reach this point yet 😉

I’m back

In the last couple of weeks two important things happened: after several secret LCTPs, Microsoft released a new public build of VS 2010 (the Release Candidate), and… I got married 🙂 I spent the honeymoon at Argentina, which has arguably the most impressive natural wonder of planet Earth (the Iguazu Falls), and impressive glaciers too (Perito Moreno). And if you like to eat meat, the beef is superb. Definitely a very recommendable traveling destination.

I have just downloaded VS 2010 RC and I am installing it. I don’t expect many changes from previous LCTPs since the focus of this build was only performance fixes, but it is a big change from the last public build (Beta 2), which was unusable for add-ins due to commandbar bugs (that I blogged a lot about in last months). All the critical bugs that I reported were fixed in LCTPs but not the minor bugs. I will change to “public” my private bugs to Microsoft for my next posts but basically VS 2010 will be a release with some bugs relating its new WPF-based commandbars. I was able to workaround most of them so Microsoft told me that they would prefer not to fix them, to avoid the risk of breaking something else.