Exploring the types exposed by PowerCLI

01/19/2016  |    5 minute read

One of the things I love about PowerShell, is that once we know the fundamentals, we can learn the rest on our own, by just exploring and experimenting. As I like to tell people, discoverability is the number 1 feature of PowerShell.

So let’s see how we can explore PowerCLI assemblies and the object types they expose.

What is an assembly ?

PowerCLI is packaged as a bunch of PowerShell modules (snapins as well, but these are an endangered species so let’s focus on modules).
There are 2 broad types of modules :

  • Script modules
  • Binary modules

Script modules are written in PowerShell and have a .psm1 file extension.
Binary modules are written in C# and are .NET Framework assemblies (.dll).

In the case of PowerCLI, the modules are binary. Well, this is not totally accurate, due to the transition of PowerCLI from snapins to modules.

For example, let’s look at the main module : VMware.VimAutomation.Core.

C:\> Get-Module -Name VMware.VimAutomation.Core |
Format-List Name,ModuleType,Path

Name       : VMware.VimAutomation.Core
ModuleType : Script
Path       : C:\Program Files (x86)\VMware\Infrastructure\vSphere
             PowerCLI\Modules\VMware.VimAutomation.Core\VMware.VimAutomation.Core.ps1

This is telling us that VMware.VimAutomation.Core is just a script module.
But looking at the content of the script VMware.VimAutomation.Core.ps1, we see that its main purpose is to load the necessary dlls and the good old snapin :

$dllToLoad |%{    
    $dllPath = [System.IO.Path]::Combine($coreAssembliesPath, $_)
    # Load DLL
    [Void] [Reflection.Assembly]::LoadFile($dllPath)
}

$snapinName = "VMware.VimAutomation.Core"
if (!(Get-PSSnapin $snapinName -ErrorAction Ignore)) {	  
		Add-PSSnapin $snapinName		
}

And the snapin itself is a dll.
Here is how to list all the .NET assemblies PowerCLI is made of (output truncated for brevity):

C:\> $PowerCliPath = 'C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI'
C:\> $PowerCliDlls = Get-ChildItem -Path $PowerCliPath -Recurse -Filter "*.dll"
C:\> $PowerCliDlls.FullName

C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\CryptoSupport.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\ICSharpCode.SharpZipLib.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Interop.Shell32.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\msvcr90.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Binding.Ls2.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.Sdk.Impl.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.Sdk.Interop.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.Sdk.Types.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.Sdk.Util10.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.Sdk.Util10Ps.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.ViCore.Cmdlets.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.ViCore.Impl.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.ViCore.Interop.dll
C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.ViCore.Types.dll

C:\> $PowerCliDlls.Count
56

There are 56 of them.

How many of them are currently loaded in our PowerShell session ?

C:\> $LoadedAssemblies = [AppDomain]::CurrentDomain.GetAssemblies()
C:\> $CliLoadedAssemblies = $LoadedAssemblies | Where-Object Location -Like "*PowerCLI*"
C:\> $CliLoadedAssemblies.Count
46

We normally never need to load these assemblies manually but, if we really want to, here is how we would load the assembly VMware.Vim.dll :

C:\> [Reflection.Assembly]::LoadFrom("$PowerCliPath\VMware.Vim.dll")

GAC    Version        Location
---    -------        --------
False  v4.0.30319     C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll

Now, let’s look into the types exposed by these PowerCLI assemblies :

C:\> $CliLoadedAssemblies.ExportedTypes | more

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    ICredentialStore
True     False    CredentialStoreFactory                   System.Object
True     False    DistinguishedName                        System.Object
True     False    DnKeyListSdk                             System.Object
True     False    LocalizableMessage                       System.Object
True     False    VimException                             System.ApplicationException
True     False    ViError                                  VMware.VimAutomation.Sdk.Types.V1.ErrorHandlin...
True     False    MethodFault                              VMware.VimAutomation.Sdk.Types.V1.ErrorHandlin...
True     False    ObnRecordProcessingFailedException       VMware.VimAutomation.Sdk.Types.V1.ErrorHandlin...
True     False    ServerObnFailureException                VMware.VimAutomation.Sdk.Types.V1.ErrorHandlin...
True     True     ErrorCategory                            System.Enum
True     True     VimExceptionSeverity                     System.Enum
True     False    ViServerConnectionException              VMware.VimAutomation.Sdk.Types.V1.ErrorHandlin...
True     False    NamedObject
True     False    Range                                    System.Object
True     False    SnapinVersion
True     False    VIObjectCore
True     False    VIObject
True     False    Task
True     True     TaskState                                System.Enum

We use the more command, otherwise the output would go on and on, for thousands of lines.
There are thousands of types, so let’s break down the number of types by assembly to have an idea of which assemblies are exposing the most types :

C:\> $CliLoadedAssemblies |
>> Select-Object -Property @{Label='Module';Expression={ $_.Modules }}, @{Label='TypesCount';Expression={ ($_.ExportedTypes).Count }} |
>> Sort-Object -Property TypesCount -Descending | Select-Object -First 15

Module                                    TypesCount
------                                    ----------
IntegritySoapService40.dll                      2986
SmsProxyService.dll                             2085
VMware.VimAutomation.ViCore.Types.dll            976
VMware.VimAutomation.ViCore.Impl.dll             537
VMware.VimAutomation.ViCore.Cmdlets.dll          415
IntegritySoapService40.XmlSerializers.dll        380
VMware.VimAutomation.ViCore.Interop.dll          220
VMware.VimAutomation.VROps.Views.dll             159
SpbmProxyService.dll                             159
VMware.VimAutomation.VROps.Schema.dll            146
ICSharpCode.SharpZipLib.dll                      101
VMware.VumAutomation.Types.dll                    69
VMware.VimAutomation.Sdk.Util10.dll               54
VMware.Binding.Ls2.dll                            53
VMware.VimAutomation.Vds.Types.dll                52

VMware.VimAutomation.ViCore.Types.dll looks interesting, we can check if it contains the type of some objects we use on a daily basis, like datastore and VMHost :

C:\> ($CliLoadedAssemblies | Where-Object Location -Like "*.ViCore.Types.dll").ExportedTypes |
>> Where-Object { $_.Name -eq 'Datastore' -or $_.Name -eq 'VMHost' } |
>> Format-List -Property 'Name', 'Attributes'

Name       : Datastore
Attributes : AutoLayout, AnsiClass, Class, Public, ClassSemanticsMask, Abstract

Name       : VMHost
Attributes : AutoLayout, AnsiClass, Class, Public, ClassSemanticsMask, Abstract

Indeed, they are here.
By the way, there is better way to find which assembly is providing a given type :

C:\> $DatastoreType = (Get-Datastore -Name 'ISCSI-1').GetType()
C:\> ([reflection.assembly]::GetAssembly($DatastoreType)).Location

C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.VimAutomation.ViCore.Impl.dll

We had seen earlier that the [Datastore] type was defined in VMware.VimAutomation.ViCore.Types.dll, and now we are told that it is in VMware.VimAutomation.ViCore.Impl.dll. What is going on ?

C:\> (Get-Datastore -Name "ISCSI-1").GetType() | Select-Object -Property FullName

FullName
--------
VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.VmfsDatastoreImpl

Aha, Get-Datastore is returning objects of the type [VmfsDatastoreImpl], not [Datastore].

We can check if this assembly defines other datastore-related types, like so :

C:\> ($CliLoadedAssemblies | Where-Object Location -Like "*.ViCore.Impl.dll" }).ExportedTypes |
>> Where-Object { $_.Name -like "*datastore*" -and $_.BaseType } |
>> Select-Object -Property 'Name', 'BaseType'

Name                    BaseType
----                    --------
DatastoreItemImpl       VMware.VimAutomation.ViCore.Util10.VersionedObjectImpl
DatastoreFolderImpl     VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreItemImpl
DatastoreRootFolderImpl VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreFolderImpl
DatastoreImpl           VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.StorageResourceImpl
NasDatastoreImpl        VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl
VmfsDatastoreImpl       VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl
DatastoreFileImpl       VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreItemImpl
DatastoreVMDiskFileImpl VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreFileImpl
DatastoreServiceImpl    System.Object

Yes, it does.
We can actually see that it defines one type for VMFS datastores (VmfsDatastoreImpl) and one type for NFS datastores (NasDatastoreImpl), both of which are child types (derived classes in C# parlance) of the type DatastoreImpl.

Also, as we can see below, the [Datastore] type is an abstract class :

C:\> 'Datastore' -as [type] | Select-Object -Property 'Name', 'Attributes'

Name                                            Attributes
----                                            ----------
Datastore AutoLayout, AnsiClass, Class, Public, Abstract

What is an abstract class ?

Basically, we cannot create instances of the class (objects) when the class is abstract.
Generally abstract classes are used as a generic template for derived classes. Then, objects are created from a derived concrete class.
Concrete means that we can create instances of it.

So we can assume that VMware.VimAutomation.ViCore.Types.dll is providing base classes for use by other PowerCLI assemblies, to create more specific classes from which we can create objects.

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...