SlightlyPosher now supports 64bit PowerShell

by Naeem Khedarun 24. July 2011 01:09

 

When trying to write some scripts to automate IIS, I was getting some strange COM errors which were down to trying to run cmdlets targeted at a 64bit process.

It turns out Console2 as a 32bit process can only host a 32bit command prompt, which is unfortunate. Luckily Console2 does have a beta 64bit version, and I’m shipping this side by side with the 32bit version to satisfy everyone.

When you run update.bat you will find a new folder in your root.

image

Running [intptr]::size against the original shell yields:

image

And running it against the new shell:

image

I can now automate my 64bit IIS without errors. If everything is running fine you won’t need the new shell, but at least its there for the day you do need it.

Switching Visual Studio Environment Tools with Powershell and SlightlyPosher

by Naeem Khedarun 13. July 2011 20:35

 

Initially the SlightlyPosher environment configured the VS2008 tools as that was what I need on my project. Pascal was kind enough to send me a patch to use the VS2010 tools instead.

I thought it would be cool to satisfy both users, as not everyone has been lucky enough to switch to VS2010 yet.

In profile.ps1 by default the VS2010 tools are loaded.

Set-VsVars32 2010

image

If you would like to switch this, its as simple as calling:

Set-VsVars32 2008

Now you will have a VS2008 environment and MSBuild 3.5 at your fingertips.

image

The implementation for this is pretty straightforward…

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

function Set-VsVars32($vsYear)
{
   switch ($vsYear)
   {
        2008 {$vstools = $env:VS90COMNTOOLS}
        2010 {$vstools = $env:VS100COMNTOOLS }
   }

   $batchFile = [System.IO.Path]::Combine($vstools, "vsvars32.bat") 
   
   Get-Batchfile -file $batchFile
   
   Write-Host -ForegroundColor 'Yellow' "VsVars has been loaded from: $batchFile"
}

The Get-BatchFile function is provided by many blogs describing how to use the Visual Studio tools with PowerShell. The Set-VsVars32 method takes the year as an argument, and loads the tools for that Visual Studio year.

Run update.bat to get these latest changes. Enjoy!

Finding all projects containing a reference to X assembly using POSH

by Naeem Khedarun 1. July 2011 00:49

 

Finding all the projects which reference a specific assembly can be a little tough in visual studio if you have hundreds of projects. NDepend can do this for you, but that requires you’re willing to pay for a licence (you should) if you need it commercially.

I wrote a little bit of POSH to do this for me…

function Get-ContainsReferenceTo($projectFile, $referenceName)
{
    [xml]$s = get-content $projectFile

    $references = $s.Project.ItemGroup | Where-Object { $_.Reference -ne $null }
    
    foreach($reference in $references.ChildNodes)
    { 
        if($reference.Include -ne $null -and $reference.Include.StartsWith($referenceName))
        {
            return $true
        }
    }

    return $false
}

 

After loading the project file into an XmlDocument, we can iterate through each reference and do a string compare against the reference name.

Running this will return “True” or “False” as to whether the file contains the reference or not.

We can then do this for all project files in a directory by doing:

function Get-ProjectsContainingReferenceTo($directory, $referenceName)
{
    Get-ChildItem $directory -include *.csproj,*.vbproj -Recurse | foreach ($_) { 
        if(Get-ContainsReferenceTo $_.fullname $referenceName -eq $true){ $_.fullname }
    }
}

 

Now if any project files match the reference, the full path of the project file will be output to the command window. We can use this to perform batch operations to change references, remove them or anything else we would like.

I hope you find this useful and you can find it bundled with SlightlyPosher.

Using PowerShell to automate setting CopyLocal to false

by Naeem Khedarun 22. June 2011 12:31

 

It’s been stressed that CopyLocal is slow and evil, so I wanted to see what the impact was on our codebase.

First we need to load the project file and pull out the references sections.

[xml]$s = get-content $projectFile

$references = $s.Project.ItemGroup | Where-Object { $_.Reference -ne $null }
$projectReferences = $s.Project.ItemGroup | Where-Object { $_.ProjectReference -ne $null }

Next we can iterate through the child nodes, and if they are missing the Private tag, add it in.

foreach($reference in $references.ChildNodes)
{ 
    if($reference.Private -eq $null)
    {
        [System.Xml.XmlElement]$copyLocal = $s.CreateElement("Private", "http://schemas.microsoft.com/developer/msbuild/2003")
        $copyLocal.InnerText = "False"
        [Void]$reference.AppendChild($copyLocal) 
    }
}

We can do a similar thing with the project references if your solution builds into a single folder.

foreach($reference in $projectReferences.ChildNodes)
{ 
    if($reference.Private -eq $null)
    {
        [System.Xml.XmlElement]$copyLocal = $s.CreateElement("Private", "http://schemas.microsoft.com/developer/msbuild/2003")
        $copyLocal.InnerText = "False"
        [Void]$reference.AppendChild($copyLocal) 
    }
}

Then all we need to do is save the file and we are done!

$s.save($projectFile)

If you want to apply this too all the project files in a directory, recursively then you could do:

Get-ChildItem $directory -include *.csproj,*.vbproj -Recurse | foreach ($_) { 
    Set-CopyLocalFalse $_.fullname $true
}

You can find the source for this in the SlightlyPosher distribution, or look at the source for the file.

Preliminary tests on our build time dropped from 6:30 minutes to 3:48 minutes thanks to this!