PowerShell and WMI just seem to go together like peanut butter and jelly, beer and pretzels, or salt and pepper. However, discovering things about WMI isn't always so easy. There are plenty of tools and scripts that will help you uncover WMI goodness, but here's another one anyway. Today's PowerShell function will get all namespaces on a computer.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The default namespace for Get-WMIObject is Root\CimV2. But there are many other useful namespaces and classes that you can leverage in PowerShell. My function, Get-WMINamespace, will list either the top level namespaces or recursively search and return all namespaces. Here's the main function code.
[cc lang="PowerShell"]
Function Get-WMINamespace {
[cmdletBinding()]
Param(
[Parameter(Position=0,Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullorEmpty()]
[Alias("name")]
[string]$Computername=$env:computername,
[object]$Credential,
[switch]$Recurse
)
Begin {
Write-Verbose -Message "$(Get-Date) Starting $($myinvocation.mycommand)"
#convert credential to a PSCredential if a string was passed.
if ( $Credential -is [system.management.automation.psCredential]) {
Write-Verbose "$(Get-Date) Using PSCredential for $($credential.username)"
}
ElseIf ($Credential) {
Write-Verbose "$(Get-Date) Getting PSCredential for $credential"
$Credential=Get-Credential $credential
}
} #close Begin
Process {
#create a command string. PacketPrivacy is required for some namespaces
#like MicrosoftTPM
$cmd="Get-WMIObject -computername $computername -Namespace 'Root' -class '__Namespace' -authentication 'PacketPrivacy' -errorAction 'Stop'"
if ($recurse) {
$cmd+=" -List -Recurse"
}
if ($Credential) {
$cmd+=" -credential `$Credential"
}
Try
{
Write-Verbose -Message "$(Get-Date) $cmd"
$data=Invoke-Expression $cmd
}
Catch
{
Write-Warning "Failed to retrieve namespace information from $Computername"
Write-Error $_
}
if ($data)
{
Write-Verbose "$(Get-Date) Processing $(($data | measure-object).count) items"
if ($Recurse) {
#format the data to accomodate nested namespaces
$data | Sort __NAMESPACE | Select @{Name="Computername";Expression={$_.__SERVER}},
@{Name="Namespace";Expression={$_.__NAMESPACE}},
@{Name="Name";Expression={Split-Path $_.__Namespace -Leaf }}
}
else {
$data | Sort __NAMESPACE | Select @{Name="Computername";Expression={$_.__SERVER}},
@{Name="Namespace";Expression={Join-path -Path $_.__NAMESPACE -ChildPath $_.Name }},Name
}
}
} #close process
End {
Write-Verbose -Message "$(Get-Date) Ending $($myinvocation.mycommand)"
} #close End
} #end Function
[/cc]
The function only needs a few parameters. It defaults to the localhost but you can use -Computername to specify a different computer. For remote computers you can also specify either a saved PSCredential object or a user name to be used with Get-Credential.
[cc lang="PowerShell"]
#convert credential to a PSCredential if a string was passed.
if ( $Credential -is [system.management.automation.psCredential]) {
Write-Verbose "$(Get-Date) Using PSCredential for $($credential.username)"
}
ElseIf ($Credential) {
Write-Verbose "$(Get-Date) Getting PSCredential for $credential"
$Credential=Get-Credential $credential
}
[/cc]
The function will only return top level namespaces, unless you use -Recurse. Because there are several ways to call Get-WMIObject based on my function parameters, I dynamically build a command string. The function starts out with the core expression.
[cc lang="PowerShell"]
#create a command string. PacketPrivacy is required for some namespaces
#like MicrosoftTPM
$cmd="Get-WMIObject -computername $computername -Namespace 'Root' -class '__Namespace' -authentication 'PacketPrivacy' -errorAction 'Stop'"
[/cc]
If I'm recursing, then I append the necessary parameters.
[cc lang="PowerShell"]
if ($recurse) {
$cmd+=" -List -Recurse"
}
[/cc]
Finally, if a credential is passed, that too is added to the command string.
[cc lang="PowerShell"]
if ($Credential) {
$cmd+=" -credential `$Credential"
}
[/cc]
The tricky part that eluded me for a bit was to escape the $ in $Credential so that the final command string would include the right variable name. Once the command string is complete, I run it with Invoke-Expression.
[cc lang="PowerShell"]
Try
{
Write-Verbose -Message "$(Get-Date) $cmd"
$data=Invoke-Expression $cmd
}
[/cc]
Assuming data is returned, all that's left is to format the data. I need to make adjustments depending on whether the function searched recursively or not. Notice my use of the Path cmdlets to split or join the Namespace path.
[cc lang="Powershell"]
if ($Recurse) {
#format the data to accomodate nested namespaces
$data | Sort __NAMESPACE | Select @{Name="Computername";Expression={$_.__SERVER}},
@{Name="Namespace";Expression={$_.__NAMESPACE}},
@{Name="Name";Expression={Split-Path $_.__Namespace -Leaf }}
}
else {
$data | Sort __NAMESPACE | Select @{Name="Computername";Expression={$_.__SERVER}},
@{Name="Namespace";Expression={Join-path -Path $_.__NAMESPACE -ChildPath $_.Name }},Name
}
[/cc]
Once the function is loaded into your session you can run it like this.
[cc lang="DOS"]
PS C:\> Get-WMINamespace
Computername Namespace Name
------------ --------- ----
SERENITY ROOT\Policy Policy
SERENITY ROOT\Interop Interop
SERENITY ROOT\WMI WMI
SERENITY ROOT\directory directory
SERENITY ROOT\Microsoft Microsoft
SERENITY ROOT\aspnet aspnet
SERENITY ROOT\ServiceModel ServiceModel
SERENITY ROOT\SecurityCenter SecurityCenter
SERENITY ROOT\RSOP RSOP
SERENITY ROOT\CIMV2 CIMV2
SERENITY ROOT\Cli Cli
SERENITY ROOT\subscription subscription
SERENITY ROOT\DEFAULT DEFAULT
SERENITY ROOT\snmp snmp
SERENITY ROOT\SecurityCenter2 SecurityCenter2
SERENITY ROOT\nap nap
SERENITY ROOT\SECURITY SECURITY
PS C:\> Get-WMINamespace -computername "JDHIT-DC01" -cred $jdhit -recurse | Select Namespace
Namespace
---------
ROOT
ROOT\aspnet
ROOT\CIMV2
ROOT\CIMV2\Applications
ROOT\CIMV2\Applications\MicrosoftIE
ROOT\Cli
ROOT\DEFAULT
ROOT\directory
ROOT\directory\LDAP
ROOT\Microsoft
ROOT\Microsoft\HomeNet
ROOT\MicrosoftActiveDirectory
ROOT\MicrosoftDNS
ROOT\MicrosoftIISv2
ROOT\MicrosoftNLB
ROOT\MSCluster
ROOT\perfmon
ROOT\Policy
ROOT\RSOP
ROOT\RSOP\Computer
ROOT\RSOP\User
ROOT\RSOP\User\S_1_5_21_805063240_3875113082_2769008284_500
ROOT\SECURITY
ROOT\ServiceModel
ROOT\snmp
ROOT\snmp\localhost
ROOT\subscription
ROOT\WMI
[/cc]
Enjoy!!
Download Get-WMINamespace-v2.