Category Archives: Powershell

Passing Boolean values to Powershell modules

Often times we need to pass a Boolean value to a Powershell provider, and a perfect example is for the purpose of a “debug” flag.

In my experience, Powershell probe and write action modules always type cast the script input parameter as String, whether the configuration element is of type Boolean or String. This means the default value in your workflow could be true, false, 1, or 0, and it will always equal true if you are handling this input parameter as Boolean in the script.

Obviously, this will cause some unexpected behaviors, and most likely will be viewed as a bug in the management pack.

The way I work around this issue (at least until this is fixed in the product) is NOT typing the script parameter, and then converting the variable to Boolean just after the param block like this:

param($debugFlag)
$debugFlag = [System.Convert]::ToBoolean($debugFlag)

By handling a Boolean input parameter like this in the script, we can effectively use the Boolean type in module configuration; the default value in the monitoring workflow can be true or false, the value will be handled appropriately by the script, the operator will see the default value as it should appear in console, and the operator will be presented with a meaningful (True|False) selector in the override interface.

UPDATE (09/02/2015) – This problem applies to Boolean, Integer, and Double values!

After writing this post, I wanted to get down to the bottom of the problem, so I poked around the Windows Library and what I found made it clear.

Taking a look at the implementation of any Powershell probe module, you will notice the Parameters element type is NamedParametersType, and this is defined in the Microsoft.Windows.PowerShellSchema. Notice the name-value pair are of type ID and string, respectively. This is the reason any type of value will be cast as String in a Powershell module.

<SchemaType ID="Microsoft.Windows.PowerShellSchema" Accessibility="Public"> 
<xsd:complexType name="NamedParametersType">
<xsd:sequence>
<xsd:element name="Parameter" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:ID" />
<xsd:element name="Value" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="SnapInsType">
<xsd:sequence>
<xsd:element name="SnapIn" minOccurs="0" maxOccurs="unbounded" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="NonNullString">
<xsd:restriction base="xsd:string">
<xsd:minLength value="1" />
</xsd:restriction>
</xsd:simpleType>
</SchemaType>

It seems to me, the way to resolve this is to update the library with a choice for value type. This would allow the developer the option to type cast, and would remove the assumption that type casting is occurring when it is not. Since this schema exists in the Microsoft Windows Library, it would make the most sense for Microsoft to fix this.

Operations Shell–Using different credentials

Some companies setup their user accounts and then provide an administrator account, and maybe only the administrator account is a member of the Operations Manager Administrator user role. The Operations Console provides a login screen, so it’s not a problem authenticating to the management group. But the Operations Shell does not provide a login option – it will automatically attempt to login using the context of the current user.

This results in an access denied message:

New-SCOMManagementGroupConnection : The user does not have sufficient permission to perform the operation.

 

One way to get around this is to use the Powershell Get-Credential cmdlet. Add this to the beginning of administrative scripts or start your console sessions with:

 

$Credentials = Get-Credential –UserName [domain\username] -Message "Enter password"

$MS = [your management server name]

New-SCOMManagementGroupConnection -ComputerName $MS -Credential $Credentials

 

Smile

Find base class, hosting class, and all properties using powershell

A few years ago, I wrote a powershell script that returns the entire base and host class path for a given class, including all available properties on each of the classes. This can be useful in a few different scenarios, including management pack development.

I haven’t used the script in a while, but the other day ran into a situation where it was quite handy. I had to update it to work with SCOM 2012, however, so I thought I would post the updated script here for future reference.

You can find the SCOM 2007 version here.

 

##This script accepts a class name, and returns the entire
##Base class path.  It also returns Host Class for each
##Base class returned.  You'll see the entire
##class path for the given class.
##Author: Jonathan Almquist, Scomskills
##version 2.0 (for SCOM 2012)
##Original: 11-01-2008
##Updated: 07-07-2014

##Usage = getClassPath.ps1 <class_system_name>
##Example = getClassPath.ps1 Microsoft.Windows.Computer

param($classname)
$ast = "-"
$class = get-scomclass | where {$_.name -eq $classname}
Write-Host ($ast * 50)
Write-Host "TARGET CLASS" $class
Write-Host ($ast * 50)`n
while ($class -ne "False")
    {
    $property = $class | foreach-object {$_.getProperties()} | Select-Object name
    foreach ($value in $property)
        {
        if ($value.name -ne $null)
            {
            write-host `t`t`t`t $value.name
            }
            else
            {
            Write-Host `t`t`t`t "No properties"
            }
        }
    write-host `n
    Write-Host ($ast * 50)
    Write-Host "BASE CLASS PATH for" $class
    Write-Host ($ast * 50)`n
    $baseclass = get-scomclass | where {$_.id -eq $class.base.id.tostring()}
    While ($baseclass.base.id -ne $NULL)
        {
        $baseclass.name
        $property = $baseclass | foreach-object {$_.getProperties()} | Select-Object name
        foreach ($value in $property)
            {
            write-host `t`t`t`t $value.name
            }
        $baseclass = get-scomclass | where {$_.id -eq $baseclass.base.id.tostring()}
        }
    if ($class.hosted -eq "True")
        {
        $hostclass = get-scomclass | where {$_.name -eq $class.Name} | ForEach-Object {$_.findHostClass()}
        write-host `n
        Write-Host ($ast * 50)
        Write-Host "HOST CLASS for" $class
        Write-Host ($ast * 50)`n
        $class = get-scomclass | where {$_.name -eq $class.Name} | ForEach-Object {$_.findHostClass()}
        Write-Host $class
        }
        else
        {
        write-host `t`t "*Not Hosted*" `n`n
        $class = "False"
        }
    }

 

🙂

Automate management packs using powershell

I’ve been asked on a few occasions to automate management packs. Unfortunately, there isn’t much information about how to do to do this using Powershell in the MSDN development kit. I am providing a couple Powershell functions you can add to your automation process that will generate a new management pack.

Just update the output directory, pack name, pack display name, and version in the highlighted lines.

 

function CreateNewPack ($id, $name, $version) {
    $mpStore = New-Object Microsoft.EnterpriseManagement.Configuration.IO.ManagementPackFileStore
    $managementPack = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPack($id, $name, (New-Object Version(1,0,0,$version)), $mpStore)
    $managementPack.DefaultLanguageCode = 'ENU'
    $managementPack.DisplayName = $name
    $managementPack.Description = $name + ' management pack was auto-generated'
    $managementPack
}
function WriteManagementPack ($directory, $mp) {
    $mpWriter = new-object Microsoft.EnterpriseManagement.Configuration.IO.ManagementPackXmlWriter($directory)
    $mpWriter.WriteManagementPack($mp) | Out-Null
}
$directory = 'c:\My Pack'
$mp = CreateNewPack 'MyNewPack' 'My New Pack' 1
$mp.AcceptChanges()
WriteManagementPack $directory $mp

Contact SCOMskills if you are interested in learning more about management pack automation, at automation@scomskills.com.

 

🙂

Output list of scripts contained in a management pack

I was perusing my library of powershell scripts today and stumbled across this neat little gem. I do not recall writing it, so probably cannot take the credit. But I wanted to post it here in case anyone else can make use of it.

If the original author is here, please raise your hand!

$xml = New-Object “System.Xml.XmlDocument”
$xml.Load(“path to management pack xml”)
$scripts = $xml.SelectNodes(“descendant::ScriptName”)
$scripts | group “#text” | select name | sort name