Macro to Restart Visual Studio Elevated
Kevin Dente ponders on Twitter:
This is something I’ve been meaning to do for a while, as often I’ll open a Web Application in Visual Studio configured to run under IIS and be met with the following:

Running anything elevated is easy, you just need to call ShellExecute (the .NET equivalent is System.Diagnostics.Process.Start) with the “RunAs” verb, so it’s simply a matter of starting Visual Studio’s devenv.exe passing the path to the current solution.
So here goes: copy and paste this into a Macro Module (ALT+F11) then wire up to a toolbar button as appropriate:
Sub ElevateVisualStudio()
Dim slnPath As String = DTE.Solution.FullName
DTE.Solution.Close(True)
Dim startInfo As New System.Diagnostics.ProcessStartInfo(DTE.FullName, slnPath)
startInfo.Verb = "RUNAS"
System.Diagnostics.Process.Start(startInfo)
DTE.Quit()
End Sub
Works On My Machine™, etc and only tested on Visual Studio 2008.
Using Windows 7’s “XP Mode” to run IE 6, IE 7 and IE8 side-by-side
Windows 7’s XP Mode is essentially a Windows XP virtual machine that runs in the new Windows 7 version of Virtual PC. This new edition of Virtual PC includes cool features such as seamless windows. The main reason I’m interested in this is to run older versions of Internet Explorer for testing purposes. IE8’s compatibility mode does a pretty good job of emulating IE7 but there are differences, so I investigated how to get “real” IE7 running under Windows 7’s XP Mode, without losing IE6.
Out of the box, the Virtual PC image is Windows XP SP3 with IE6. The trick to getting IE6 to appear as a seamless window like this is to launch the Virtual Windows XP virtual machine and in the VM, create a shortcut in the “All Users” Start Menu or desktop:

After a short delay, the shortcut will be duplicated into the Windows 7 host’s start menu:

When you launch this shortcut in Windows 7, the main Virtual PC window will close and the application will be launched and projected onto your desktop.
Creating a VM for IE7
You can’t install IE7 side-by-side with IE6 on the same machine, so to run IE7 at the same time as IE6 we will need to create a new VM. Unfortunately, if you run the VirtualWindowsXP.msi setup again you’ll get a message saying “Setup has detected that Virtual Windows XP is already installed”:

The workaround is to create a new instance of the VM manually using the supplied VHD as the base disk image. To do this do the following:
Open the Virtual Machines folder from the Start Menu and click Create virtual machine:

Specify a name and location for the virtual machine:

For memory I specified 256MB, which should me more than enough for just running IE7:

Here’s the important bit. Choose “Create a virtual hard disk using advanced options”

…and then choose a Differencing disk. This is the same way that the default Virtual Windows XP VM is set up:

If you want, you can change the default name and location (I didn’t bother):
For the parent virtual hard disk choose the original Virtual Windows XP virtual disk, which on my machine was at C:\Program Files\Virtual Windows XP\Virtual Windows XP.vhd:

Now start the new Virtual PC you just created from the Virtual Machines folder and complete Windows Setup as appropriate, choosing a computer name unique for your network and an Administrator password:

When that’s done:
- Enable Integration Features from the Tools menu of the Virtual PC window
- For credentials enter Administrator and the password you entered during setup.
- I chose to Remember my credentials for convenience
- download and install IE7 in the VM,
When IE7 has installed and rebooted, create a shortcut to IE7 in the “All Users” start menu which, after a short delay, will create a corresponding shortcut in the Windows 7 start menu of the host.

So here’s the end result, IE6, IE7 and IE8 all running on Windows 7:

Ahhh, 3 generations, all together – don’t they look adorable?
Fixing WebSVN “Unable to call svn command” error
WebSVN is a great PHP web-based interface to Subversion that we run on our IIS build server. But, after updating to a more recent build we started getting errors like the following when viewing diffs:
Unable to call svn command "svn --non-interactive --config-dir /tmp"
The source of the error is in the getFileContents function in svnlook.php, where it’s piping the output of svn cat to GNU Enscript (for syntax highlighting) and then parsing the output of that using sed. I guessed that maybe the regex that sed is using isn’t being escaped properly for the Windows command line and therefore failing.
But I noticed that all of this code was in an if($config->useEnscript) block. Just before that is an if($config->useGeshi) block that looks a lot simpler. Simpler because GeSHi is PHP-based syntax highlighter, rather than an external command whose output requires special parsing. So I went to our include/config.php and added the $config->useGeshi(); call (as detailed in the distconfig.php template config file), and it all started working happily again!
Unzipping/extracting MSI files
If, like me, you are constantly wanting to just extract the files from a Windows Installer MSI file quickly, then this is for you.
My ZIP utility of choice 7-Zip appears to support extracting MSI files but in fact extracts all the various weird and wonderful binary streams in the MSI rather than simply just the actual files. Thankfully I stumbled across a Windows Installer switch today after typing msiexec /? that does the job perfectly: the /a “administrative install” switch, e.g.:
msiexec /a foo.msi /qb TARGETDIR="C:\TEMP\Foo"
So, what I’ve done is packaged this up as a little registry tweak that conveniently lets you do this by simply right clicking a file like so:

Copy and paste the following into a *.reg file and double-click it:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\Msi.Package\shell\Extract MSI\command] @="msiexec.exe /a \"%1\" /qb TARGETDIR=\"%1 Extracted\""
Hope that helps!
Fixing “Provider: Unspecified error” when querying LDAP with the ADsDSOObject OLEDB Provider
As part of our logon script we have a Windows Script Host script that was failing with “Provider: Unspecified error” (mmn, helpful) but only on some Windows XP machines.
The offending line of code looked like this:
rs = con.Execute("<LDAP://DC=example,DC=com>; (sAMAccountName="+ username +"); ADsPath; subTree")
After some trial and error the fix was this (see if you can spot the difference):
rs = con.Execute("<LDAP://DC=example,DC=com>;(sAMAccountName="+ username +");ADsPath;subTree")
Can you see what it is? No spaces after the semicolons!
Alternatively the SQL-like syntax also seems to be a bit more forgiving:
rs = con.Execute("SELECT ADsPath FROM 'LDAP://DC=example,DC=com' WHERE sAMAccountName='"+ username +"'")
It appears that with some later version of ADSI ADsDSOObject (or to give it its full title, the “OLE DB Provider for Microsoft Directory Services”) the query syntax strictness has been relaxed. In any case “Unspecifed error” appears to mean “Syntax error” in this case.
Getting a machine’s NetBIOS domain name in C#
I tried to find some mechanism to get the current machine’s NetBIOS domain name (the machine domain, not user domain), but couldn’t find anything in the usual places (e.g. System.Environment). If you want the fancy-schmancy Active Directory DNS domain then you can use Domain.GetComputerDomain().Name from System.DirectoryServices.ActiveDirectory, or another one that I stumbled across in Reflector was IPGlobalProperties.GetIPGlobalProperties().DomainName that lives in System.Net.NetworkInformation. But a simple way of getting the old-skool NetBIOS/LanManager-style machine domain name proved elusive.
Some googling suggested that WMI would provide the answer but I find WMI a little heavyweight, and not always reliable. The information is also probably in the registry somewhere, although I couldn’t find it after a cursory scan. The proper, supported way it would appear is to use the Network Management API. So my solution entailed P/Invoking to netapi32.dll.
If you’re after the same information I hope you find the code below useful. Once you’ve incorporated this in your project, just call the GetMachineNetBiosDomain method. It will return the machine’s Workgroup name if the machine is not domain-joined.
UPDATE: Now works on 64-bit thanks to update sent by Rp Brongers.
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
class NetUtil
{
[DllImport("netapi32.dll", CharSet = CharSet.Auto)]
static extern int NetWkstaGetInfo(string server,
int level,
out IntPtr info);
[DllImport("netapi32.dll")]
static extern int NetApiBufferFree(IntPtr pBuf);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
class WKSTA_INFO_100
{
public int wki100_platform_id;
[MarshalAs(UnmanagedType.LPWStr)]
public string wki100_computername;
[MarshalAs(UnmanagedType.LPWStr)]
public string wki100_langroup;
public int wki100_ver_major;
public int wki100_ver_minor;
}
public static string GetMachineNetBiosDomain()
{
IntPtr pBuffer = IntPtr.Zero;
WKSTA_INFO_100 info;
int retval = NetWkstaGetInfo(null, 100, out pBuffer);
if (retval != 0)
throw new Win32Exception(retval);
info = (WKSTA_INFO_100)Marshal.PtrToStructure(pBuffer, typeof(WKSTA_INFO_100));
string domainName = info.wki100_langroup;
NetApiBufferFree(pBuffer);
return domainName;
}
}
Disabling direct PDF viewing/opening from the web
This worries me (more information). It would appear that you could craft PDFs that could hijack someone’s machine simply by their opening the PDF. This is especially pernicious because Adobe Reader is so intent on integrating PDF into Internet Explorer using various Browser Helper Objects and ActiveX Controls that a “drive-by” hijack would be simple to set up once you’ve crafted the malicious PDF file.
A quick fix (that Works On My Machine™) that prevents the automatic opening/viewing of PDF files from the web is to change the HKEY_CLASSES_ROOT\.pdf\Content Type registry key from application/pdf to something like application/octet-stream. This means that you have to save the files first before opening them.
Some possible scriptable ways of automating this:
Method 1: A .REG file
Save the following into a file with a “.reg” file extension and running using regedit.exe /s filename.reg.
REGEDIT4 [HKEY_CLASSES_ROOT\.pdf] "Content Type"="application/octet-stream"
Method 2: The REG command
Alternatively the following, using the reg.exe command will achieve the same result:
reg add HKCR\.pdf /v "Content Type" /d "application/octet-stream" /f
You obviously still need to be careful about PDFs, you just have the ability now to actively decide whether you want to open them.
Cisco home page FAIL
UPDATE: it’s over 2 hours later now and they’ve finally fixed it :)
Cisco’s home page this morning: looks like they ran out of their allocation of lowercase letter ‘t’ (thanks to Chris Venus for pointing it out):
Or was it “Speak Like an Irishman” day and nobody told me?
Lowercase ‘t’s were being stripped from the source which explains why there were no styles, etc:
Chris reckons it’s a possibly a whitespace-trimming RegEx gone wrong, WDYT?
Setting Google Chrome as the default browser for Adobe AIR apps
UPDATE: Logan Buesching commented to say that Chrome apparently creates “ChromeHTML” shell\open keys except they’re in HKCR (which is why you get a UAC prompt, it’s the machine part of the registry), so you can actually just set HKCU\Software\Classes\.htm to ChromeHTML and you’re done. Logan also goes into more detail as to what’s going on so check out his post.
It seems odd that they end up creating a global HKCR key which ulitimately points to an app that’s installed in a user’s private profile. I’m sure this will cause issues if you have multiple people using your machine. Anyway, I guess this is all a bit moot: this is beta software kids, and I’m sure Google will fix this in due course by release and you may have to undo some of these registry shenanigans for it to work as expected.
Google Chrome was a big hit in the office today. To the extent that many of my colleagues were setting it as their default browser already, even though it’s a beta product. Cwazy.
Unfortunately even if you do click the “Make Google Chrome my default browser” button on the Options page, not all applications that launch hyperlinks comply. One of those is the Twitter client Twhirl, which is an Adobe AIR application (I’m assuming this is an issue with AIR itself rather than Twhirl doing something silly). I deduced what AIR was doing when trying to locate the default browser by using Sysinternals’ Process Monitor (ProcMon). It was using the current user’s “.htm” file association preference: which on my machine was pointing to FirefoxHTML. So I created a new registry key for GoogleChromeHTML that specified the location of chrome.exe as the file opener and pointed the “.htm” setting there, which did the trick.
To make this easier to replicate, and to save having to write tedious explanatory steps detailing exactly what to do – I’ve created a short JScript Windows Script file.
Save the following with a “*.js” file extension (e.g. ChromeDefaultForAIR.js) and run it:
var wshell = new ActiveXObject('WScript.Shell');
var chromePath = wshell.ExpandEnvironmentStrings('%USERPROFILE%\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe');
wshell.RegWrite('HKCU\\Software\\Classes\\.htm\\',
'GoogleChromeHTML');
wshell.RegWrite('HKCU\\Software\\Classes\\GoogleChromeHTML\\shell\\open\\command\\',
'"' + chromePath + '" "%1"');
Normal caveats for editing your registry and downloading and running random scripts from some idiot’s blog apply. To revert, set HKCU\Software\Classes\.htm back to FirefoxHTML.
If it helps leave a note in the comments!
Identifying the unidentified problem with Windows Firewall
Recently Windows Vista has been refusing to show the Windows Firewall Settings dialog box and instead showing the ever so informative message: “Windows Firewall: Due to an unidentified problem, Windows cannot display Windows Firewall settings”.

No clues. Nothing in the Event Log. Nothing. Brilliant.
Well I had a brain wave this morning about what might be causing it. Thankfully it turned out to be right. I remembered that on our Windows Domain we have a few Group Policy settings that apply to Windows Firewall.
In this case the culprit was the “Define program exceptions” that had a few old entries for AVG 7.5 Network Edition. As we’d upgraded to AVG 8.0 recently the program paths were no longer valid, nor really necessary. So I removed them entirely and set the policy back to Not configured. To verify it worked I ran gpupdate /target:computer /force at a command prompt on my workstation and voila: the Windows Firewall Settings dialog box would now appear once more.
Group Policy for Windows Firewall is stored on client machines in the the Registry at:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsFirewall
So if you’re not on a domain and there are registry entries in this location that have been set for some reason, then adjusting them will have the same effect as changing the Group Policy. If you are on a domain then getting the Group Policy fixed is obviously the right approach.
Hope that helps you – leave a comment if it does.
Comments (1)