Speeding Up PowerShell Startup - Updating Update-Gac.ps1

Speeding Up PowerShell Startup - Updating Update-Gac.ps1

  • Comments 18

Have I ever mentioned how much I love the community?  Today Kirill Osenkov posted a comment on the blog pointing out that there was an API to get the .NET Framework install path:  RuntimeEnvironment.GetRuntimeDirectory() .  I didn' t know that and now I do.  :-)

I took the opportunity to rewrite Update-Gac.ps1 and in the process I decided to make it better.  This illustrates the point I've made many times.  With GUIs - you click buttons and that the end you what do you have?  Maybe the system works, maybe it doesn't and that is it.  With scripting, you end up with a system that may or may not work (same as before) BUT you also produce an artifact (a script).  When you share that script - the world changes.  If your script is crap (or just doesn't work) - people will look at it and tell you so and in the process they often tell you how to make it work or make it better.  If it works - often people will show you better ways to accomplish the same task (as Kirill did today). 

Sometimes someone's script will spark an inspiration - "I don't need THAT but if it did THIS, that would be awesome!" and an incentive to create new scripts.

One way or the other, the act of sharing a script improves your world.  You get better.  Others get better. The world gets better.

 So that is one thought.  The other thought is that PowerShell is all about producing scripts OF THE RIGHT QUALITY

Does that mean PowerShell is all about producing high quality scripts?  ABSOLUTELY NOT!

High quality scripts are often very difficult and expensive to write.  We absolutely want to support people that want to do this (we think about the guy who wants to run scripts that run the Federal Reserve Bank's servers or the DataCenter at the CIA [I sure hope both of those environments write high quality scripts]).  BUT we also want to support people that want quick and dirty scripts. 

The task at hand should determine the quality of the script.  For my Update-Gac script, it was a quick and dirty script that I rarely use.  Now that I've decided to share it, I get a little embarrassed by how raw it is so I invested a few minutes this morning to improve the script itself (thanks again to Kirill) and the user experience of the script.  At that is the point, scripts are living things.  That start out and then over time we craft them, buff them, take suggestions from other people, sometimes other people take our scripts and bring them to new levels. 

The efficient and effective creation and sharing of IT artifacts (scripts) is probably the biggest contribution PowerShell can make to the industry.  Said another way, PowerShell doesn't solve your IT problems.  PowerShell helps the IT community to work together to solve it's problems.  This is precisely why we've added Graphical PowerShell (now called PowerShell Integrated Scripting Environment) to V2 - to make it easy to create and debug scripts.  It is also why we added Modules - to make it easier and safer to share scripts.

OK - enough with all that.  Here is the new and improved Update-gac.ps1

Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe)
[AppDomain]::CurrentDomain.GetAssemblies() |
    sort {Split-path $_.location -leaf} |
        $Name = (Split-Path $_.location -leaf)
        if ([System.Runtime.InteropServices.RuntimeEnvironment]::FromGlobalAccessCache($_))
            Write-Host "Already GACed: $Name"
            Write-Host -ForegroundColor Yellow "NGENing      : $Name"
            ngen $_.location | %{"`t$_"}

<Update 12/4/2008> NOTE - this is a workaround for a V1 bug.  This is fixed in V2. 


Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Attachment: update-Gac.ps1
Leave a Comment
  • Please add 8 and 1 and type the answer here:
  • Post
  • PingBack from http://powerscripting.wordpress.com/2008/09/07/episode-40-poshboard-part-duex/

  • you're a masochist :)


  • oh and also gac does not imply ngen. An assembly can be gac'd but have no native image (or it could be invalid) in which case jit still occurs. Of course ngen without gac usually is worse than jit so maybe you should only ngen gac assemblies and always re-ngen them since ngen is smart enough to know if an image is up to date.

    I'd type my version but I'm on my stupid iPhone.  

  • Hello I've run this script on Windows 2008 x64 with Exchange 2007 SP1 and it have not effect to speed up the exchange powershell starting. Sorry.

  • I'm getting a ton of errors indicating assemblies that can not be found... this isn't expected is it?

  • Below is the content of the Update-GAC.ps1 script that I run whenever I install a new version of PowerShell.

  • how do you un-do the power shell change?

  • Similar to Chris' comment earlier... we accidently ran this script while in Exchange Management Shell rather than just in PowerShell.  We saw errors similar to this:

           WRN: Assembly binding logging is turned OFF.

           To enable assembly bind failure logging, set the registry value [HKLM\So


    \Microsoft\Fusion!EnableLog] (DWORD) to 1.

           Note: There is some performance penalty associated with assembly bind fa



           To turn this feature off, remove the registry value [HKLM\Software\Micro



            while resolving 0x100005c - Microsoft.Exchange.Common.IL.FilterDelegate


           Warning: System.IO.FileNotFoundException: Could not load file or assembl

    y 'Mic

    rosoft.Exchange.Common.IL, Version=, Culture=neutral, PublicKeyToken=31b

  • You state this is fixed in V2, but when I installed V2 CTP3, it had the same slow start bug, until I ran this script. This really needs to be fixed.

  • The following are examples I demonstrated to show how easy and powerful PowerShell is to use with Operations

  • I ran both versions of this script under the EMS and regular powershell.  It didn't resolve the EMS start-up problem or the EMC start-up problem.  It is taking over a minute to load each one.  In fact the EMC often times out when "expanding".  It's a real handicap, and additional advice would be appreciated.

  • On my machine I ran this and the script got an error - due to-- after the sort, the first item going into the Split-Path --was null.

    add the following

    if ($_.location){

    ##only if there is a location code executes

    ## within the foreach(%) after the sort


  • Guys, I have 2008 R2 installed, and Powershell startup is really slow.

    Don't know if you fixed anything but this is too much time for the shell.

  • Same as Alex, can't understand why a shell does not fire up in a split of sec when running 8 cpu/16gb of ram.

    This is ridiculous.

  • Could you please let us know in case if there is any other way to speed up the Powershell opening on the Exchange 2010 SP1? is this script also applicable for Exchange 2010 SP1 ? wondering whether or not as Exchange 2010 SP1 is a Remote Powershell. Please clarify this.

    Thanks in advance

Page 1 of 2 (18 items) 12