Function to speed-up the execution of the first PowerCLI cmdlet

PowerCLI logo
Last year there was a post on the PowerCLI Team blog called How to speed-up the execution of the first PowerCLI cmdlet. That post showed commands you need to execute to pre-compile some of the PowerCLI code to prevent this from being done in every PowerCLI session.

Running these commands will speed-up the execution of the first PowerCLI cmdlet you run in your session. The blog post was made before PowerCLI 5.0 was released and didn’t show the commands to speed-up PowerCLI 5.0. Later there was a post at the vNugglets blog Speed Up First PowerCLI 5 cmdlet — Precompile XMLSerializers that shows the commands needed for PowerCLI 5.0.

But what happens when PowerCLI 5.1 or 6.0 is released? Of course we can try to find the new commands needed to speed-up PowerCLI every time a new version is released. But would it not be easier if we have a function that will do this for you?

The Install-PowerCLIXmlSerializer function presented in this post will show you a PowerShell function that you need to run once after you install a new PowerCLI version to speed-up the execution of the first cmdlet every time you run PowerCLI.

The Install-PowerCLIXmlSerializer function

The Install-PowerCLIXmlSerializer function searches in the Global Assembly Cache on your computer for all the PowerCLI XML Serializers available. Then the function will pre-compile all these PowerCLI XML Serializers.

After the installation of a new PowerCLI version you have to run this function once. If you us both the 64-bit and 32-bit PowerCLI versions then you have to run this function once in both the 32-bit and 64-bit version of PowerCLI.

Make sure you run the Install-PowerCLIXmlSerializer function in a PowerShell session that you “Run as Administrator”.

function Install-PowerCLIXmlSerializer {
  <#
    .SYNOPSIS
      Installs all the PowerCLI XmlSerializers.

    .DESCRIPTION
      Installs all the PowerCLI XmlSerializers.
	  This is needed to speed-up the execution of the first PowerCLI cmdlet that is run in a PowerCLI session.
	  After you install a new version of PowerCLI you only have to run this function once.
	  If you use both the 32-bit and the 64-bit version of PowerCLI then you have to run this function in both versions.
	  You must run this function with administrative privileges enabled.

    .EXAMPLE
      PS C:\> Install-PowerCLIXmlSerializers

    .INPUTS
      None

    .OUTPUTS
      System.String

    .NOTES
      Author:  Robert van den Nieuwendijk
      Date:    18-2-2012
      Version: 1.0
  #>
  
  # Create an alias for ngen.exe
  Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe)
  
  # Install all the PowerCLI XmlSerializers
  Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers | `
  ForEach-Object {
    if ($_) {
      $Name = $_.Name
      Get-ChildItem -Path $_
    }
  } | `
  Select-Object -Property @{N="Name";E={$Name}},@{N="Version";E={$_.Name.Split("_")[0]}},@{N="PublicKeyToken";E={$_.Name.Split("_")[-1]}} | `
  ForEach-Object {
    if ($_) {
      ngen install "$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)"
    }
  }
}

Listing 1. PowerShell Install-PowerCLIXmlSerializer function to speed-up the execution of the first PowerCLI cmdlet you run in your PowerCLI session.

About Robert van den Nieuwendijk
Robert van den Nieuwendijk is a freelance senior systems engineer with over 30 years of experience in the IT industry. He focusses on VMware vCloud Suite and Microsoft Windows Server. He tries to automate as much of his work as possible using Microsoft PowerShell. Robert is the author of the books “Learning PowerCLI” and “Learning PowerCLI – Second Edition.” Robert is a frequent contributor and moderator at the VMware VMTN Communities. He has a bachelor degree in software engineering and holds the following IT certifications and accreditations: VSP 2016, VTSP 2016, VCP4-DCV, VCP5-DCV, VCP6-DCV, VCP6-CMA, VCA-Cloud, VCA-WM, VCA-NV, VMSP, VMTSP, ZCS, ZCP, ZCP-Cloud, MCSE, MCSA, MCP, MCP+I, PRINCE2 Foundation and ITIL Foundation. In 2012, 2013, 2014, 2015, 2016, 2017, 2018 and 2019 Robert received the VMware vExpert award for his contribution to the community of VMware users over the past year. In 2017 Robert also received the VMware vExpert Cloud award. PernixData made him in 2015 a member of the PernixPro.

7 Responses to Function to speed-up the execution of the first PowerCLI cmdlet

  1. Tim says:

    Thanks for the function Robert.
    Should you un-install the pre 5.1 versions or are they still required?

    For example I have:
    VimService25.XmlSerializers
    VimService40.XmlSerializers
    VimService41.XmlSerializers
    VimService50.XmlSerializers

  2. bwuch says:

    I have been using this function and it works great. However, I have found a scenario where it doesn’t appear to be improving performance. I have a Windows 2008 R2 server running PowerCLI 5.1 Release 1 build 793510 where performance of the first PowerCLI command is still slow — but only when using 64-bit powershell sessions. The performance does improve for the 32-bit powershell session on the same server. Has anyone else seen similar behavior?

  3. Roy says:

    I found that I needed to also compile the 64 bit version too:
    putting this after the set-alias for ngen:
    $TargetWMI = @{
    Win32_Processor = Get-WmiObject -Class Win32_Processor
    } # end hash
    if ($TargetWMI.Win32_Processor.AddressWidth -eq 64) {
    Set-Alias ngen64 (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() -replace “Framework64”, “Framework”) ngen.exe)
    } # end if

    putting this after where you call the current ngen install:

    if ($TargetWMI.Win32_Processor.AddressWidth -eq 64) {
    Write-Host “precompiling 64bit $($_.Name) $($_.Version)”
    ngen64 install “$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)”
    } # end if

    • KEB says:

      Very nice!

      @roy: Its not working with more than one processor machines. But you are right. Its necessary to compile it for 64bit as well.

      I’ve changed it a bit to select the first processor (full code without surrounding function):

      # Create an alias for ngen.exe
      Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe)
      $TargetWMI = @{
      Win32_Processor = Get-WmiObject -Class Win32_Processor
      } # end hash
      if (@($TargetWMI.Win32_Processor)[0].AddressWidth -eq 64) {
      Set-Alias ngen64 (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() -replace "Framework64", "Framework") ngen.exe)
      } # end if

      # Install all the PowerCLI XmlSerializers
      Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers | `
      ForEach-Object {
      if ($_) {
      $Name = $_.Name
      Get-ChildItem -Path $_
      }
      } | `
      Select-Object -Property @{N="Name";E={$Name}},@{N="Version";E={$_.Name.Split("_")[0]}},@{N="PublicKeyToken";E={$_.Name.Split("_")[-1]}} | `
      ForEach-Object {
      if ($_) {
      ngen install "$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)"
      if (@($TargetWMI.Win32_Processor)[0].AddressWidth -eq 64) {
      Write-Host "precompiling 64bit $($_.Name) $($_.Version)"
      ngen64 install "$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)"
      } # end if
      }
      }

  4. peleg says:

    Hi Keb/Robert,

    i tried your code and the line
    Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers
    didn’t return anything, so i tried
    PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-ChildItem -Path C:\Windows\Microsoft.NET\assembly\GAC_MSIL\VimService
    *.XmlSerializers which returned :

    VimService60.XmlSerializers

    from command line i did :
    c:\Windows\Microsoft.NET\Framework\v4.0.30319>ngen.exe install “VimService60.XmlSerializers, Version=6.0.0.0, Culture=ne
    utral, PublicKeyToken=10980b081e887e9f”
    and the result is :
    Microsoft (R) CLR Native Image Generator – Version 4.0.30319.33440
    Copyright (c) Microsoft Corporation. All rights reserved.
    All compilation targets are up to date.

    should the order be first compile then Robers and yours script?
    when i run your script it doesn’t print anything although i am on 64 bit machine.
    any idea?

Leave a comment