PowerCLI is great tool, and the Team behind it surprises us on a regular basis with a new Release. With the v6.x generation we witnessed the introduction of Modules. And the Team keeps adding further integration with other VMware products.
With the PowerCLI installation comes a shortcut to a PowerShell sessions, loaded with all the PowerCLI goodness. And this is ideal to make your first steps in the wonderful world of PowerShell and PowerCLI.
But soon you’ll start using more advanced features of PowerShell. You’ll be scheduling jobs, running parallel workflows, start using PowerCLI in Desired State Configuration (DSC). At that moment, the simple PowerCLI session doesn’t cut it anymore, and even the Init scripts that are installed together with PowerCLI, will not give you the exact environment as you want it. Hence my Universal PowerCLI Loader!
I have been using a “Universal PowerCLI loader” function since quite some time now. I thought it was time to prettify it a bit, and share it with the community.
To create the Universal PowerCLI loader, I first needed to take stock of what all the different PowerCLI versions require and bring. The result of that inquiry is reflected in the following spreadsheet.
Some clarifications on the table:
Columns E, F and G: contain hyperlinks to the respective Release Notes, Download link and Online Helppage for each PowerCLI release. Note that the download will require you to enter a MyVMware account.
Columns H and I: the minimum and maximum supported PowerShell version
Columns J and K: the minimum and maximum supported OS (for workstations) on which you can use PowerCLI
Columns L till P: the required .Net version
Columns Q and R: the minimum and maximum supported vSphere version. These are just an indication, always use the VMware Product Interoperability Matrixes to determine which version is required.
Columns U and V: the number of cmdlets available for the “regular” modules and for the “Cloud” modules. To get the total number of cmdlets in a specific release, add these two numbers together.
Some interesting observations that can be made from this table:
- The table starts with PowerCLI 5.1.0.2, since I personally think you should never need an older version. If you do, let me know, and I’ll see if I can expand the table and the function.
- Notice that with PowerCLI 5.8 a separate installation for PowerCLI for Tenants was introduced (row 7)
- With the PowerCLI v6.x series, modules were introduced
- Not all cmdlets are currently migrated from PSSnapins to Modules, hence the mix of PSSnapin and Modules
- WMF 5 support is included from the PowerCLI v6.3. Note that this is for the WMF 5 that comes with Windows 10. The WMF 5 that is still in preview, and that will probably be released with Windows 2016, is not yet officially supported
The Function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
function Enable-PowerCLI { <# .SYNOPSIS Load PowerCLI modules and PSSnapins .DESCRIPTION This function will load all requested PowerCLI modules and PSSnapins. The function will, depending on the installed PowerCLI version, determine what needs to be loaded. .NOTES Author: Luc Dekens .PARAMETER Cloud Switch to indicate if the Cloud related cmdlets shall be loaded .PARAMETER InitScript The PowerCLI PSSnapin have associated initialisation scripts. This switch will indicate if that script needs to be executed or not. .EXAMPLE PS> Enable-PowerCLI .EXAMPLE PS> Enable-PowerCLI -Cloud #> [CmdletBinding()] param( [Switch]$Cloud, [Switch]$InitScript ) $PcliPssnapin = @{ 'VMware.VimAutomation.License' = @(2548067) 'VMware.DeployAutomation' =@(2548067,3056836,3205540,3737840) 'VMware.ImageBuilder' = @(2548067,3056836,3205540,3737840) } $PcliModule = @{ 'VMware.VimAutomation.Core' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.Vds' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.Cloud' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.PCloud' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.Cis.Core' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.Storage' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.HA' = @(2548067,3056836,3205540,3737840) 'VMware.VimAutomation.vROps' = @(3056836,3205540,3737840) 'VMware.VumAutomation' = @(3056836,3205540,3737840) 'VMware.VimAutomation.License' = @(3056836,3205540,3737840) } # 32- or 64-bit process $procArch = (Get-Process -Id $pid).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"] if($procArch -eq 'x86'){ $regPath = 'HKLM:\Software\VMware, Inc.\VMware vSphere PowerCLI' } else{ $regPath = 'HKLM:\Software\WOW6432Node\VMware, Inc.\VMware vSphere PowerCLI' } # Check if PowerCLI (regular or Tenant) is installed if(!(Test-Path -Path $regPath)) { $regPath = $regPath.Replace('VMware vSphere PowerCLI','VMware vSphere PowerCLI for Tenants') if(!(Test-Path -Path $regPath)) { Throw 'Can not find a PowerCLI installation!' } } # Get build $buildKey = 'InstalledBuild' Try{ $pcliBuild = Get-ItemProperty -Path $regPath -Name $buildKey | Select -ExpandProperty $buildKey -ErrorAction Stop } Catch{ Throw "PowerCLI doesn't seem to be installed on this system!" } # Get installation path $installPathKey = 'InstallPath' Try{ $pcliInstallPath = Get-ItemProperty -Path $regPath -Name $installPathKey | Select -ExpandProperty $installPathKey -ErrorAction Stop } Catch{ Throw "PowerCLI doesn't seem to be installed on this system!" } # Load modules if($pcliBuild -ge 2548067) { $loadedModule = Get-Module -Name VMware* -ErrorAction SilentlyContinue | %{$_.Name} if($loadedModule -and $pcliBuild -ge 3737840) { $loadedModule = $loadedModule | where{$_ -notmatch 'Common$|SDK$'} } $targetModule = $PcliModule.GetEnumerator() | where{$_.Value -contains $pcliBuild} | %{$_.Key} $targetModule = $targetModule | where{$loadedModule -notcontains $_} if(!$Cloud) { $targetModule = $targetModule | where{$_ -notmatch 'Cloud'} } if($targetModule) { $targetModule | where{$loadedModule -notcontains $_.Name} | %{ Import-Module -Name $_ -Verbose:$false } } } # Load PSSnapin $loadedSnap = Get-PSSnapin -Name VMware* -ErrorAction SilentlyContinue | %{$_.Name} if($pcliBuild -ge 3737840) { $loadedSnap = $loadedSnap | where{$_ -notmatch 'Core$'} } $targetSnap = $PcliPssnapin.GetEnumerator() | where{$_.Value -contains $pcliBuild} | %{$_.Key} $targetSnap = $targetSnap | where{$loadedSnap -notcontains $_} if(!$Cloud) { $targetSnap = $targetSnap | where{$_ -notmatch 'Cloud'} } if($targetSnap) { $targetSnap | where{$loadedSnap -notcontains $_} | %{ Add-PSSnapin -Name $_ -Verbose:$false # Run initialisation script if($InitScript) { $filePath = "{0}Scripts\Initialize-{1}.ps1" -f $pcliInstallPath,$_.ToString().Replace(".", "_") if (Test-Path $filePath) { & $filePath } } } } } |
Annotations
Line 27-44: in these tables the relation between the PowerCLI version and the required modules and PSSnapin are defined
Line 47-53: depending if the PowerShell session is a 32- or 64-bit process, another registry branch needs to be accessed.
Line 56-63: check if PowerCLI, or PowerCLI for Tenants, is actually installed on the station before continuing
Line 66-83: the buildnumber and the installation path are retrieved from the registry
Line 86-106: loads the requested PowerCLI modules, if we are in a PowerCLI v6.x environment. The logic first determines which modules are available, then substracts the ones that are already loaded and finally loads the missing ones. This means that the function can be called more than once.
Line 94: in combination with the table, define earlier, this line will check for each known PowerCLI module, if it is present in the current PowerCLI installation.
Line 109-135: similar logic as before with the modules, to load the required PowerCLI PSSnapins.
Line 127-133: execute the PSSnapin initialisation scripts if requested. The default is not to run these scripts.
Sample Usage
The purpose of the function is quite straightforward, it loads the PowerCLI PSSnapin and modules. The call to the function can be placed in the beginning of your scripts. No more need to handle the loading of PowerCLI in your scripts.
1 |
Enable-PowerCLI |
This will load all PowerCLI PSSnapins and modules, depending on the installed PowerCLI version, minus the Cloud related modules and PSSnapins.
If you need the Cloud functionality, you just need to do
1 |
Enable-PowerCLI -Cloud |
The Enable-PowerCLI function is available on my Github Scripts repository.
Note that the Enable-PowerCLI function can not be added to a module. The Add-PSSnapin cmdlets executed inside a module, are not propagated to the caller!
This is a know, unresolved issue.
Enjoy!
Nawir
I got this error with esxi 6.7
PS C:\> Connect-VIServer -Server 192.168.88.201 -User root -Password Password
Name Port User
—- —- —-
192.168.88.201 443 root
PS C:\> ls .\Clone-MasterVM.ps1 -MasterName WIN2016 -CloneName AD1 -DatastoreName 600GB -register
Get-ChildItem : A parameter cannot be found that matches parameter name ‘MasterName’.
At line:1 char:25
+ ls .\Clone-MasterVM.ps1 -MasterName WIN2016 -CloneName AD1 -Datastore …
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
Sam
Hi.. I am not versed in Powershell or PowerCLI.. but found this function very handy. Is there way to just include it in a powershell script so it prepares the environment within the script and not call out to a function? If so.. how would i go abouts doing that?
I am asking as i have a laundry list of PowerCLI and need to run a very simple get-dvswitch but cannot execute from powercli (need to invoke thru command.com -> powershell.exe).
Any help is much appreciated!
Sam
Graham Mitchell
Any plans to update this for PowerCLI 6.5R1?
Graham
Alex
This is great work and seems really cool Luc! I am trying to build up mu proficiency with both PowerCLI and Powershell and wanted to ask how this is used. Does this script need to be executed in Powershell? or in PowerCLI? Once executed, it installs what is needed and then one can simply add the “Enable-PowerCLI” at the beginning of a script? Sorry for the “noob-like” questions, but this is something I am trying to get a grasp of.
LucD
Hi Alex,
PowerCLI is added on top of PowerShell.
And yes, you load the function and then you call Enable-PowerCLI.
This should make sure that all required PSSnapins and modules for PowerCLI are loaded.
Nick M
I also just ran into an issue with my version of powercli, which was 3639347, which wasn’t a part of the arrays you put together for $pclipssnapin and $pclimodule, so nothing happened.
I’m not good enough at powershell to know how to make the version checking component that you put in more tolerable to changes if folks were to have a newer, older, or different version loaded, but that may make it better and more modular for the future if that was there. 🙂
LucD
I don’t seem to have that specific build in my “official” list of PowerCLI versions.
I strongly suspect that this is a private beta that came just before PowerCLI 6.3R1.
I did, on purpose, not include support for beta releases. If you run a beta, you’re on your own 🙂
Nick M
Hi LucD, to get your powershell header items to work, they need to exist on their own lines. If you do help on your function, it currently doesn’t report back proper information. But once on new lines, everything looks good.
LucD
Thanks, I corrected that, on my blog and on the Github repository
Damien Solodow
Looks really cool. 🙂 Any plans to publish on GitHub/PowerShellGallery?
LucD
Yes, was planning on starting a module on Github/PSGallery with some of my functions in there.
LucD
Unfortunately, as I discovered, you can’t use Add-PSSnapin cmdlets inside a module. The loaded PSSnapin will not be propagated to the caller.
This is a known issue I’m afraid.