0

We have moved our system alerting over to SCOM 2012 and receive heartbeat alerts when servers go offline. Presently there are approximately 750 servers in the vDC that I am managing. The SCOM 2012 server is in a different untrusted domain.

I have one working script where it puts the servers in Maintenance mode, but its run serially and takes about 40 minutes to put nearly 400 servers in Maintenance Mode. This is a workable solution, but I would like to use the foreach -parallel command to speed it up.

I have my workflow (to use the foreach -parallel command) created and placed in one of the default PowerShell Module locations on the Source and Destination Machines. I've tested the set of commands outside of the workflow on the SCOM server and it runs successfully. When I try to run the command remotely via an Invoke-command, the SCOM commands come back as being unrecognized.

#Get Date for usage in Connection Name
$Date = Get-Date -Format HHmmsss
#combine Name with Date to uniquify
$name = "ScomMM" + $Date

#Collect Servers from WSUS Server 
[reflection.assembly]::LoadWithPartialName("Microsoft.Updateservices.Administration") | out-null
$WSUS = [Microsoft.updateservices.administration.adminproxy]::Getupdateserver("ServerName",$false,8530);
$TS = $wsus.getcomputertargetgroups() | ? {($_.name -eq "Group1") -or ($_.Name -eq "Group2")}
$computers = $TS.getcomputertargets() | Select-Object FullDomainName

#Setup Trusted host 
invoke-Command -ScriptBlock {(winrm.cmd s winrm/config/client '@{TrustedHosts="*PublicIPAddress*"}')}
Enable-PSRemoting -Force
#Credentials stored in a file
$username = "username"
$password = get-content 'Path' | convertto-securestring
$creds = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $username,$password
$session = new-PSSession -ComputerName "IPAddress" -Credential $creds -Name $name

#SCOM Commands Module
Import-Module OperationsManager

#Workflow
Import-Module Set-MM

#Run the command remotely
Invoke-Command -Session $session -ScriptBlock {
    Import-Module -Name Set-MM
    Set-MM -computers $using:computers
}

#Workflow - Stored at C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Set-MM\Set-MM.psm1
Workflow Set-MM
{
    Param($computers)
    Foreach -Parallel($computer in $computers)
    {
        Get-SCOMClassInstance -Name $computers.FullDomainName | Start-SCOMMaintenanceMode -EndTime (Get-Date).AddMinutes(6) -Reason PlannedOperatingSystemReconfiguration
    }
}

At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Set-MM\Set-MM.psm1:6 char:3
+         Get-SCOMClassInstance -Name $computers.FullDomainName | Start ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cannot find the 'Get-SCOMClassInstance' command. If this command is defined as a workflow, ensure it is 
defined before the workflow that calls it. If it is a command intended to run directly within Windows 
PowerShell (or is not available on this system), place it in an InlineScript: 'InlineScript { 
Get-SCOMClassInstance }'
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : CommandNotFound
    + PSComputerName        : IPAddress

The term 'Set-MM' is not recognized as the name of a cmdlet, function, script file, or operable program. 
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    + CategoryInfo          : ObjectNotFound: (Set-MM:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    + PSComputerName        : IPAddress    

        Get-PSSession | Remove-PSSession

If I use an Inlinescript on the script inside the foreach -Parallel

InlineScript{Get-SCOMClassInstance -Name $Using:computers.FullDomainName | Start-SCOMMaintenanceMode -EndTime (Get-Date).AddMinutes(6) -Reason PlannedOperatingSystemReconfiguration}

I get this for each computer that is attempting to get processed in the workflow:

The term 'Get-SCOMClassInstance' is not recognized as the name of a cmdlet, function, script file, or 
operable program. Check the spelling of the name, or if a path was included, verify that the path is 
correct and try again.
    + CategoryInfo          : ObjectNotFound: (Get-SCOMClassInstance:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    + PSComputerName        : ServerName
  • Sounds like it is the SCOM module/plug-in that isn't being loaded in the remote PS sessions. I notice that you run `Import-Module Set-MM` _within_ the ScriptBlock but probably are hoping that the SCOM one will be there by default? I don't think you gain anything by loading the modules in the main script, i.e. locally. – Charlie Joynt Mar 03 '16 at 23:35
  • If I run like this, I still get the same result with the "Get-SCOMclassinstance not being recognized. Invoke-Command -Session $session -ScriptBlock { Import-Module OperationsManager Import-Module -Name Set-MM Set-MM -computers $using:computers } – Waffles Mar 04 '16 at 00:15
  • I'm guessing that didn't work? Not all cmdlets are Workflow-compatible, hence the advice to run then in an InlineScript. – Charlie Joynt Mar 04 '16 at 00:18
  • Since you've been able to get the Set-MM module onto all the remote machines, would you be able to copy a script and have the workflow invoke that script? – Charlie Joynt Mar 04 '16 at 00:19
  • What you are saying is to run an inline script inside of the invoke-command? – Waffles Mar 04 '16 at 00:25
  • The InlineScript goes within the `Foreach -Parallel` command, like you already tried, but rather than try to use the SCOM cmdlets directly, I'm wondering if you're able to fire off a separate script which imports the module(s) etc. – Charlie Joynt Mar 04 '16 at 00:41
  • Something like: `InlineScript{ & C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Set-MM\Scripts\Set-MaintenanceMode.ps1 }` – Charlie Joynt Mar 04 '16 at 00:43
  • I did something sort of similar, but I need to optimize it. I'll try your approach to see if it performs better. Rather than store the Workflow in a Module (psm1) file and then call it with the invoke command, I created a Workflow in the invoke-command and then called a function in the foreach that runs the Scom command. The only downside to this approach is each iteration of the Foreach loop also imports the OperationsManager Module. I kept running into Timeout issues with WSMAN, so I went with a smaller group of servers on the WSUS server and it ran successfully for half of the servers – Waffles Mar 04 '16 at 02:10
  • And then it ran out of resources and failed to process the rest. Half of the servers was 10. I've previously increased the memory of WSMAN from 1024 to 2048. – Waffles Mar 04 '16 at 02:11

0 Answers0