Scott Hanselman

How to change the default browser in Visual Studio programmatically with PowerShell and possibly poke yourself in the eye

August 21, '10 Comments [29] Posted in ASP.NET | ASP.NET MVC | PowerShell | VS2010
Sponsored By

UPDATE: Why my own MacGyver solution was brilliant in its horrible way, the folks over at World of VS have taken up the challenge and created a proper Visual Studio extension that you should use. I'll chat with them and get some details and maybe a write-up of how they did it. So, while I encourage you to enjoy my tale below, go get the World of VS Default Browser Switcher now!

I've heard and seen lots of complaints about how it's hard to set the default browser that Visual Studio launches when you launch a debug session for a website.

Step 0 - Adequate

Folks spend time hunting around the Tools|Options dialog in Visual Studio looking for setting. They eventually realize it's not in there at all, but instead you have to right-click on an ASPX page within a Web Project and click "Browse With..."

Right Click | Browse With

From this dialog you can click Set Default, which is totally obvious, right my daimies? Um, no. This doesn't work for ASP.NET MVC people who use other view engines and might not even have a .ASPX file in their solution. Plus, it's slow and irritating. Sa da tay.

Browse With - Default.aspx 

It IS interesting that I can add other browsers, like Google Chrome to this dialog via Add. Note that Google Chrome installs in C:\Users\Scott\appdata\Local\Google\Chrome\Application\chrome.exe which may not be c:\Program Files where you usually go hunting for these things.

"What my thought process was" - or - "CSI: Visual Studio Default Browser"

Where is this browser information stored? That was my first question. Remember that your computer is NOT a black box. Even good programmers make this mistake and they "flip this switch and hope that light turns on" without confirming that the switch and the light are connected with good wire and they know how electricity works.

I can guess all day, or I can open up ProcMon and just see for myself. Seriously, learn how to use this freaking tool. You can flip light switches all day or you can just open up the wall and see the wires. If you know how to use Process Monitor competently, people of both sexes will immediately find you more attractive. It's true. I get all sorts of free Tacos and Chips when folks look can I run ProcMon like Keanu Reeves can look sad.

I fired ProcMon up set it to only show the devenv.exe process, and I took a chance and set 'contains browser' for the path. If this didn't work I'd open the flood gates and start sifting a bit. I could also have said 'highlight' things with the word browser if I liked.

Process Monitor Filter (2)

I launch VS, open the Browse With dialog and sweet sassy mollassy. Look at all that good stuff.

Process Monitor - Sysinternals www.sysinternals.com

Oh, fonts too small, let me zoom in.

Registry Zoomed In

Looks like we're reading values out of the registry at HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp and...

image 

...reading out of the browsers.xml file at C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0\browsers.xml.

What's in that file? I'm guessing XML with no schema, given it was probably 2003 when someone wrote this.

<?xml version="1.0"?>
<BrowserInfo>
<BrowserInfo>
<Browser>
<Name>Google Chrome</Name>
<Path>"C:\Users\Scott\AppData\Local\Google\Chrome\Application\chrome.exe"</Path>
<Resolution>0</Resolution>
<IsDefault>False</IsDefault>
</Browser>
</BrowserInfo>
</BrowserInfo>

I've seen folks attempt to change this with various extensions in Visual Studio and using automation calls within Visual Studio, but to the best of my knowledge, this feature has been in here for years and years and there's no way to get at it programmatically.

Step 1 - Slightly Awesome

Interestingly as well, my first attempt at changing the browser programmatically consisted of this brilliance:

C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0>copy "browsers - firefox.xml" browsers.xml /y
1 file(s) copied.

But, it seems that those registry keys are serious and really used for something, because each time I opened Browse With... I found my changes thrown away, probably because VS isn't watching for file for change notification, but rather caching the file in memory.

Looks like a job for PowerShell (yes, I know can do this with batch files, but PowerShell is way batter, so nyah. Learn it.)

First I need to figure out what's going on in this registry. If I got to that key (by right-clicking the key within ProcMon and clicking Jump To), then right-click on the key in the Registry Editor I get:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp]
"CacheFilePath"="C:\\Users\\Scott\\AppData\\Local\\Microsoft\\VisualStudio\\10.0\\browsers.xml"
"CacheFileSizeBytes"=dword:000000e6
"CacheFileDateLastMod"=hex(b):6f,18,a4,ee,17,41,cb,01
"LastConfigurationTimestamp"=hex(b):00,26,aa,86,09,41,cb,01

Ok, so that's the location of the file we already know about, and  looks like the file size in hex, as well as some magic goo for CacheFileDateLastMod and LastConfigurationTimestamp.

One at a time. The CacheFileSizeBytes is easy. Did you know that the Windows 7 calculator was quietly upgraded while you were out there not learning how to convert hex in your head? It's true! (Yes, you can also just look at the decimal value in the Registry, but again, this is more fun. Yes, you could always convert between Hex and Dec in calc.exe, but again, fun. What's your beef? ;) )

Calculator in Windows 7 - Being Awesome in Programmer Mode

Click Dec(imal) and looks like 230 bytes, the size of my browser.xml file. What's the deal with those mod dates, though? They a probably a Windows file time, if they aren't ticks. Ticks are seconds since 1970-1-1 and a Windows FileTime is the number of 100-nanosecond ticks since 1601-1-1 rounded to the nearest millisecond. Why? Because 1601 was an awesome year. I mean, the Battle of Kinsale stopped the siege in Kinsale, Ireland, and famine killed half the Estonians. Sheesh, that was a horrible year! What were we thinking!?

Anyway, the easiest way to convert something you think might be a Date into a Date (and reason number 0x3b for you to finally learn PowerShell) is this line in PowerShell.

PS C:\> [DateTime]129268523480000000
Saturday, August 21, 0410 8:19:08 AM

Lemme do that again against a blue background with a screenshot so you really believe me.

Windows PowerShell, again, being awesome.

Oh yes, I'm on a horse. Cool. Those are FileTimes. So, tappity tappity and here's a PowerShell script to check the current values and output them for testing.

cd C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0

$browsers = [xml](get-content 'browsers.xml')
$browsers.BrowserInfo.Browser.Name + " " + $browsers.BrowserInfo.Browser.Path

$regkey = "HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp"

"LastConfigTimestamp: " + ([DateTime](get-itemproperty $regkey).LastConfigurationTimestamp).ToLocalTime()
"CacheFileDateLastMod: " + ([DateTime](get-itemproperty $regkey).CacheFileDateLastMod).ToLocalTime()
"CacheFileSizeBytes: " + (get-itemproperty $regkey).CacheFileSizeBytes

I'll go and develop and run this script in the PowerShell ISE (that's S for Scripting) that you already have on your computer. Freaky how Microsoft sneaks stuff like this on your machine. If you've got Windows 7, you're already got this.

Windows PowerShell ISE (x86)

I run Visual Studio and click Browse|With... a few times and watch the values change. Seems I need the SET to my GET script, so why not something like this. I've made copies of browsers.xml like browsers-chrome and browsers-firefox. You can do the same if you like.

cd C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0 

copy '.\browsers - firefox.xml' .\browsers.xml
$regkey = "HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp"

set-itemproperty $regkey -name LastConfigurationTimestamp -value (&{[DateTime]::Now.ToUniversalTime().ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileDateLastMod -value (&{((dir .\browsers.xml).LastWriteTimeUtc).ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileSizeBytes -value (&{(dir .\browsers.xml).Length}) -type dword

What I am doing in this script? I'm copying my browser xml over the main one AND I'm updating the TimeStamp to now to get Visual Studio to re-read the file. Visual Studio seems to be checking and triple checking and if the CacheFileDateLastMod and CacheFileSizeBytes don't reflect reality, it will freak out and just delete my file completely and rebuild a new browsers.xml from scratch. Paranoid.

You can go and fancy these scripts up with command-line parameters all you want because you're a better programmer than I, but I am all Save|As, baby. I have "UpdateDefaultBrowserToChrome.ps1" and, yes, wait for it, "UpdateDefaultBrowserToFireFox.ps1" and I sleep at night just fine, thank you very much.

I can right click on them on my desktop and select Run with PowerShell if I like.

Right clicking on my PowerShell script on my desktop

But...still....it could be more awesome. Darn my parents and the work ethic they instilled in me as a small child.

Step 2 - Extremely Awesome

You can run PowerShell scripts from the regular not-really-DOS command line like this if you like.

C:\Users\Scott\Desktop>powershell .\UpdateDefaultVSBrowserToChrome.ps1

I could even install PowerConsole and run these commands from INSIDE Visual Studio 2010 if I like and I want to rip a hole in the space time continuum. My, is that intellisense inside PowerShell inside Visual Studio? Double sun power!!!!

Powershell being awesome INSIDE Visual Studio 2010. Double Sun Power!!!!!

Still, this doesn't fit my mindless point and click mouse-like workflow. I'll go to Tools | External Tools and add two. Make sure you select the right PowerShell, which will be x86 even if you're on x64 so you correctly access the registry. I also checked Use Output window and added a single line of text at the bottom of each script.

External Tools 

Nice, but why not a toolbar?

Step 3 - Profit! I mean, Profoundly Awesome!

Right click on any Toolbar, this Customize and add buttons for External Tools (in my case #6 and #7) and...

Switchy Browser Toolbar buttons

Which gives me this when I click:

Pow, Sally. Browser changed to Chrome.

And shows this in Browse With, showing me it worked:

Browse With - Default.aspx again with Chrome

Yay! Enjoy.

Roll Up Instructions

  1. Go to C:\Users\YOURNAME\AppData\Local\Microsoft\VisualStudio\10.0
  2. Make a bunch of browser-whatever xml files for your browsers, or populate your list from Visual Studio, then make copies.
  3. Make yourself a few of these (or make one that switches if you're awesome)
cd C:\Users\YOURNAME\AppData\Local\Microsoft\VisualStudio\10.0

copy '.\browsers - CUSTOMBROWSER.xml' .\browsers.xml
$regkey = "HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp"

set-itemproperty $regkey -name LastConfigurationTimestamp -value (&{[DateTime]::Now.ToUniversalTime().ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileDateLastMod -value (&{((dir .\browsers.xml).LastWriteTimeUtc).ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileSizeBytes -value (&{(dir .\browsers.xml).Length}) -type dword
"Bam, son. Browser changed to CUSTOM BROWSER."
  1. Add some external tools that call PowerShell with your new scripts as parameters.
  2. Add toolbar buttons if you feel like it.
  3. Go write a proper Visual Studio 2010 extension that does all this and packages it up in one click, put in on the VS Gallery and impress your friends and family. Crap. Now *I* need to do that for my next post, don't I? Shoot. Kzu? Give me a call and teach me how to do this.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 228 - Performance of Silverlight on Windows Phone 7

August 20, '10 Comments [2] Posted in Podcast | Silverlight | WinPhone
Sponsored By

4 Windows Phone 7 Series Phones Scott talks to Jeff Wilcox, a Developer on the Silverlight Team about developing on Windows Phone 7. What kinds of performance can we expect from the phone? Jeff Wilcox shows Scott some tips and tricks on how to get the smoothest animations from your phone. Frame Rate Counters and more fun are explained!

NOTE: If you want to download our complete archives as a feed - that's all 228 shows, subscribe to the Complete MP3 Feed here.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Download: MP3 Full Show

Links from the Show

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX,MVC,Silverlight,Windows Formsand WPF. Enjoy developer tools like .NET reporting,ORM,Automated Testing Tools, TFS, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visitwww.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 227 - Inside Expression SuperPreview with developer Mike Calvo

August 20, '10 Comments [0] Posted in ASP.NET | Podcast
Sponsored By

Scott talks to Mike Calvo, a Microsoft Lead Developer based out of Minnesota (!) about Expression SuperPreview. SuperPreview helps developers and designers with cross-browser CSS and HTML issues. How'd they build it and with what? What's inside? How does the cloud fit in and how do they support Safari?

I played with SuperPreview a bit last year, but started looking at it again last month when I noticed that version 4 has introduced support for Safari on Mac via a Cloud-based Remote Service.

I fired up Expression SuperPreview 4, and saw this:

Remove Browsers Beta Signup

Then I signed up:

Signup screen for Expression SuperPreview Remote Browsers Beta

Which enabled Mac Safari for this initial beta. I assume they'll add a pile of other browsers. If I don't see immediate browser support for ALynx, the Amiga port of Unix/VMS Lynx browser, then Microsoft sucks and they don't care about the little guy!

IE6, 7, 8, FireFox 3.6 and Safari 4 Mac in SuperPreview

So now I can compare DOM layouts between Windows FireFox 3.6 (on the left) and Safari 4 Mac (on the right). You can also compare between browsers and PhotoShop comps.

Windows FireFox 3.6 (on the left) and Safari 4 Mac (on the right)

More details on how this works in this episode of the podcast!

NOTE: If you want to download our complete archives as a feed - that's all 227 shows, subscribe to the Complete MP3 Feed here.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Download: MP3 Full Show

Links from the Show

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Hansel_Promo

Hanselminutes podcasts listeners can get $50 off any Telerik product this summer. All interested listeners should drop an email to podcast@telerik.com and mention the Hanselminutes promo and their sales team will reply with the special $50-off coupon code.

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX,MVC,Silverlight,Windows Formsand WPF. Enjoy developer tools like .NET reporting,ORM,Automated Testing Tools, TFS, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visitwww.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 226 - Building your own Ultimate Developer PC 2.0 with Pete Brown

August 20, '10 Comments [3] Posted in Hardware | Podcast
Sponsored By

This Insane Heat Sink Pic was seen at HotHardware.com My two-hundred-and-twenty-sixth podcast is up. Scott catches up with Pete Brown after they've both built their "Ultimate Developer PCs." Any regrets? What'd they learn and how you can learn from their mistakes and successes?

UPDATE: Pete and I did a Skype call with Joel Barsotti and he guided me in the overclocking process and I was able to easily take the 3.33Ghz Intel i7 processor I have to 4.0Ghz, a free 20% speed gain while staying on air cooling. I'm sure I could take it beyond but I don't want to compromise stability. Is a short overclocking show or article something you all are interested in?

NOTE: If you want to download our complete archives as a feed - that's all 225 shows,subscribe to the Complete MP3 Feed here.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Download: MP3 Full Show

Links from the Show

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Hansel_Promo

Hanselminutes podcasts listeners can get $50 off any Telerik product this summer. All interested listeners should drop an email to podcast@telerik.com and mention the Hanselminutes promo and their sales team will reply with the special $50-off coupon code.

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX,MVC,Silverlight,Windows Formsand WPF. Enjoy developer tools like .NET reporting,ORM,Automated Testing Tools, TFS, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visitwww.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Awesome Visual Studio Command Prompt and PowerShell icons with Overlays

August 19, '10 Comments [10] Posted in Musings | PowerShell | VS2010
Sponsored By

I'm not usually one of the "icon people." By that I mean, I don't collect icons, or change all the icons on my system to custom fancypants icons. But, I noticed today that I was using the Command Prompt alongside a Visual Studio Command Prompt (which is just a command prompt with the right path and environment set) as well as regular PowerShell as well as a PowerShell prompt with "VSVars32" set (again, just PowerShell with the right environment setup). However, their icons all look the same.

Seemed like a quick opportunity to edit a few icons and change my world. I went over and downloaded the most lovely Free Icon Editor I know of, IcoFX. I encourage you to donate to them because they are doing the world a wonderful service. I used their Extract command on cmd.exe, as well as devenv.exe and powershell.exe.

 Extract Icon

Disclaimer: I'm sure I'm breaking all sorts of international law or something by doing this. When the ninjas burst in and say "you can't use our icons for fun" I will likely deny having written this post. Back me up on this. I did this for me. This is not official Microsoft anything and you can't say it is. Who are you!? Stop calling me! Jimmy no live here! You no call back!

 

Aside: Here's the part I'm bummed about. It seems that the VS2010 icon editor is still stupid about alpha channels. I'm actually scandalized about the whole thing, but since I don't work on that team, I'll need to dig in to get more details. I would have liked to have done this all in VS.

OK, so now I've got all my icons loaded in IcoFX. I will edit them all and make a nice icon in one of the many resolutions that are available, even though technically I suppose for my use I just need 32x32 icons for the Windows 7 Taskbar and/or my desktop.

IcoFX

A little editing and resizing...seriously, this Icon Editor is a joy. Go now!

IcoFX (3)

I saved these as vscommand.ico and vspowershell.ico and now I have these two nice icons on my desktop.

image

Now I pin the "Visual Studio Command Prompt" to the Taskbar, and it looks like this:

image

I even did a little one for the system menu, 'cause that's how I roll.

image

OK, so that's lovely.

However, when I'm in PowerShell, I'll sometimes switch my VSVars on by running the custom PowerShell VSVars script that I put in my Microsoft.PowerShell_profile.ps1. Remember this one from Chris Tavares?

function Get-Batchfile ($file) {
$cmd = "`"$file`" & set"
cmd /c $cmd | Foreach-Object {
$p, $v = $_.split('=')
Set-Item -path env:$p -value $v
}
}

function VsVars32($version = "10.0")
{
$key = "HKLM:SOFTWARE\Microsoft\VisualStudio\" + $version
$VsKey = get-ItemProperty $key
$VsInstallPath = [System.IO.Path]::GetDirectoryName($VsKey.InstallDir)
$VsToolsDir = [System.IO.Path]::GetDirectoryName($VsInstallPath)
$VsToolsDir = [System.IO.Path]::Combine($VsToolsDir, "Tools")
$BatchFile = [System.IO.Path]::Combine($VsToolsDir, "vsvars32.bat")
Get-Batchfile $BatchFile
[System.Console]::Title = "Visual Studio " + $version + " Windows Powershell"
//add a call to set-consoleicon as seen below...hm...!
}

Why not go completely over the top and combine this with Aaron Lerch's script for "Changing the Windows PowerShell Console Icon"? This way, when I call "vsvars32" I'll also change the Icon for my PowerShell. Crazy.

Here's Aaron's script with a few changes to make it a dot-sourced function and a couple typo fixes. This changes the system menu icon on the fly, but doesn't refresh the taskbar or ALT-TAB yet. Not sure if that's possible?

##############################################################################
## Script: Set-ConsoleIcon.ps1
## By: Aaron Lerch, tiny tiny mods by Hanselman
## Website: www.aaronlerch.com/blog
## Set the icon of the current console window to the specified icon
## Dot-Source first, like . .\set-consoleicon.ps1
## Usage: Set-ConsoleIcon [string]
## PS:1 > Set-ConsoleIcon "C:\Icons\special_powershell_icon.ico"
##############################################################################

$WM_SETICON = 0x80
$ICON_SMALL = 0

function Set-ConsoleIcon
{
param(
[string] $iconFile
)

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | out-null
$iconFile
# Verify the file exists
if ([System.IO.File]::Exists($iconFile) -eq $TRUE)
{
$icon = new-object System.Drawing.Icon($iconFile)

if ($icon -ne $null)
{
$consoleHandle = GetConsoleWindow
SendMessage $consoleHandle $WM_SETICON $ICON_SMALL $icon.Handle
}
}
else
{
Write-Host "Icon file not found"
}
}


## Invoke a Win32 P/Invoke call.
## From: Lee Holmes
## http://www.leeholmes.com/blog/GetTheOwnerOfAProcessInPowerShellPInvokeAndRefOutParameters.aspx
function Invoke-Win32([string] $dllName, [Type] $returnType,
[string] $methodName, [Type[]] $parameterTypes, [Object[]] $parameters)
{
## Begin to build the dynamic assembly
$domain = [AppDomain]::CurrentDomain
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$module = $assembly.DefineDynamicModule('PInvokeModule')
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")

## Go through all of the parameters passed to us. As we do this,
## we clone the user's inputs into another array that we will use for
## the P/Invoke call.
$inputParameters = @()
$refParameters = @()

for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
{
## If an item is a PSReference, then the user
## wants an [out] parameter.
if($parameterTypes[$counter - 1] -eq [Ref])
{
## Remember which parameters are used for [Out] parameters
$refParameters += $counter

## On the cloned array, we replace the PSReference type with the
## .Net reference type that represents the value of the PSReference,
## and the value with the value held by the PSReference.
$parameterTypes[$counter - 1] =
$parameters[$counter - 1].Value.GetType().MakeByRefType()
$inputParameters += $parameters[$counter - 1].Value
}
else
{
## Otherwise, just add their actual parameter to the
## input array.
$inputParameters += $parameters[$counter - 1]
}
}

## Define the actual P/Invoke method, adding the [Out]
## attribute for any parameters that were originally [Ref]
## parameters.
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',
$returnType, $parameterTypes)
foreach($refParameter in $refParameters)
{
$method.DefineParameter($refParameter, "Out", $null)
}

## Apply the P/Invoke constructor
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
$method.SetCustomAttribute($attr)

## Create the temporary type, and invoke the method.
$realType = $type.CreateType()
$realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null,
$inputParameters)

## Finally, go through all of the reference parameters, and update the
## values of the PSReference objects that the user passed in.
foreach($refParameter in $refParameters)
{
$parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1]
}
}

function SendMessage([IntPtr] $hWnd, [Int32] $message, [Int32] $wParam, [Int32] $lParam)
{
$parameterTypes = [IntPtr], [Int32], [Int32], [Int32]
$parameters = $hWnd, $message, $wParam, $lParam

Invoke-Win32 "user32.dll" ([Int32]) "SendMessage" $parameterTypes $parameters
}

function GetConsoleWindow()
{
Invoke-Win32 "kernel32" ([IntPtr]) "GetConsoleWindow"
}

It might also be interesting to make a ".Icon" property on System.Console using PowerShell's "Type Extensions" abilities. That way I could do[System.Console]::Icon = "something.ico", but I'll leave that as an exercise for the reader.

Magical Visual Studio Command Prompt Icons

Remember, we never spoke.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.