Saturday, March 31, 2012

B1248 LED Name Badge C# / .NET API

I am working on an open source API for the B1248 LED name badge that I got from CodeMania in Auckland, New Zealand. So far, it is possible to send any ASCII message to the device in the first slot, so it is useful as a display attached to a computer.

The code is not complete and I am definitely open to contributions!!

Find the code at BitBucket: https://bitbucket.org/bartj/led

Friday, March 23, 2012

Work with a "shadow copy" of your file system

Sometimes it is useful to be able to take a snapshot of the file system as it currently stands while still having programs use / access it. The reason I wrote this PowerShell script is that I want to be able to copy virtual machines around while still accessing them. Unfortunately, copying virtual machines takes a long time due to their size, so it is useful to be able to copy them while they are in use. This script allows me to shut down the virtual machine, start the copy operation, and then restart the virtual machine while the copy is still in progress.

Notes / caveats:

  • This script requires administrative privileges.
  • The script is naive and does not work if the folder you want to work with is inside a mount point or directory junction (this situation is usually rare).
  • The script leaves a symbolic link in the temp folder, so these may accumulate over time.

function CreateShadowCopy([string]$LocationToOpen) {
    if(-not $LocationToOpen -or -not (test-path $LocationToOpen)) {
        $LocationToOpen = get-location
    }
    if(-not (get-item $LocationToOpen).PSIsContainer) {
        $LocationToOpen = split-path -Parent $LocationToOpen
    }
 
    $fullPath = (resolve-path $LocationToOpen).Path
    $fileRoot = [system.io.path]::GetPathRoot($fullPath)
    $shadow = (Get-WmiObject -list win32_shadowcopy).Create($fileRoot, "ClientAccessible") 
    $shadowRoot = join-path $env:temp $shadow.ShadowID
    $shadowPath = gwmi win32_shadowcopy | ? { $_.Id -eq $shadow.ShadowID } | select -ExpandProperty DeviceObject
    cmd /c mklink /d $shadowRoot $shadowPath\ | out-null
    $rootlessCurrentPath = $fullPath.substring($fileRoot.length)
    join-path $shadowRoot $rootlessCurrentPath
}

$shadowPath = CreateShadowCopy D:\
try {
    pushd $shadowPath

    ls .
    echo "Do stuff..."
}
finally {
    popd
    cmd /c rd $shadowPath
}

Tuesday, January 24, 2012

Direct Booking does not successfully book a resource in Outlook 2010

The Microsoft support article entitled Direct Booking does not successfully book a resource in Outlook 2010 discusses how to solve a problem booking resources in Outlook 2010. The following PowerShell one-liner will fix the problem:
New-ItemProperty "HKCU:\Software\Microsoft\Office\14.0\Outlook\Options\Calendar" EnableDirectBooking -Value 1 -PropertyType DWORD

Wednesday, January 18, 2012

Installing printers using PowerShell

Our developer team has a wiki page that describes very clearly how to use the Windows 7 UI to install network printers into developer machines. The document is well written, with all steps accompanied by screenshots. However, it is tricky and boring to follow, so I thought there must be a simpler way to add printers using PowerShell - and it turns out there is.

$net = New-Object -Com WScript.Network
$net.AddWindowsPrinterConnection('\\server\printer')

Saturday, January 7, 2012

Removing old versions of Chrome using PowerShell

Google Chrome leaves older versions of itself on disk, which can cause useful vulnerability scanners such as the fantastic Secunia PSI to report Chrome as vulnerable although the older version is not in use.

To automatically remove older versions from the current user, run the following PowerShell one-liner.

dir ~\AppData\Local\Google\Chrome\Application | ? { $_ -match '\d+\.\d+\.\d+\.\d+' } | % { @{ File=$_; Version=(New-Object System.Version $_.Name) } } | sort -Descending Version | select -Skip 1 | % { del -fo -r $_.File.PSPath }

Versioning .NET assemblies

Providing meaningful version numbers to PE binaries (.EXEs and .DLLs) is a very good way to make sure that you can always find the correct source code that was used to build. Note that this should be used in conjunction with a symbol server, which is so trivially easy to set up in TFS 2010 that everyone should be doing it.

This is my currently recommended way for using the various versions available in .NET assemblies. Note that it is subject to change as new and better ideas come along!


The AssemblyVersion.cs file

Set up a single C# file that you will include in all your assemblies that need to be given the same version number. I currently give all the DLLs in a single releasable product the same version number so future releases of an assembly will have a new version number, regardless of whether any of the code in that DLL has actually changed. I find this the simplest way to ensure consistency of the product through the full SDLC. In this C# file, which could be called AssemblyVersion.cs, your continuous integration (CI) server will generate something like the following code:

using System.Reflection;

[assembly: AssemblyVersion("1.0.2.23456")]
[assembly: AssemblyInformationalVersion("1.0.1beta1 ($/Project/Main;223456)")]

You will need to put this file in a common location and include it as a linked file in each of your projects. This common file replaces the versioning information that is usually in AssemblyInfo.cs, so you will need to remove those attributes from each project that you include AssemblyVersion.cs in.


AssemblyVersion.cs in development and production

I like to make version number obviously different when building on developer machines, so I typically set the version to 0.0.0.0 or - in case Visual Studio Code Analysis complains - 0.0.0.1. The following AssemblyVersion.cs file would be checked into source control:

using System.Reflection;

[assembly: AssemblyVersion("0.0.0.0")]
[assembly: AssemblyInformationalVersion("development")]
And the following PowerShell script would be launched from within TFS, Jenkins, Cruise Control, or your CI server of choice to modify AssemblyVersion.cs.
param(
        [parameter(mandatory=$true)][int]$MajorVersion,
        [parameter(mandatory=$true)][int]$MinorVersion,
        [parameter(mandatory=$true)][int]$SourceRevision,
        [parameter(mandatory=$true)][string]$SourceBranch
)

#validate source parameters
if($SourceRevision -lt 0 -or $SourceRevision -gt 6553565535) {
    throw "Invalid SourceRevision."
}
if($MajorVersion -lt 0 -or $MajorVersion -gt 65535 -or $MinorVersion -lt 0 -or $MinorVersion -gt 65535) {
    throw "Invalid major / minor version."
}

$scriptFolder = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$versionFile = resolve-path (join-path $scriptFolder 'AssemblyVersion.cs') # script must be in the same folder as AssemblyVersion.cs

if(-not (test-path $versionFile)) {
    throw "Unable to find version file."
}

#calculate Build/Revision version component
if($SourceRevision -le 65535) {
    $rev1 = 0
    $rev2 = $SourceRevision
} 
else {
    $verStr = $SourceRevision.ToString()
    $rev2 = [int][string]::Join('', $verStr[-5..-1])
    if($rev2 -gt 65535) {
        $rev2 = [int][string]::Join('', $verStr[-4..-1])
    } 
    $rev1 = [int]$verStr.SubString(0, $verStr.length - $rev2.ToString().length)
}

$assemblyVersion = "$MajorVersion.$MinorVersion.$rev1.$rev2"
$humanVersion = $SourceBranch + ':' + $SourceRevision

Write-Host "Setting assembly version to $assemblyVersion and human readable version to '$humanVersion'."

(type $versionFile) -replace '0.0.0.0',$assemblyVersion -replace 'development',$humanVersion | Out-File -Encoding UTF8 $versionFile

AssemblyVersionAttribute

The Assembly version will by default also be set as the AssemblyFileVersion if the latter is not explicitly specified. One important piece of information I want to include is the revision number of the source code that was used to make the build. Each component in the AssemblyVersion is limited to 65535 (16 bit). Since it won't take long for 65535 revisions to be committed when checking in early and often, I spill over into the build number in a human readable fashion, so version 1.0 built from revision 223456 would be 1.0.2.23456.


AssemblyInformationalVersionAttribute

The AssemblyInformationalVersion attribute is a very useful free text string that will appear in the Product Version field when looking at the details of the DLL in Windows Explorer. I sometimes use a semantic version as the first part of that string, and always include an unambiguous reference to the source code that was used to build it i.e. branch and revision details for whatever source control system is in use.