Sync Configuration Manager Client and Operations Manager Agent State in Service Manager
This post is the 4th in a series focused on making common administrative tasks in System Center and Azure available via the Service Manager Self-Service Portal. The Configuration Manager and Operations Manager Connectors pull a lot of information into Service Manager but not everything necessary to manage clients, agents, and other settings. This solution allows for the synchronizing of Configuration Manager client state and Operations Manager agent state into Service Manager on a schedule and on-demand.
Series
Prerequisites
The scenarios were designed using the following
- System Center Service Manager 2012 R2
- Self-Service Portal configured and working
- Active Directory Connector configured and working
- Configuration Manager Connector configured and working
- Orchestrator Connector configured and working
- System Center Configuration Manager 2012 R2
- Discovery configured and working
- System Center Orchestrator 2012 R2
- SC 2012 Configuration Manager Integration Pack configured and working
- SC 2012 Service Manager Integration Pack configured and working
- Configuration Manager Console installed on runbook servers (open the console, make sure you can connect to your site server)
- Operations Manager Console installed on runbook servers
- Service Manager Console installed on runbook servers
- Runbook servers configured to allow PowerShell scripts to run
Create a service account or use the one created in the previous blog post
- Give the account admin rights to Service Manager
- Give the account admin rights to Configuration Manager
- Give the account admin rights to Operations Manager
Create a share to store scripts and logs or use the one created in the previous blog post
- Create a share that the service account you created and authenticated users will have access to on the Runbook Servers that will be used for this scenario.
- In the share, create a folder called "Automation" and give the service account access to it.
- Copy DiscoverWindowsComputerExtended.ps1 into the Automation Folder
- In the share, create a sub-folder called "Logs" in the Automation Folder and give the applicable administrators access to it. Orchestrator will write logs to this folder and admins can use these logs for troubleshooting.
- In the Logs folder, create a sub-folder called "SRLogs" and give authenticated users access to it. Users of the Service Manager Portal will use these to see the status of the Collection Sync task so they will need rights to this folder.
param
(
[Parameter(Mandatory=$true)]
$CMSiteCode,
[Parameter(Mandatory=$true)]
$CMSiteServer,
[Parameter(Mandatory=$true)]
$OMManagementServer,
[Parameter(Mandatory=$true)]
$SMManagementServer,
[Parameter(Mandatory=$true)]
$VerboseLogging,
[Parameter(Mandatory=$false)]
$ServiceRequest
)
#Functions
function LogIt
{
param (
[Parameter(Mandatory=$true)]
$message,
[Parameter(Mandatory=$true)]
$component,
[Parameter(Mandatory=$true)]
$type )
switch ($type)
{
1 { $type = "Info" }
2 { $type = "Warning" }
3 { $type = "Error" }
4 { $type = "Verbose" }
}
if (($type -eq "Verbose") -and ($Global:Verbose))
{
$toLog = "{0} `$$<{1}><{2} {3}><thread={4}>" -f ($type + ":" + $message), ($Global:ScriptName + ":" + $component), (Get-Date -Format "MM-dd-yyyy"), (Get-Date -Format "HH:mm:ss.ffffff"), $pid
$toLog | Out-File -Append -Encoding UTF8 -FilePath $Global:LogFile
$Global:LogBuffer = $Global:LogBuffer + $toLog + "`r`n"
Write-Host $message
}
elseif ($type -ne "Verbose")
{
$toLog = "{0} `$$<{1}><{2} {3}><thread={4}>" -f ($type + ":" + $message), ($Global:ScriptName + ":" + $component), (Get-Date -Format "MM-dd-yyyy"), (Get-Date -Format "HH:mm:ss.ffffff"), $pid
$toLog | Out-File -Append -Encoding UTF8 -FilePath $Global:LogFile
$Global:LogBuffer = $Global:LogBuffer + $toLog + "`r`n"
Write-Host $message
}
}
function CreateServiceRequestLog
{
param($serviceRequest, $srLogPath)
LogIt -message ("Full Log File Path:" + $Global:LogFile) -component "Main()" -type 1
if ($serviceRequest)
{
$srLog = Join-Path $srLogPath ("Logs\SRLogs\" + $serviceRequest + ".log")
LogIt -message ("Service Request Log File Path:" + $srLog) -component "Main()" -type 1
$Global:LogBuffer | Out-File -Append -Encoding UTF8 -FilePath $srLog
}
}
function GetScriptDirectory
{
$invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $invocation.MyCommand.Path
}
function GetCMSiteConnection
{
param ($siteCode, $siteServer)
try { $CMModulePath = Join-Path -Path (Split-Path -Path "${Env:SMS_ADMIN_UI_PATH}" -ErrorAction Stop) -ChildPath "ConfigurationManager.psd1" }
catch
{
LogIt -message ("Cannot get path to CM console, will try default path: " + $_.Exception.Message) -component "GetCMSiteConnection()" -type 4
LogIt -message ("Trying static path: C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1") -component "GetCMSiteConnection()" -type 4
$CMModulePath = 'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
}
Import-Module $CMModulePath -ErrorAction Stop
try { $CMProvider = Get-PSDrive -PSProvider 'CMSite' -Name $siteCode -ErrorAction Stop }
catch
{
LogIt -message ("Cannot connect to CM site by Site Code, will retry: " + $siteCode + " Error: " + $_.Exception.Message) -component "GetCMSiteConnection()" -type 4
try { $CMProvider = New-PSDrive -PSProvider 'AdminUI.PS.Provider\CMSite' -Name $siteCode -Root $siteServer -Description 'SCCM Site' -ErrorAction Stop}
catch
{
LogIt -message ("Cannot connect to CM site by Server Name, exiting: " + $siteServer + " Error: " + $_.Exception.Message) -component "GetCMSiteConnection()" -type 3
exit
}
}
LogIt -message ("Connected to CM Site: " + $siteCode) -component 'GetCMSiteConnection()' -type 1
CD "$($CMProvider.SiteCode):\"
return $CMProvider
}
function GetOMManagementGroupConnection
{
param ($computerName)
Import-Module OperationsManager
try { $OM = New-SCManagementGroupConnection -computerName $computerName -ErrorAction Stop }
catch
{
LogIt -message ("Cannot connect to OM management group: " + $computerName + " Error: " + $_.Exception.Message) -component "GetOMManagementGroupConnection()" -type 3
exit
}
LogIt -message ("Connected to OM management group: " + $computerName) -component "GetOMManagementGroupConnection()" -type 1
return $OM
}
function GetSMManagementGroupConnection
{
param ($computerName)
$smDir = (Get-ItemProperty 'hklm:/software/microsoft/System Center/2010/Service Manager/Setup').InstallDirectory
try { Import-Module ($smDir + "\Powershell\System.Center.Service.Manager.psd1") -ErrorAction Stop }
catch
{
LogIt -message ("Cannot import SM PowerShell module, Error: " + $_.Exception.Message) -component "GetSMManagementGroupConnection()" -type 3
}
try { $SM = New-SCManagementGroupConnection -computerName $computerName -ErrorAction Stop }
catch
{
LogIt -message ("Cannot connect to SM management group: " + $computerName + " Error: " + $_.Exception.Message) -component "GetSMManagementGroupConnection()" -type 3
exit
}
LogIt -message ("Connected to SM management group: " + $computerName) -component "GetSMManagementGroupConnection()" -type 1
return $SM
}
function GetSCClass
{
param($computer, $name)
try { $scClass = Get-SCClass -ComputerName $computer -Name $name }
catch { LogIt -message ("Cannot get SM Class: " + $name + " Error: " + $_.Exception.Message) -component "GetSCClass()" -type 3 }
LogIt -message ("Retrieved SM Class: " + $name) -component "GetSCClass()" -type 4
return $scClass
}
function GetSCClassInstance
{
param($computer, $class, $filter)
if ($filter)
{
try { $scClassInstance = Get-SCClassInstance -ComputerName $computer -Class $class -Filter $filter }
catch { LogIt -message ("Cannot get SM Class instance: " + $class + " with filter: " + $filter + " Error: " + $_.Exception.Message) -component "GetSCClassInstance()" -type 2 }
}
else
{
try { $scClassInstance = Get-SCClassInstance -ComputerName $computer -Class $class }
catch { LogIt -message ("Cannot get SM Class instance: " + $class + " Error: " + $_.Exception.Message) -component "GetSCClassInstance()" -type 2 }
}
LogIt -message ("Retrieved SM Class instance of type: " + $class.Name) -component "GetSCClassInstance()" -type 4
return $scClassInstance
}
function GetCMClientObjects
{
param($computer, $siteCode)
try { $cmClients = Get-WmiObject "SMS_R_System" -ComputerName $computer -Namespace ("root\sms\site_{0}" -f $siteCode) }
catch
{
LogIt -message ("Cannot get CM Client Objects") -component "GetCMClientObjects()" -type 3
exit
}
LogIt -message ("Retrieved CM Client Objects") -component "GetCMClientObjects()" -type 4
return $cmClients
}
function GetCMClients
{
param($objects)
$ht = @{}
foreach ($object in $objects)
{
$ou = $null
$i = 0
if ($object.SystemOUName) { $aOU = $object.SystemOUName.Split(",") }
if ($aOU.Count -gt 0)
{
$ouRaw = $object.SystemOUName[$aOU.Count - 1]
$aOUs = $ouRaw.Split("/")
$iLastElement = $aOUs.Count
[array]::Reverse($aOUs)
foreach ($s in $aOUs)
{
$i++
if ($i -ne $iLastElement)
{
if ($ou) { $ou = $ou + "," + $s }
else { $ou = $s }
}
}
}
if (!($object.Client)) { $client = $false } else { $client = $true }
$PSObjectStrongName = (New-Object psobject).psobject.GetType().AssemblyQualifiedName
$o = New-Object "System.Collections.ObjectModel.Collection``1[[$PSObjectStrongName]]"
$o.Add((New-Object psobject -Property @{
PrincipalName=$object.ResourceNames[0];
Client=$client;
SystemOUName=$ou;
Agent=$false;
ProxyEnabled=$false
}))
try { $ht.Add($object.ResourceNames[0].ToUpper(), $o) } catch {}
}
LogIt -message ("Retrieved CM Clients") -component "GetCMClients()" -type 4
return $ht
}
function GetOMAgentObjects
{
param($computer)
try { $omAgents = Get-SCOMAgent -ComputerName $computer }
catch
{
LogIt -message ("Cannot get OM Agent Objects") -component "GetOMAgentObjects()" -type 3
exit
}
LogIt -message ("Retrieved OM Agent Objects") -component "GetOMAgentObjects()" -type 4
return $omAgents
}
function GetOMAgents
{
param($objects)
$ht = @{}
foreach ($object in $objects)
{
try { $ht.Add($object.PrincipalName.ToUpper(), $object.ProxyingEnabled) } catch {}
}
LogIt -message ("Retrieved OM Agents") -component "GetOMAgents()" -type 4
return $ht
}
function GetSMObjects
{
param($computer)
$deviceDefinition = GetSCClass -computer $computer -name 'Microsoft.Windows.Computer'
$deviceInstances = GetSCClassInstance -computer $computer -class $deviceDefinition
LogIt -message ("Retrieved SM Objects") -component "GetSMObjects()" -type 4
return $deviceInstances
}
function GetSMDevices
{
param($objects)
$ht = @{}
foreach ($object in $objects)
{
$PSObjectStrongName = (New-Object psobject).psobject.GetType().AssemblyQualifiedName
$o = New-Object "System.Collections.ObjectModel.Collection``1[[$PSObjectStrongName]]"
$o.Add((New-Object psobject -Property @{
PrincipalName=$object.PrincipalName;
Client=$object.CMClient;
SystemOUName=$object.OrganizationalUnit;
Agent=$object.OMAgent;
ProxyEnabled=$object.OMProxyEnabled
}))
try { $ht.Add($object.PrincipalName.ToUpper(), $o) } catch {}
}
LogIt -message ("Retrieved SM Devices") -component "GetSMDevices()" -type 4
return $ht
}
function GetCombinedCMOMData
{
param($cmClients, $omAgents)
$ht = $cmClients
foreach ($omAgent in $omAgents.GetEnumerator())
{
$oCM = $ht.Get_Item($omAgent.Key)
if ($oCM)
{
$PSObjectStrongName = (New-Object psobject).psobject.GetType().AssemblyQualifiedName
$oCombined = New-Object "System.Collections.ObjectModel.Collection``1[[$PSObjectStrongName]]"
$oCombined.Add((New-Object psobject -Property @{
PrincipalName=$oCM.PrincipalName;
Client=$oCM.Client;
SystemOUName=$oCM.SystemOUName;
Agent=$true;
ProxyEnabled=$omAgent.Value
}))
try { $ht.Set_Item($omAgent.Key, $oCombined) } catch {}
}
else
{
$PSObjectStrongName = (New-Object psobject).psobject.GetType().AssemblyQualifiedName
$oCombined = New-Object "System.Collections.ObjectModel.Collection``1[[$PSObjectStrongName]]"
$oCombined.Add((New-Object psobject -Property @{
PrincipalName=$omAgent.Key;
Client=$false;
SystemOUName=$null;
Agent=$true;
ProxyEnabled=$omAgent.Value
}))
try { $ht.Add($omAgent.Key, $oCombined) } catch {}
}
}
LogIt -message ("Retrieved Combined CM/OM Data") -component "GetCombinedCMOMData()" -type 4
return $ht
}
function IsWindowsComputerCurrent
{
param($smRecord, $cmomRecord)
$bCurrent = $true
if ($cmomRecord.Value.SystemOUName -ne $smRecord.SystemOUName) { $bCurrent = $false }
return $bCurrent
}
function IsWindowsComputerExtendedCurrent
{
param($smRecord, $cmomRecord)
$bCurrent = $true
try
{
if ($cmomRecord.Value.Agent.ToString() -ne $smRecord.Agent.ToString()) { $bCurrent = $false }
if ($cmomRecord.Value.ProxyEnabled.ToString() -ne $smRecord.ProxyEnabled.ToString()) { $bCurrent = $false }
if ($cmomRecord.Value.Client.ToString() -ne $smRecord.Client.ToString()) { $bCurrent = $false }
}
catch{ $bCurrent = $false }
return $bCurrent
}
function UpdateWindowsComputerObject
{
param($computer, $object)
$classDefinition = GetSCClass -computer $computer -name 'Microsoft.Windows.Computer'
$filter = 'PrincipalName -eq "{0}"' -f $object.Value.PrincipalName
$class = GetSCClassInstance -computer $computer -class $classDefinition -filter $filter
$class.OrganizationalUnit = $object.Value.SystemOUName
try { Update-SCClassInstance -Instance $class -ErrorAction Stop }
catch { LogIt -message ("Cannot Update Windows Computer Instance: " + $object) -component "UpdateWindowsComputerObject()" -type 3 }
LogIt -message ("Retrieved Existing Instance for " + $object.Value.PrincipalName) -component "UpdateWindowsComputerObject()" -type 4
LogIt -message ("Updated OU for " + $object.Value.PrincipalName + " to " + $object.Value.SystemOUName) -component "UpdateWindowsComputerObject()" -type 1
}
function UpdateWindowsComputerExtendedObject
{
param($computer, $object)
$classDefinition = GetSCClass -computer $computer -name 'Microsoft.Windows.Computer'
$filter = 'PrincipalName -eq "{0}"' -f $object.Value.PrincipalName
$class = GetSCClassInstance -computer $computer -class $classDefinition -filter $filter
if ($class)
{
try { $class.OMAgent = $object.Value.Agent } catch { $class.OMAgent = $false }
try { $class.CMClient = $object.Value.Client } catch { $class.CMClient = $false }
try { $class.OMProxyEnabled = $object.Value.ProxyEnabled.ToString() } catch { $class.OMProxyEnabled = $false }
try
{
$class | Update-SCClassInstance -ErrorAction Stop
LogIt -message ("Retrieved Existing Extended Instance for " + $object.Value.PrincipalName) -component "UpdateWindowsComputerExtendedObject()" -type 4
LogIt -message ("Updated OMAgent for " + $object.Value.PrincipalName + " to " + $object.Value.Agent) -component "UpdateWindowsComputerExtendedObject()" -type 1
LogIt -message ("Updated CMClient for " + $object.Value.PrincipalName + " to " + $object.Value.Client) -component "UpdateWindowsComputerExtendedObject()" -type 1
LogIt -message ("Updated OMProxyEnabled for " + $object.Value.PrincipalName + " to " + $object.Value.ProxyEnabled) -component "UpdateWindowsComputerExtendedObject()" -type 1
}
catch { LogIt -message ("Cannot Update Windows Computer Instance: " + $object.Value.PrincipalName + " Error:" + $_.Exception.Message) -component "UpdateWindowsComputerExtendedObject()" -type 3 }
}
}
function DeleteWindowsComputerExtendedObject
{
param($computer, $object)
$classDefinition = GetSCClass -computer $computer -name 'Microsoft.Windows.Computer'
$filter = 'PrincipalName -eq "{0}"' -f $object.Value.PrincipalName
$class = GetSCClassInstance -computer $computer -class $classDefinition -filter $filter
if ($class)
{
if (($class.OMAgent) -or ($class.CMClient) -or ($class.OMProxyEnabled))
{
$class.OMAgent = $false
$class.CMClient = $false
$class.OMProxyEnabled = $false
try { Update-SCClassInstance -Instance $class -ErrorAction Stop }
catch { LogIt -message ("Cannot Update Extended Instance for " + $object.Value.PrincipalName) -component "DeleteWindowsComputerExtendedObject()" -type 3 }
LogIt -message ("Retrieved Existing Instance for " + $object.Value.PrincipalName) -component "DeleteWindowsComputerExtendedObject()" -type 4
LogIt -message ("Extended Instance Removed for " + $object.Value.PrincipalName) -component "DeleteWindowsComputerExtendedObject()" -type 1
}
}
}
function UpdateOUProperty
{
param($computer, $object)
$classDefinition = GetSCClass -computer $computer -name 'Microsoft.Windows.Computer'
$filter = 'PrincipalName -eq "{0}"' -f $object.Value.PrincipalName
$class = GetSCClassInstance -computer $computer -class $classDefinition -filter $filter
if ($class.OrganizationalUnit -ne $null)
{
$class.OrganizationalUnit = $null
try { Update-SCClassInstance -Instance $class -ErrorAction Stop }
catch { LogIt -message ("Cannot Update Windows Computer Instance: " + $object) -component "UpdateWindowsComputerObject()" -type 3 }
LogIt -message ("Retrieved Existing Instance for " + $object.Value.PrincipalName) -component "UpdatedOUProperty()" -type 4
LogIt -message ("Updated OU for " + $object.Value.PrincipalName + " to NULL") -component "UpdateOUProperty()" -type 1
}
}
function SubmitDiscoveryData
{
param($computer, $combinedCMOMData, $combinedSMData)
#Update/Add
foreach ($cmomRecord in $combinedCMOMData.GetEnumerator())
{
$smRecord = $combinedSMData.Get_Item($cmomRecord.Key)
if($combinedSMData.ContainsKey($cmomRecord.Key))
{
#See if Windows Computer Object needs updating
if (!(IsWindowsComputerCurrent -smRecord $smRecord -cmomRecord $cmomRecord))
{
UpdateWindowsComputerObject -computer $computer -object $cmomRecord
}
#See if Windows Computer Extended Object needs updating
if (!(IsWindowsComputerExtendedCurrent -smRecord $smRecord -cmomRecord $cmomRecord))
{
UpdateWindowsComputerExtendedObject -computer $computer -object $cmomRecord
}
}
else { LogIt -message ("Could not find record in SM CMDB for device " + $cmomRecord.Key + ", skipping") -component "SubmitDiscoveryData()" -type 2 }
$combinedSMData.Remove($cmomRecord.Key)
}
#Remove
foreach ($smRecord in $combinedSMData.GetEnumerator())
{
DeleteWindowsComputerExtendedObject -computer $computer -object $smRecord
UpdateOUProperty -computer $computer -object $smRecord
}
}
#Main
$Version = "1.0"
[bool]$Global:Verbose = [System.Convert]::ToBoolean($VerboseLogging)
$Global:LogFile = Join-Path (GetScriptDirectory) 'Logs\DiscoverWindowsComputerExtended.log'
$Global:ScriptName = 'DiscoverWindowsComputerExtended.ps1'
$Global:LogBuffer = ''
$Global:ScriptStatus = 'Success'
LogIt -message ("Windows Computer Extended Discovery Script v{0}" -f $Version) -type 1 -component "Main()"
#Connect to CM
$CM = GetCMSiteConnection -siteServer $CMSiteServer -siteCode $CMSiteCode
#Get CM Clients
$CMClientObjects = GetCMClientObjects -computer $CM.Root -siteCode $CM.Name
$CMClients = GetCMClients -objects $CMClientObjects
#Connect to OM
$OM = GetOMManagementGroupConnection -computerName $OMManagementServer
#Get OM Agents
$OMAgentObjects = GetOMAgentObjects -computer $OMManagementServer
$OMAgents = GetOMAgents -objects $OMAgentObjects
#Combine Data to be Discovered
$CombinedCMOMData = GetCombinedCMOMData -cmClients $CMClients -omAgents $OMAgents
#Connect to SM
$SM = GetSMManagementGroupConnection -computerName $SMManagementServer
#Get SM Devices
$SMObjects = GetSMObjects -computer $SMManagementServer
$SMDevices = GetSMDevices -objects $SMObjects
#Submit Data
SubmitDiscoveryData -computer $SMManagementServer -combinedCMOMData $CombinedCMOMData -combinedSMData $SMDevices
#Log Result
$Ret = $Global:ScriptStatus
LogIt -message ("Script Complete, Result: {0}" -f $Ret) -component "Main()" -type 1
#Create SR Log if needed
CreateServiceRequestLog -serviceRequest $ServiceRequest -srLogPath (GetScriptDirectory)
Import the Windows Computer Extended Discovery Management Pack into Service Manager
This Management Pack contains a class that extends Microsoft.Windows.Computer so that it includes properties for the Configuration Manager client, Operations Manager agent, and Operations Manager Agent Proxy.
- Open the Service Manager Console
- Select Administration
- Right-Click Management Packs and select Import
- Select the Custom.Example.DataCenter.Automation.WindowsComputerExtended.mp management pack and choose Open, Import, and OK
<?xml version="1.0" encoding="utf-8"?>
<ManagementPack SchemaVersion="2.0" ContentReadable="true" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
<Manifest>
<Identity>
<ID>Custom.Example.DataCenter.Automation.WindowsComputerExtended</ID>
<Version>1.0.0.0</Version>
</Identity>
<Name>DataCenter Automation: Windows Computer Extended</Name>
<References>
<Reference Alias="Windows">
<ID>Microsoft.Windows.Library</ID>
<Version>7.5.8501.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
<Reference Alias="System">
<ID>System.Library</ID>
<Version>7.5.8501.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
</References>
</Manifest>
<TypeDefinitions>
<EntityTypes>
<ClassTypes>
<ClassType ID="Custom.Example.DataCenter.Automation.WindowsComputerExtended.MicrosoftWindowsComputerExtended" Base="Windows!Microsoft.Windows.Computer" Extension="true" Accessibility="Public" Abstract="false" Hosted="false" Singleton="false">
<Property ID="OMAgent" Key="false" Type="bool" />
<Property ID="CMClient" Key="false" Type="bool" />
<Property ID="OMProxyEnabled" Key="false" Type="bool" />
</ClassType>
</ClassTypes>
</EntityTypes>
</TypeDefinitions>
<LanguagePacks>
<LanguagePack ID="ENU" IsDefault="true">
<DisplayStrings>
<DisplayString ElementID="Custom.Example.DataCenter.Automation.WindowsComputerExtended">
<Name>DataCenter Automation: Windows Computer Extended</Name>
<Description>Management Pack for extending Windows Computer in Service Manager</Description>
</DisplayString>
<DisplayString ElementID="Custom.Example.DataCenter.Automation.WindowsComputerExtended.MicrosoftWindowsComputerExtended">
<Name>Windows Computer Extended</Name>
</DisplayString>
<DisplayString ElementID="Custom.Example.DataCenter.Automation.WindowsComputerExtended.MicrosoftWindowsComputerExtended" SubElementID="OMAgent">
<Name>Operations Manager Agent</Name>
</DisplayString>
<DisplayString ElementID="Custom.Example.DataCenter.Automation.WindowsComputerExtended.MicrosoftWindowsComputerExtended" SubElementID="CMClient">
<Name>Configuration Manager Client</Name>
</DisplayString>
<DisplayString ElementID="Custom.Example.DataCenter.Automation.WindowsComputerExtended.MicrosoftWindowsComputerExtended" SubElementID="OMProxyEnabled">
<Name>Operations Manager Proxy Enabled</Name>
</DisplayString>
</DisplayStrings>
<KnowledgeArticles></KnowledgeArticles>
</LanguagePack>
</LanguagePacks>
</ManagementPack>
Create the Windows Computer Extended (On-Demand) Runbook
This Runbook will launch a PowerShell script when it is triggered via the Service Manager Self-Service Portal.
Open the Orchestrator Runbook Designer
Create a new runbook
Drag the "Runbook Control\Initialize Data" activity into the new runbook
Configure a "ServiceRequest" parameter of type "String" under the Initialize Data activity
Drag the "System\Run Program" activity into the new runbook
Link the two activities
Configure the Security of "System\Run Program" to use the service account
Configure three settings under the "Details" section of the "Run Program" activity and click finish
- Program path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- Parameters: -File <local sharepath>\Automation\DiscoverWindowsComputerExtended.ps1 -CMSiteCode CAS -CMSiteServer sccm2012r2cas.contoso.com -OMManagementServer scom2012r2.contoso.com -SMManagementServer sm2012r2.contoso.com -VerboseLogging false -ServiceRequest {ServiceRequest from "Initialize Data"}
- Working Folder: <local sharepath>\Automation
- Note, the data between the curly braces are Published Data from the Data Bus. This is obtained by right-clicking on the white space and selecting the appropriate variable. You can also use Orchestrator variables configured under Global Settings for items such as CMSiteCode, CMSiteServer, and SMManagementServer.
Check In the Runbook
The Runbook should look like this:
Create the Windows Computer Extended (Full - Scheduled) Runbook
This Runbook will launch a PowerShell script when it is triggered via a schedule. This will catch Collections and Collection modifications that have occurred outside of the Service Manager Self-Service Portal.
Open the Orchestrator Runbook Designer
Create a new runbook
Drag the "Scheduling\Monitor Date/Time" activity into the new runbook
Configure one setting under Details of the Monitor Date/Time activity and click Finish
- Every: 1 hour
Drag the "System\Run Program" activity into the new runbook
Link the two activities
Configure the Security of "System\Run Program" to use the service account
Configure three settings under the "Details" section of the "Run Program" activity and click finish
- Program path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- Parameters: -File <local sharepath>\Automation\DiscoverWindowsComputerExtended.ps1 -CMSiteCode CAS -CMSiteServer sccm2012r2cas.contoso.com -OMManagementServer scom2012r2.contoso.com -SMManagementServer sm2012r2.contoso.com -VerboseLogging false
- Working Folder: <sharepath>\Automation
- You can also use Orchestrator variables configured under Global Settings for items such as CMSiteCode, CMSiteServer, and SMManagementServer.
Check in and Start this runbook.
The Runbook should look like this:
Summary
The on-demand runbook will be used in future posts for synchronizing Configuration Manager and Operations Manager client/agent information with Service Manager. The scheduled runbook will start working on the schedule to synchronize Configuration Manager client state, Operations Manager agent state, and Operations Manager agent proxy setting thereby picking up changes made outside of the Service Manager Portal.
Continue to the 5th post in this series: Using the Service Manager Self-Service Portal to Manage Configuration Manager Clients