Monthly Archive

Categories

PowerShell and WMI

WMI classes and Storage cmdlets

There is a hierarchy of objects to work through when dealing with disks

First you have the physical disk

PS>  Get-CimInstance -ClassName Win32_DiskDrive | fl

Partitions : 5
DeviceID   : \\.\PHYSICALDRIVE0
Model      : HFS256G3AMNB-2200A
Size       : 256052966400
Caption    : HFS256G3AMNB-2200A

 

A physical disk can have 1 or more partitions:

PS>  Get-CimInstance -ClassName Win32_DiskPartition | fl

NumberOfBlocks   : 716800
BootPartition    : False
Name             : Disk #0, Partition #0
PrimaryPartition : False
Size             : 367001600
Index            : 0

 

NumberOfBlocks   : 409600
BootPartition    : True
Name             : Disk #0, Partition #1
PrimaryPartition : True
Size             : 209715200
Index            : 1

 

NumberOfBlocks   : 485312512
BootPartition    : False
Name             : Disk #0, Partition #2
PrimaryPartition : True
Size             : 248480006144
Index            : 2

 

NumberOfBlocks   : 921600
BootPartition    : False
Name             : Disk #0, Partition #3
PrimaryPartition : False
Size             : 471859200
Index            : 3

 

NumberOfBlocks   : 12492800
BootPartition    : False
Name             : Disk #0, Partition #4
PrimaryPartition : False
Size             : 6396313600
Index            : 4

 

next step down is logical disks

PS>  Get-CimInstance -ClassName Win32_LogicalDisk | fl

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 108900372480
Size         : 248480002048
VolumeName   : Windows

 

The classes Win32_DiskDriveToDiskPartition and Win32_LogicalDiskToPartition  link physical disks to partitions and partitions to logical disks respectively.

 

Then you’ve got volumes – which is where you actually work with disks for the most part

PS>  Get-CimInstance -ClassName Win32_Volume | fl Caption, Label

Caption : C:\
Label   : Windows

 

Caption : \\?\Volume{524b798f-a072-4ecc-8cfe-fb823e10a5e7}\
Label   : Windows RE tools

 

Caption : \\?\Volume{4ea44e2e-dd30-4cd9-bfd1-c991be836d97}\
Label   :

 

Caption : \\?\Volume{c671d23c-f5e5-473d-b6c4-fecb4a99e5b3}\
Label   : Recovery image

 

The Storage module introduced with Windows 8 has cmdlets for some of these tasks:

PS>  Get-PhysicalDisk | fl FriendlyName, SerialNumber, CanPool, OperationalStatus, HealthStatus, Usage
, Size

FriendlyName      : HFS256G3AMNB-2200A
SerialNumber      : EI3AN118813AM3740
CanPool           : False
OperationalStatus : OK
HealthStatus      : Healthy
Usage             : Auto-Select
Size              : 256060514304

 

Partitions:

PS>  Get-Partition | fl PartitionNumber, DriveLetter, Offset, Size, Type

PartitionNumber : 1
DriveLetter     :
Offset          : 1048576
Size            : 367001600
Type            : Recovery

 

PartitionNumber : 2
DriveLetter     :
Offset          : 368050176
Size            : 209715200
Type            : System

 

PartitionNumber : 3
DriveLetter     :
Offset          : 577765376
Size            : 134217728
Type            : Reserved

 

PartitionNumber : 4
DriveLetter     : C
Offset          : 711983104
Size            : 248480006144
Type            : Basic

 

PartitionNumber : 5
DriveLetter     :
Offset          : 249191989248
Size            : 471859200
Type            : Recovery

 

PartitionNumber : 6
DriveLetter     :
Offset          : 249663848448
Size            : 6396313600
Type            : Recovery

 

Get-Disk returns similar, but not identical, information to Get-PhysicalDisk

 

The Get-Disk cmdlet gets one or more Disk objects visible to the operating system, or optionally a filtered list.

The Get-Disk cmdlet gets one or more Disk objects visible to the operating system, or optionally a filtered list.

 

There isn’t a cmdlet to get logical disks

 

For volumes:

PS>  Get-Volume | fl DriveLetter, FileSystemLabel, FileSystem, DriveType, HealthStatus, OperationalSta
tus, SizeRemaining, Size

DriveLetter       : C
FileSystemLabel   : Windows
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 108473528320
Size              : 248480002048

 

DriveLetter       :
FileSystemLabel   :
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 122884096
Size              : 471855104

 

DriveLetter       :
FileSystemLabel   : Windows RE tools
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 61980672
Size              : 366997504

 

DriveLetter       :
FileSystemLabel   : Recovery image
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 476807168
Size              : 6396309504

 

As you can see from this quick comparison the same sorts of information is available from the storage cmdlets and WMI. In fact under the hood the storage cmdlets are using WMI – but a set of new classes defined in ROOT/Microsoft/Windows/Storage

WMI Filters

A common mistake with WMI/CIM filters is:

PS>  Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=C:"
Get-WmiObject : Invalid query "select * from Win32_LogicalDisk where DeviceId=C:"
At line:1 char:1
+ Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=C:"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCo
   mmand

 

The clue is in the invalid query error message

When you use the –Filter parameter and are testing a property of type string the value you are testing against has to be in quotes

PS>  Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId='C:'"

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 108999528448
Size         : 248480002048
VolumeName   : Windows

 

The filter is defined as a string so you need to use single quotes inside the double quotes. You could mess around with all single quotes but then you have to escape the inner set of quotes – good luck with that – its an unnecessary exercise in frustration

 

How do you know the property is a string?

PS>  (Get-CimClass -ClassName Win32_LogicalDisk).CimClassProperties['DeviceId']

Name               : DeviceID
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {CIM_Key, read, key, MappingStrings...}
ReferenceClassName :

 

The same rules for –Filter apply to Get-CimInstance

Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceId='C:'"

Cim session oddity

The CIM cmdlets were introduced with PowerShell 3.0.  You can use the –ComputerName parameter to access a remote machine or, if you need to run multiple commands to the remote machine, you can create a CIM session.

 

CIM sessions are analogous to PowerShell remoting sessions and use WSMAN by default to connect to the remote machine:

PS> $c12 = New-CimSession -ComputerName W12R2SUS

PS> Get-CimInstance -CimSession $c12 -ClassName Win32_OperatingSystem | fl

SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 9600
RegisteredUser  : Windows User
SerialNumber    : 00252-00107-57895-AA282
Version         : 6.3.9600
PSComputerName  : W12R2SUS

 

In this case I’m accessing a Windows 2012 R2 system

 

If you try to create a CIM session to a machine running PowerShell 2.0 it will appear to work but you’ll get an error when you try to access the session:

PS> $c8 = New-CimSession -ComputerName W8R2STD01
PS> Get-CimInstance -CimSession $c8 -ClassName Win32_OperatingSystem | fl
Get-CimInstance : The WS-Management service cannot process the request. A DMTF resource URI was used to access a non-DMTF class. Try again using a non-DMTF resource URI.
At line:1 char:1
+ Get-CimInstance -CimSession $c8 -ClassName Win32_OperatingSystem | fl
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (root\cimv2:Win32_OperatingSystem:String) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80338139,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : W8R2STD01

 

The reason is that the version of WSMAN installed with with PowerShell 2.0 (WSMAN 2.0) isn’t compatible with CIM sessions which expect WSMAN 3.0

 

One option is to use a DCOM based session:

PS> $opt = New-CimSessionOption -Protocol Dcom
PS> $c8D = New-CimSession -ComputerName W8R2STD01 -SessionOption $opt
PS> Get-CimInstance -CimSession $c8D -ClassName Win32_OperatingSystem | fl

SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 7601
RegisteredUser  : Windows User
SerialNumber    : 00477-179-0000007-84050
Version         : 6.1.7601
PSComputerName  : W8R2STD01

 

PowerShell MVP Jeff Hicks discovered that if you use a filter parameter with Get-CimInstance you can access PowerShell 2.0 machines using a WSMAN based CIM session

PS> Get-CimInstance -CimSession $c8 -ClassName Win32_OperatingSystem -Filter "Caption LIKE '%'"  | fl

SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 7601
RegisteredUser  : Windows User
SerialNumber    : 00477-179-0000007-84050
Version         : 6.1.7601
PSComputerName  : W8R2STD01

 

In this case you’re filtering on the Caption being like any characters

 

I stood in for a speaker who was ill at the recent European PowerShell conference and part of the session was on using CIM sessions. This issue came up and I decided to investigate a bit closer

Without a filter:

PS> Get-CimInstance -CimSession $c8 -ClassName Win32_OperatingSystem -Verbose
VERBOSE: Perform operation 'Enumerate CimInstances' with following parameters, ''namespaceName' =
root\cimv2,'className' = Win32_OperatingSystem'.
Get-CimInstance : The WS-Management service cannot process the request. A DMTF resource URI was used to access a
non-DMTF class. Try again using a non-DMTF resource URI.
At line:1 char:1
+ Get-CimInstance -CimSession $c8 -ClassName Win32_OperatingSystem -Ver ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (root\cimv2:Win32_OperatingSystem:String) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80338139,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : W8R2STD01

VERBOSE: Operation 'Enumerate CimInstances' complete.

 

An attempt is made to enumerate the instances of the Win32_OperatingSystem class

 

If you use a filter

PS> Get-CimInstance -CimSession $c8 -ClassName Win32_OperatingSystem -Filter "Caption LIKE '%'"  -Verbose | fl
VERBOSE: Perform operation 'Query CimInstances' with following parameters, ''queryExpression' = SELECT * FROM
Win32_OperatingSystem WHERE Caption LIKE '%','queryDialect' = WQL,'namespaceName' = root\cimv2'.

SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 7601
RegisteredUser  : Windows User
SerialNumber    : 00477-179-0000007-84050
Version         : 6.1.7601
PSComputerName  : W8R2STD01

VERBOSE: Operation 'Query CimInstances' complete.

 

You’re sending a WQL  query to the remote machine.

 

My current theory is that Get-CimInstance is trying to enumerate the instances of a particular class (in a similar way to Get-WSmnaInstance does) and that fails due to the WSMAN version mismatch.  Using the Filter bypasses the enumeration allowing it to work.

 

This is a totally undocumented feature and there is no guarantee it will continue to work in future versions. Until PowerShell 2.0 is gone from you environment be aware that its an option but be careful

Folder creation dates from WMI

A question on the powershell.org about finding the creation date of folders raises some interesting points

 

To find a folder’s creation date use:

Get-WmiObject -Class Win32_Directory -Filter "Drive='C:' AND Path = '\\users\\$user\\'" | select Name, @{N='Creation date'; E={$_.ConvertToDateTime($_.CreationDate)}}

 

OR

 

Get-CimInstance -ClassName Win32_Directory -Filter "Drive='C:' AND Path = '\\users\\$user\\'" | select Name, CreationDate

 

If you use Get-WmiObject the date is returned in the form

20160128110039.938756+000

 

Which is why you need to perform the conversion using the ConvetToDateTime method that PowerShell adds to every WMI object.

 

Get-CimInstance automatically performs the conversion for you.

 

The other interesting part is the filter

"Drive='C:' AND Path = '\\users\\$user\\'"

 

Note that it’s wrapped in double quotes. Each of the values is a string so HAS to be in single quotes. Also note that you need to double the \ characters as WMI treats a single \ as an escape character so you have to escape the escape character.

Monitor Info

A question on the forum about combining information from 2 CIM classes produced this:

 

function Get-MonitorInfo {
    [CmdletBinding()]
    param(
        $computername = $env:COMPUTERNAME
    )

    $cs = New-CimSession -ComputerName $computername
   
    $monitors =  Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorId -Filter "Active = '$true'" -CimSession $cs
   
    foreach ($monitor in $monitors) {
       
        $in = ($monitor.InstanceName).Replace('\', '\\')
        Write-Verbose -Message $in
        $dp = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams -Filter "InstanceName = '$in'" -CimSession $cs
       
        $name = ''

        foreach ($c in $monitor.UserFriendlyName){
            if ($c -ne '00'){$name += [char]$c}
        }

        $type = 'Unknown'
        switch ($dp.VideoInputType){
            0 {$type = 'Analog'}
            1 {$type = 'Digital'}
        }
       
        New-Object -TypeName PSObject -Property @{
            Name = $name
            Type = $type
        }
    }
   
    Remove-CimSession -CimSession $cs
}

 

Create a CIM session to the computer. Get the instances of the WmiMonitorId class. Iterate through them and find the matching WmiMonitorBasicDisplayParams class instance.

 

The InstanceName of the monitor will look like this:

DISPLAY\GSM598F\4&19086f00&0&UID200195_0

you need to replace \ by \\ to use the value in a CIM query because \ is treated as the escape character and you have to escape it to use it

 

Translate the UserFriendly name by converting the byte array to a string and determine the VideoInputType using the switch.

 

Create an object and output

IIS information

In my recent post about getting server information from a IIS web server I said I post about getting similar information from later machines.

 

You still have the root\MirosoftIISv2 namespace available if you install the IIS 6.0 tools but one question to keep in mind – how long will they continue to be available?

 

Your alternative is the root\webadministration names space. You can use the Site class to get the relevant information

 

$serverdata = @()
Get-CimInstance -Namespace root\webadministration -ClassName Site -ComputerName $env:COMPUTERNAME |
foreach {

$serverdata += New-Object -TypeName PSObject -Property @{
Port = [string]::Join(',', ($_.Bindings | select -ExpandProperty BindingInformation))
SiteName = $_.Name
SiteId = $_.id
PSComputerName = $_.PSComputerName
Status = Invoke-CimMethod -InputObject $_ -MethodName GetState | select -ExpandProperty ReturnValue
}

}
$serverdata

 

Remember that COM objects are inert so you can’t call the method directly on the object. otherwise the info is about the same

IIS 6.0 server information

A question of the forum asked about getting data from IIS 6.0 servers

 

One of the ways to access this data is to use CIM (WMI). IIS 6.0 has the root\MicrosoftIIsV2  namespace. Later versions of Windows server also have a root\webadministration namespace which is preferred.

 

The original question asked about IIS 6.0 – I’ll show the same functionality using the later namespace in the next post

 

This based on the original code in the question and isn’t necessarily how I would do it from scratch

$file = Get-Content "C:\Temp\PowerShellScripts\IISQuery\servers.txt"
$OutputDir = "C:\Temp\PowerShellScripts\IISQuery\Output"
$OutputFile = Join-Path $OutputDir "IIStest.csv"
$serverdata = @()

foreach ($computername in $file)
{
$IISWebServer = Get-WmiObject -Namespace root\MicrosoftIIsV2 -Class IISWEbServer -ComputerName $computername -Authentication 6
foreach ($webserver in $IISWebServer) {

$IISWebServerSet = Get-WmiObject -Namespace root\MicrosoftIISv2 -Class IISWebServerSetting -ComputerName $computername -Filter "Name='$($webserver.Name)'"  -Authentication 6

$serverdata += New-Object -TypeName PSObject -Property @{
PScomputername = $IISWebServerSet.PScomputername
ServerComment = $IISWebServerSet.ServerComment
SiteStatus = $webserver.ServerState
Bindings = [string]::join(';',($IISWebServerSet.ServerBindings | select -expand hostname))
Port = [string]::join(';',($IISWebServerSet.ServerBindings | select -expand Port))
SiteName = $IISWebServerSet.Name
}

} ## end of foreach ($webserver in $IISWebServer)

}  ## end of foreach ($computername in $file)
$serverdata | Export-Csv -Path $OutputFile –NoTypeInformation

 

Start by defining input and output files and an empty array

 

Loop through the servers and get the IISWebserver class instance. You’ll get one object per web site. Loop through the sites and get the IISWebServerSetting class for that site (using –Filter).

 

Create and output object and add to the array

Export the array to a csv file

 

There are a few improvements that could be made to this to make it more efficient that I’ll cover in a later post

Network adapter Index

A few years ago I wrote a post about setting the IP metric on a connection - https://richardspowershellblog.wordpress.com/2012/01/01/changing-ip-connection-metric/

 

I was recently asked if the Index’s associated with network adapters were consistent acros machines. The answer – unfortunately- is no they’re not as a rule.

 

I used the function from the original post

function Test-IPmetric {
    Get-WmiObject -Class Win32_NetworkAdapter -Filter "AdapterType = 'Ethernet 802.3'" |
    foreach {
        Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “Index=$($_.DeviceId)” |
        Select-Object Description, Index, IPEnabled, IPConnectionMetric
    }
}

to view the index

 

The Index property from Win32_NetworkAdapaterConfiguration is identical to the DeviceId from the Win32_NetworkAdapater class for a given network adapter.

 

if you try the function on a number of machines you’ll see that Index numbers assigned by Windows aren’t consistent.  My test VMs (Hyper-V) all seem to have the same index numbers assigned but I always create my VMs and add network adapters in the same way.

 

I wouldn’t rely on a particular index being assigned to a given network adapter – always pull the data and test

CDXML filter parameters

I was recently asked about adding a filter parameter to a cmdlet created through CDXML. If you’ve not seen it before (see PowerShell and WMI Chapters 18 & 19 from www.manning.com) CDXML allows you to creat ecmdlets by wrapping a WMI class in some simple XML.

 

The resultaing CDXML (Cmdlet Definition XML) is thn published as a module.  Here’s a simple example using the Win32_NetworkAdapterConfiguration class

<?xml version='1.0' encoding='utf-8'?>
<PowerShellMetadata xmlns='http://schemas.microsoft.com/cmdlets-over-objects/2009/11'>
  <Class ClassName='ROOT\cimv2\Win32_NetworkAdapterConfiguration'>
    <Version>1.0</Version>
    <DefaultNoun>NetworkAdapterConfiguration</DefaultNoun>
    <InstanceCmdlets>
      <GetCmdletParameters DefaultCmdletParameterSet='DefaultSet'>
      </GetCmdletParameters>
    </InstanceCmdlets> 
  </Class>
</PowerShellMetadata>

 

The first 2 lines are boilerplate. The NameSpace and WMI class are defined on line 3, follwoed by a version number (arbitary) and a default noun for you cmdlet to use.  Instance cmdlets defines how you’ll pull the data for existing instances of the class – in other words the Get-NetworkAdapterConfiguration cmdlet.

 

Save as a CDXML file and import as a module

Import-Module .\NetworkAdapterConfiguration.cdxml

 

Get-Module will sjow it as a Cim module with a single exported command.   Use it like any other cmdlet

PS> Get-NetworkAdapterConfiguration | ft -a

ServiceName  DHCPEnabled Index Description
-----------  ----------- ----- -----------
kdnic        True        0     Microsoft Kernel Debug Network Adapter
mwlu97w8     True        1     Marvell AVASTAR Wireless Composite Device
msu64w8      False       2     Surface Ethernet Adapter
mwlu97w8     True        3     Marvell AVASTAR 350N Wireless Network Controller
RFCOMM       False       4     Bluetooth Device (RFCOMM Protocol TDI)
BthPan       True        5     Bluetooth Device (Personal Area Network)
vwifimp      True        6     Microsoft Wi-Fi Direct Virtual Adapter
vwifimp      True        7     Microsoft Wi-Fi Direct Virtual Adapter
RasSstp      False       8     WAN Miniport (SSTP)
RasAgileVpn  False       9     WAN Miniport (IKEv2)
Rasl2tp      False       10    WAN Miniport (L2TP)
PptpMiniport False       11    WAN Miniport (PPTP)
RasPppoe     False       12    WAN Miniport (PPPOE)
NdisWan      False       13    WAN Miniport (IP)
NdisWan      False       14    WAN Miniport (IPv6)
NdisWan      False       15    WAN Miniport (Network Monitor)

 

Using the cmdlet is equivalent to

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration

 

but is easier and requires less typing.

Very often you’ll want to pick a specific adapter – for instance

 

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter 'Index=3'

 

You can implement the same kind of filters using CDXML. You add a queryable properties section as shown below:

<?xml version='1.0' encoding='utf-8'?>
<PowerShellMetadata xmlns='http://schemas.microsoft.com/cmdlets-over-objects/2009/11'>
  <Class ClassName='ROOT\cimv2\Win32_NetworkAdapterConfiguration'>
    <Version>1.0</Version>
    <DefaultNoun>NetworkAdapterConfiguration</DefaultNoun>
    <InstanceCmdlets>
      <GetCmdletParameters DefaultCmdletParameterSet='DefaultSet'>

        <QueryableProperties>
          <Property PropertyName='Index'>
            <Type PSType ='UInt32'/>
            <RegularQuery AllowGlobbing='true'>
              <CmdletParameterMetadata PSName='Index'  ValueFromPipelineByPropertyName='true' CmdletParameterSets='DefaultSet' />
            </RegularQuery>
          </Property>
        </QueryableProperties>       
             
      </GetCmdletParameters>
    </InstanceCmdlets> 
  </Class>
</PowerShellMetadata>

 

Set the paraemter name – same as property to use here – and the type (unsigned integer). Decide whether pipeline input and wildcards (globbing) are allowed and save the file.

 

Re-import the module (use the Force) and your new parameter is available

Get-NetworkAdapterConfiguration -Index 3

 

Its important to understand CDXMLMI – even if you never create a CDXML module – because 2/3 of the cmdlets in Windows Server 2012 and later are created this way.

WMI discovery

I’ve been working with System Center Configuration Manager this week. SCCM uses a lot of WMI. However, WMI discovery is still a bit of an art.

 

I needed to find the SMS_SCI_Component class.

 

If you know the namespace you can easily find the classes in that namespace but namespaces are hierarchical so you need to work down the tree.

The root namespace is at the top of the namespace tree so

C:\Scripts> Get-CimInstance -ClassName __NAMESPACE -Namespace root

Name
----
subscription
DEFAULT
SCCMDP
CIMV2
msdtc
Cli
nap
MicrosoftIISv2
SECURITY
CCMVDI
NetworkModel
RSOP
SMS
ccm
StandardCimv2
WMI
AccessLogging
directory
Policy
InventoryLogging
Interop
Hardware
ServiceModel
Microsoft
aspnet

 

After a bit of digging I found I needed the sms namespace

PS C:\Scripts> Get-CimInstance -ClassName __NAMESPACE -Namespace 'root\sms'

Name 
----    
site_PS1

 

which leads to:

Get-CimInstance -ClassName SMS_SCI_Component -Namespace 'root\sms\site_PS1'

 

What if you only know the class?

There’s a little trick using Get-WmiObject

Get-WmiObject -Namespace root -Recurse -List -Class SMS_SCI_Component

   NameSpace: ROOT\SMS\site_PS1

Name  
----      
SMS_SCI_Component      

 

The trick is to start with the root namespace and use the –Recurse (search through all child namespaces) and –List (just give class details) parameters.  You’ll see a listing by namespace for each instance of the class discovered.