Tuesday, August 9, 2011

How to get powershell syntax highlighting in HTML

Step 1: Use PowerGUI.
Aside from the code-highlighting, it's all kinds of awesome.
Step 2: Select the code
Step 3: From the Menu: Edit->Copy As->HTML
Step 4: Paste and enjoy in your Blog.

Finding locked files with OpenFiles

OpenFiles is a command line executable that has been around since XP. It isn't a powershell command so it doesn't produce nice PSObjects to play with, just raw text.

To find a particular file in the daunting amount of output, I do this:

OpenFiles | %{ if ($_.contains("search string")) { $_ } } 

Powershell locks loaded assemblies. Remove-Module doesn't help.

I was testing an assembly generated by Visual Studio. I imported the module into powershell via Import-Module, created the class I wanted, invoked its members, and viewed the results. Then I tweaked the project in Visual Studio and rebuilt. Powershell had the output assembly loaded and locked, so the build failed.

No news there.

The first workaround was to just close powershell and reopen it.

But! I figured I could call Remove-Module and get passed the lock without actually closing Powershell...
While this seemed like a good idea. It failed. Powershell didn't remove the lock it had on the imported assembly and it was still listed in the modules that Powershell was using. Remove-Module didn't remove the module. It just stopped showing up in Get-Modules. In fact, the variables created using the .net dll were still alive in the powershell process. Remove-Module was no solution.

Next! I figured that I would load the module inside of a powershell session and then unload the session.
Enable-PSRemoting
$session = $New-PSSession
Enter-PSSession $session
#Do Stuff
Exit-PSSession
Remove-PSSession $session

This failed as well. :(

Next I figured that I could create an AppDomain, create a Runspace in the AppDomain, do stuff, and then unload the AppDomain. I'm certain that this approach would work, but it isn't worth the time, especially since the following pseudo-shadow copy solution will work just fine:

$fileName = [System.IO.Path]::GetTempFileName()
[Environment]::CurrentDirectory = "myProjectDirectory\bin\x86\Debug"
[System.IO.File]::Copy("MyDll.dll", $fileName + ".dll")
Import-Module ($filename + ".dll")

And thus the module is loaded, and doesn't lock the Visual Studio output files.