SCOM – SCOM Management Pack Creation Script v1.0
Automate building an entire SCOM Management Pack Script!
I had created many customized management packs using Visual Studios within combination of the VSAE Authoring extensions application.
Writing an entire management can take a lot of time depending on the complexity requirements such as
·Classes
·Discoveries
·Views
·Monitors
·Rules
There have been methods to speed up and aid in the productivity such as using the VSAE authoring guide available on TechNet, opening a sealed management pack to look at the XML code and also using the existing codes from a management pack which you yourself had created.
One of the issues I sometimes faced was creating Monitors, Rules or discoveries using the templates as sometimes if you make edits directly to the XML file which can control anyone of these it will then be overwritten if you attempt to change anything inside of the template files used to create any of those specific objects within your management pack.
This lead me to develop my own solution which would end up being a PowerShell script called the “ SCOM Management Pack Creation Script v1.0 ”
What can it do
This script has the capability to build an entire SCOM management pack from scratch using its XML codes and intellisense answers.
Here are the objects in which can be created
·Classes
·Properties for classes (additional attributes)
·Secure References (Run As Accounts)
·Discoveries
·Script for discoveries (PowerShell, VBScript, Registry & WMI)
·Views
·Monitors & Rules (Event Monitor)
The script has the ability to format the entire XML code the exact same way you would see it shown within the Visual Studios application when creating a new project to create a management Pack.
How does it work
The script has various functions which can perform many different tasks which allow you to fully build and customize the entire management pack.
Below is a list of the CMDLets and description of each one detailing how each one works.
New-SCOMMPClass
This function creates the XML frame for the class file
Add-SCOMMPClass
This will create the actual Class object in the XML format
Switches
§-ClassName – Name of the class
§-ClassType – Type of class (Options being WindowsComputer, UnixComputer, ComputerGroup, InstanceGroup, WindowsApplicationComponent or WindowsLocalApplication)
§-Abstract – Will this class be abstract (Options being true or false)
§-Hosted – Will this class be a hosted class (Options being true of false)
§-Singleton – Will this class be a singleton class (Options being true or false)
§-MPClassFile – Location of where the XML file will be created
Add-SCOMMPClassProperty
This will create any additional properties for your class
Switches
§-PropertyName – Name of the Property
§-PropertyType – Type of property i.e. string, boolean
§-PropertyDescription – Description of the property
§-AffectedClassID – The class which this property is linked to
§-MPClassFile – Location of where the XML files will be created
Add-SCOMMPRunAsAccount
This will add a Run as Account to your class
Switches
§-SecureReferenceName – Name of the Run As Account
§-SecureReferenceDescription – Description of the Run As Account
§-MPClassFile - Location of where the XML file will be created
Edit-SCOMMPClass
Gives you a numbered option list of if you want to create a new class, property for a specific class or a run as account
New-SCOMMPDiscovery
This function creates the XML frame for the class file
Add-SCOMMPPowerShellDiscovery
The discovery file gets created using PowerShell as its form of discovery
Switches
§-DiscoveryName – Name of the discovery
§-DiscoveryTarget – Which class will the discovery run for
§-DiscoveryDescription – Description of the discovery
§-DiscoveryClass – Discovery Class Name
§-DiscoveryRunAsAccount – Run As account used to run the discovery
§-IntervalSeconds – Time to run the discovery
§-SyncTime – Specifcy a time to run at (optional)
§-ScriptName – Name of the script
§-ScriptBody – Script body content
§-TImeoutSeconds – Time it takes to no longer run
§-MPClassFile – Location of the class file
§-MPDiscoveryFile – Location of where the discovery file will be created
§-ClassID – Pass through details of the class used
Add-SCOMMPRegistryDiscovery
The discovery file gets created using the Registry as its form of discovery
Switches
§-DiscoveryName – Name of the discovery
§-DiscoveryTarget – Which class will the discovery run for
§-DiscoveryDescription – Description of the discovery
§-DiscoveryClass – Discovery Class Name
§-DiscoveryRunAsAccount – Run As account used to run the discovery
§-Frequency – Seconds it takes to run
§-MPClassFile – Location of the class file
§-MPDiscoveryFile – Location of where the discovery file will be created
§-ClassID – Pass through details of the class used
Add-SCOMMPRegistryKey
Switches
§-AttributeName – Name of the Registry Key name
§-RegistryPath – Path to the key
§-PathType – 0 – To check key exists, 1 – Key value to be retrieved
§-AttributeType – 0 – Boolean, 1 – String, 2 – Integer and 3 - Float
§-ClassID – Pass through details of the class used
Edit-SCOMMPRegistryKey
Asks to create a Registry attribute for your discovery
Add-SCOMMPWMIDiscovery
The discovery file gets created using WMl as its form of discovery
Switches
§-DiscoveryName – Name of the discovery
§-DiscoveryTarget – Which class will the discovery run for
§-DiscoveryDescription – Description of the discovery
§-DiscoveryClass – Discovery Class Name
§-DiscoveryRunAsAccount – Run As account used to run the discovery
§-Namespace – The WMI namespace which will be used to discover objects
§-Query – The WMI query used to run discovery
§-Frequency – Seconds it takes to run
§-ClassID – Pass through details of the class used
Add-SCOMMPVBScriptDiscovery
The discovery file gets created using VBScript as its form of discovery
Switches
§-ClassID – Pass through details of the class used
§-DiscoveryName – Name of the discovery
§-DiscoveryTarget – Which class will the discovery run for
§-DiscoveryDescription – Description of the discovery
§-DiscoveryClass – Discovery Class Name
§-DiscoveryRunAsAccount – Run As account used to run the discovery
§-IntervalSeconds – Time to run the discovery
§-SyncTime – Specifcy a time to run at (optional)
§-MPClassFile – Location of the class file
§-MPDiscoveryFile – Location of where the discovery file will be created
§-ScriptName – Name of the script
§-ScriptBody – Script body content
§-TImeoutSeconds – Time it takes to no longer run
§-ClassID - Pass through details of the class used
Add-SCOMMPComputerGroupDiscovery
Creates the entry to discover and create a Computer Group for your class
Switches
§-DiscoveryName – Name of the discovery
§-DiscoveryTarget – Which class will the discovery run for
§-DiscoveryDescription – Description of the discovery
§-ClassID - Pass through details of the class used
§-DiscoveryFile – Discovery file location where the computer group discovery will be added
Add-SCOMMPInstanceGroupDiscovery
Creates the entry to discover and create an Instance Group for your class
Switches
§-DiscoveryName – Name of the discovery
§-DiscoveryTarget – Which class will the discovery run for
§-DiscoveryDescription – Description of the discovery
§-ClassID - Pass through details of the class used
§-DiscoveryFile – Discovery file location where the instance group discovery will be added
Create-PowerShellScript
Creates the PowerShell script with the PowerShell lines which enable it to capture all of the properties you wish to discover and a line to display where you should enter your PowerShell script to do the capturing logic
Create-VBScript
Creates the VBScript script with the VBScript lines which enable it to capture all of the properties you wish to discover and a line to display where you should enter your VBscript to do the capturing logic
New-SCOMMPView
This function creates the XML frame for the view file
Add-SCOMMPView
Creates the view XML for your class and management pack
Switches
§-ViewName – Name of the View
§-ViewID – ID name of the View
§-ViewTarget – Class which the view will be created for
§-ViewType – Options such as “StateView”, “AlertView”, “EventView” and “OverridesSummaryView”
§-FolderID – Folder ID for where the view will be placed
§-MPViewFile – Output location of the View XML file
New-SCOMMPFolder
This function creates the XML frame for the folders view file
Add-SCOMMPFolder
Creates the folder view XML
Switches
§-FolderName – Name of the folder shown in the SCOM Console
§-FolderID – ID name of the folder i.e. SCOM.Folder
§-FolderParent – Enter “Root” for it to show in the console
§-MPFolderFile – Location of where the XML file will be outputted
Edit-SCOMMPViewsFolders
Asks if you wish to create more views or folders for your management pack
New-SCOMMPMonitorRule
This function creates the XML frame for the Monitor and Rule file depending on which one you chose to create
Add-SCOMMPWindowsEventMonitor
Creates the Windows 2 state Event Monitor
Switches
§-MontiorName – Name of monitor
§-MonitorEnabled – If monitored is enabled by default or not “true” or “false”
§-MonitorTarget – (Options being WindowsComputer, UnixComputer, ComputerGroup, InstanceGroup, WindowsApplicationComponent or WindowsLocalApplication)
§-MonitorRunAsAccount – Run as account which will run the monitor
§-AlertOnState – If it should alert on Error or Warning
§-AlertSeverity – Alert Severity, Error or Warning
§-AlertPriority – Alert Priority, High, Normal or Low
§-AlertMessage – Message shown when alert is created
§-UnHealthyLogName – Log Name for unhealthy status
§-UnHealthyPublisherName – Publisher name for unhealthy status
§-UnHealthyEventDisplayNumber – Event Number for unhealthy status
§-HealthyLogName – Log Name for healthy status
§-HealthyPublisherName – Publisher name for healthy status
§-HealthyEventDisplayNumber - Event Number for unhealthy status
§-MPMonitorRuleFile – Output for XML for Monitor file
Add-SCOMMPWindowsEventRule
Creates the Event Rule
Switches
§-RuleName – Name of rule
§-RuleEnabled – If rule is enabled by default or not, “true” or “false”
§-RuleTarget – (Options being WindowsComputer, UnixComputer, ComputerGroup, InstanceGroup, WindowsApplicationComponent or WindowsLocalApplication)
§-RuleRunAsAccount – Run As Account which will run the rule
§-AlertMessage – Message shown when alert is created
§-Severity – Alert Severity, Error or Warning
§-Priority – Alert Priority, High, Normal or Low
§-LogName – Log Name for unhealthy status
§-PublisherName – Publisher name for unhealthy status
§-MPMonitorRuleFile - Output location of the View XML file
Edit-SCOMMPMonitorRule
Asks if you wish to create a Monitor or Rule for your Management Pack
Step-by-Step Guide on how to use
Once you run the management pack this is how the process will go
( Note: Ensure when you are creating any classes or anything make sure you go through the wizard and enter it again exactly as you did it as it is case sensitive and it can stop the management pack from building successfully)
PowerShell Script Steps
1.Enter the name of the Management Pack
2.Enter the platform type which is either “Windows” or “Unix”
3.Enter the discovery method which is either “PowerShell”, “VBScript”, “WMI” or “Registry”
4.Enter the location of where all of the XML files will be created
5.You will go through the creating of the class object
6.Asked to extract properties from a specific class to build the discovery around ( Note: Depending on the discovery method you chose it will create the template for it i.e. PowerShell, it will create the PowerShell lines to capture the information but you would need to enter your initial script into it for it to be able to work)
7.Asks to create a ComputerGroup for your class
8.Asks to create an InstanceGroup for your class
9.Creates the Management Pack folder
10.Enter details to create the views
11.Asks if you wish to add more folders or views
12.Asks if you wish to create any Monitors or Rules
13.If yes it will ask to create a Monitor or Rule and then go into the questions for it
14.Message states the management pack is now created
Create Visual Studios Project Steps
Once this is done you will need to create a new Visual Studios project if you haven’t done so already and do the following to create the objects.
§Right click your project and choose to create a new object
§Choose the Empty Fragment file and give it an appropriate name according to the XML files you created
§Open the XML files I.e. class file and copy the XML from this and into the Empty Fragment file which you have created
§Create the script file (if PowerShell or VBScript) in your Visual Studios project and name it exactly as it is on your XML output.
§Copy the information from your outputted script file into the new script you created for your new management pack.
§If you had an InstanceGroup created, then make sure to right click the “References” part in your Visual Studios project and click to add a new reference. Browse to the C:\Program Files (x86)\System Center Authoring Extensions\References\OM12/16\SystemCenter.InstanceGroup.Library . Then once showing click the reference object and change the Alias to SCIG
§Build the management pack when ready
Release Notes
Version one of SCOM Management Pack Creation
(Note: Essentially is capable of Windows Management Packs only)
§Creates Classes (Add multiple classes and properites and RunAs Account)
§Creates Discovery files (PowerShell & Registry only)
§Creates PowerShell script that can be used for PowerShell
§Creates Folders (Can Add multiple folders)
§Creates Views (Can add multiple views and add them to specific folders)
It currently creates each part as a separate file where the XML code can be copied into a visual studio project
Version two will do the following
§Support for Unix Management Pack creation
§Edit specific parts of the management pack XML content
§Create as one whole XML file
§Add any Monitor and Rule type besides Event monitor creation
Troubleshooting
Four error messages after building management pack failed with Module DS not valid
Make sure that the script you created is created with exactly the same name as the output script file from the PowerShell Script. As your created discovery file references the script name within the “ScriptFile” XML switch
Errors Regarding instancegroup Unknown alias
Add the SystemCenter.InstanceGroup.Library management pack to your References in your Visual Studio Project. Change the alias name from “MSIL” to “SCIG”
Script
Here is the script. Highlight it and save into a .ps1 script
# #
# SCOM Management Pack Creation Version 1 #
# By Dujon Walsham #
# Walsham Solutions Ltd #
# Co Founder of SC-Clan #
# 360 degrees of perfected styles #
# Script for SCOM aka Gza/Genius #
# #
# Things to fix on script #
# #
# #
# #
# #
# #
# #
#############################################################################################
# Create New Class
Function New-SCOMMPClass
{
#PARAM (
#[String]$ClassName = $(Read-Host -Prompt "Name of Class"),
#[String]$ClassType = $(Read-Host -Prompt "Type of Class"),
#[String]$ClassDescription = $(Read-Host -Prompt "Description of Class"),
#[String]$PropertyName = $(Read-Host -Prompt "Name of Property"),
#[String]$PropertyType = $(Read-Host -Prompt "Type of Property"),
#[String]$PropertyDescription = $(Read-Host -Prompt "Description of Property"),
#[String]$SecureReferenceName = $(Read-Host -Prompt "Name of Run As Account"),
#[String]$SecureReferenceDescription = $(Read-Host -Prompt "Description of Run As Account"),
#[String]$MPClassFile = $(Read-Host -Prompt "Where to save class file")
#)
#$ClassID = $ClassName -replace " ", "."
#$PropertyID = $PropertyName -replace " ", "."
#$SecureReferenceID = $SecureReferenceName -replace " ", ""
# Builds the XML structure for the Class
Add-Content $MPClassFile "<ManagementPackFragment SchemaVersion=""2.0"" xmlns:xsd="" `n" id="1080427193">http://www.w3.org/2001/XMLSchema"">`n
<TypeDefinitions>`n <EntityTypes>`n <ClassTypes>`n </ClassTypes>`n</EntityTypes>`n<SecureReferences>`n</SecureReferences>`n </TypeDefinitions>`n <LanguagePacks>`n <LanguagePack ID=""ENU"" IsDefault=""true"">`n <DisplayStrings>`n </DisplayStrings>`n </LanguagePack>`n </LanguagePacks>`n</ManagementPackFragment> "
}
Function Add-SCOMMPClass
{
Param (
[String]$ClassName = $(Read-Host -Prompt "Name of Class"),
[String]$ClassType = $(Read-Host -Prompt "Type of Class"),
[String]$ClassDescription = $(Read-Host -Prompt "Description of Class"),
[String]$Abstract = $(Read-Host -Prompt "Is this an abstract class which will be used a base class. true or false (Must be lowercase) Default is false"),
[String]$Hosted = $(Read-Host -Prompt "Is this class hosted by another class. true or false (Must be lowercase) Default is true"),
[String]$Singleton = $(Read-Host -Prompt "Is this a singleton class where only one instance will exist. true or false (Must be lowercase) Default is false"),
[String]$MPClassFile = $(Read-Host -Prompt "Where to save class file")
)
# Default Values
If ($Abstract -eq "")
{$Abstract = "false"}
If ($Hosted -eq "")
{$Hosted = "true"}
If ($Singleton -eq "")
{$Singleton = "false"}
# Sets ClassType
If ($ClassType -eq "WindowsComputer") {$ClassType = "Windows!Microsoft.Windows.ComputerRole"}
If ($ClassType -eq "WindowsApplicationComponent") {$ClassType = "Windows!Microsoft.Windows.ApplicationComponent"}
If ($ClassType -eq "WindowsLocalApplication") {$ClassType = "Windows!Microsoft.Windows.LocalApplication"}
If ($ClassType -eq "UnixComputer") {$ClassType = "Unix!Microsoft.Unix.ComputerRole"}
If ($ClassType -eq "ComputerGroup") {$ClassType = "SC!Microsoft.SystemCenter.ComputerGroup"}
If ($ClassType -eq "InstanceGroup") {$ClassType = "SCIG!Microsoft.SystemCenter.InstanceGroup"}
# Formats the Class Name to the relevant format for the XML to handle the Class name
$ClassID = $ClassName -replace " ", "."
$ClassContent = Get-Content $MPClassFile
# Writes the Class Type information in the class file
$FindLastClassTypeLine = Select-String $MPClassFile -pattern "</ClassTypes>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastClassTypeLine] += "`n <ClassType ID=""$classID"" Base=""$ClassType"" Accessibility=""Internal"" Abstract=""$Abstract"" Hosted=""$Hosted"" Singleton=""$Singleton"">`n </ClassType>"
$ClassContent | Set-Content $MPClassFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPClassFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPClassFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$ClassID"">`n <Name>$ClassName</Name>`n <Description>$ClassDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPClassFile
}
Function Add-SCOMMPClassProperty
{
Param (
[String]$PropertyName = $(Read-Host -Prompt "Name of Property"),
[String]$PropertyType = $(Read-Host -Prompt "Type of Property i.e. string, boolean (has to be lowercase)"),
[String]$PropertyDescription = $(Read-Host -Prompt "Description of Property"),
[String]$AffectedClassID = $(Read-Host -Prompt "Class which the property will be added to"),
[String]$MPClassFile = $(Read-Host -Prompt "Class file location")
)
# Formats the Property Name to the relevant format for the XML to handle the Property name
$AffectedClassID = $AffectedClassID -replace " ", "."
$PropertyID = $PropertyName -replace " ", "."
$ClassContent = Get-Content $MPClassFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPClassFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$AffectedClassID"" SubElementID=""$PropertyID"">`n <Name>$PropertyName</Name>`n <Description>$PropertyDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPClassFile
# Adds the Property to the Class within the XML file
(Get-Content $MPClassFile) |
Foreach-Object {
$_
if ($_ -match "<Classtype ID=""$AffectedClassID""")
{
" <Property ID=""$PropertyID"" Key=""true"" Type=""$PropertyType""/>"
}
} | Set-Content $MPClassFile
}
Function Add-SCOMMPRunAsAccount
{
Param (
[String]$SecureReferenceName = $(Read-Host -Prompt "Name of Run As Account"),
[String]$SecureReferenceDescription = $(Read-Host -Prompt "Description of Run As Account"),
[String]$MPClassFile = $(Read-Host -Prompt "Class file location")
)
# Formats the Secure Reference Name to the relevant format for the XML to handle the Secure Reference name
$SecureReferenceID = $SecureReferenceName -replace " ", "."
$ClassContent = Get-Content $MPClassFile
# Adds the Secure Reference (Run As Account) to the management pack
$FindLastSecureReferenceLine = Select-String $MPClassFile -pattern "</SecureReferences>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastSecureReferenceLine] += "`n <SecureReference ID=""$SecureReferenceID"" Accessibility=""Internal"" Context=""System!System.Entity"" />"
$ClassContent | Set-Content $MPClassFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPClassFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPClassFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$SecureReferenceID"">`n <Name>$SecureReferenceName</Name>`n <Description>$SecureReferenceDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPClassFile
}
#Edit Class File
Function Edit-SCOMMPClass
{
While($True) {
[int]$xMenuChoiceA = 0
while ( $xMenuChoiceA -lt 1 -or $xMenuChoiceA -gt 4 ){
Write-host "1. Create New Class"
Write-host "2. Create New Property"
Write-Host "3. Create Run As Account"
Write-Host "4. Exit"
[Int]$xMenuChoiceA = read-host "Please enter an option 1 to 4..." }
Switch( $xMenuChoiceA ){
1{Write-Host ""; Add-SCOMMPClass -MPClassFile $MPClassFile; Write-Host ""}
2{Write-Host ""; Add-SCOMMPClassProperty -MPClassFile $MPClassFile; Write-Host ""}
3{Write-Host ""; Add-SCOMMPRunAsAccount -MPClassFile $MPClassFile; Write-Host ""}
4{Return}
}
}
}
Function New-SCOMMPDiscovery
{
Param (
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$MPDiscoveryFile = $(Read-Host -Prompt "Where will the discovery file be saved")
)
# Wrties variable values which are specific to Visual Studios
$IncludeFileContent = "$" + "IncludeFileContent"
$MPElement = "$" + "MPElement"
$Target = "$" + "Target"
# Writes the XML structure of the Discovery
Add-Content $MPDiscoveryFile "<ManagementPackFragment SchemaVersion=""2.0"" xmlns:xsd="" `n" id="1320591599">http://www.w3.org/2001/XMLSchema"">`n
<Monitoring>`n <Discoveries>`n <Category>Discovery</Category>`n <DiscoveryTypes>`n </DiscoveryTypes>`n </DataSource>`n </Discovery>`n </Discoveries>`n </Monitoring>`n <LanguagePacks>`n <LanguagePack ID=""ENU"" IsDefault=""true"">`n <DisplayStrings>`n </DisplayStrings>`n </LanguagePack>`n </LanguagePacks>`n</ManagementPackFragment>"
}
Function Add-SCOMMPPowerShellDiscovery
{
Param (
[String]$DiscoveryName = $(Read-Host -Prompt "Name of Discovery"),
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$DiscoveryDescription = $(Read-Host -Prompt "Description of discovery"),
[String]$DiscoveryClass = $(Read-Host -Prompt "Discovery Class"),
[String]$DiscoveryRunAsAccount = $(Read-Host -Prompt "Discovery RunAs Account"),
[String]$IntervalSeconds = $(Read-Host -Prompt "Interval Seconds"),
[Parameter(Mandatory=$false)][String]$SyncTime = $(Read-Host -Prompt "Sync Time. Leave blank if not needed"),
[String]$ScriptName = $(Read-Host -Prompt "Script Name"),
[String]$ScriptBody = $(Read-Host -Prompt "Script Body"),
[String]$TimeoutSeconds = $(Read-Host -Prompt "Timeout Seconds"),
[String]$MPClassFile = $(Read-Host -Prompt "Where the Class file is located"),
[String]$MPDiscoveryFile = $(Read-Host -Prompt "Where will the discovery file be saved"),
[String]$ClassID = (Read-Host -Prompt "ClassID used in previously created class")
)
# Wrties variable values which are specific to Visual Studios
$Target = "$" + "Target"
$Data = "$" + "Data"
$MPElement = "$" + "MPElement"
$IncludeFileContent = "$" + "IncludeFileContent"
#$ClassID = $ClassID -replace " ", "."
# Formats the Secure Reference Name to the relevant format for the XML to handle the Secure Reference name
$DiscoveryID = $DiscoveryName -replace " ", "."
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery ID to the XML Management Pack
$FindCategoryLine = Select-String $MPDiscoveryFile -pattern "<Category>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindCategoryLine] += "`n <Discovery ID=""$DiscoveryName"" Target=""$DiscoveryTarget"" Enabled=""true"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPDiscoveryFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$DiscoveryID"">`n <Name>$DiscoveryName</Name>`n <Description>$DiscoveryDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery Class
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DiscoveryClass TypeID=""$DiscoveryClass"">`n </DiscoveryClass>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Retrieves the details for the Class created previously
$MPClassContent = Get-Content $MPClassFile
# Finds all of the properties which were created from that particular class by searching the class.xml file
$FindProperties = ((Get-Content $MPClassFile) -match "<DisplayString ElementID=""$ClassID"" SubElementID") -replace "<DisplayString ElementID=""$ClassID"" SubElementID", "<Property PropertyID" -replace ">", " />"
# Adds all of the properties which were discovered in the Class previously created to the Discovery Class
$FindDiscoveryClassLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryClass" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryClassLine] += "`n $FindProperties"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Edits the DataSource line to prepare for it being a PowerShell Discovery
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DataSource ID=""DS"" TypeID=""Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider"" RunAs=""$DiscoveryRunAsAccount"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Adds the PowerShell Discovery Configuration to the XML
$FindDataSourceLine = Select-String $MPDiscoveryFile -pattern "<DataSource" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDataSourceLine] += "`n <IntervalSeconds>$IntervalSeconds</IntervalSeconds>`n <SyncTime>$SyncTime</SyncTime>`n <ScriptName>$ScriptName</ScriptName>`n <ScriptBody>$IncludeFileContent/$ScriptBody$</ScriptBody>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
#Writes the PowerShell Script Parameters
$FindScriptBodyLine = Select-String $MPDiscoveryFile -pattern "<ScriptBody>" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindScriptBodyLine] += "`n <Parameters>`n <Parameter>`n <Name>sourceID</Name>`n <Value>$MPElement$</Value>`n </Parameter>`n <Parameter>`n <Name>managedEntityID</Name>`n <Value>$Target/Id$</Value>`n </Parameter>`n <Parameter>`n <Name>computerName</Name>`n <Value>$Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Value>`n </Parameter>`n </Parameters>`n <TimeoutSeconds>$TimeoutSeconds</TimeoutSeconds>"
$ClassContent | Set-Content $MPDiscoveryFile
}
Function Add-SCOMMPRegistryDiscovery
{
Param (
[String]$DiscoveryName = $(Read-Host -Prompt "Name of Discovery"),
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$DiscoveryDescription = $(Read-Host -Prompt "Description of discovery"),
[String]$DiscoveryClass = $(Read-Host -Prompt "Discovery Class"),
[String]$DiscoveryRunAsAccount = $(Read-Host -Prompt "Discovery RunAs Account"),
[String]$Frequency = $(Read-Host -Prompt "Frequency (seconds)"),
[String]$MPClassFile = $(Read-Host -Prompt "Where the Class file is located"),
[String]$MPDiscoveryFile = $(Read-Host -Prompt "Where will the discovery file be saved"),
[String]$ClassID = (Read-Host -Prompt "ClassID used in previously created class")
)
# Wrties variable values which are specific to Visual Studios
$Target = "$" + "Target"
$MPElement = "$" + "MPElement"
$ClassContent = Get-Content $MPDiscoveryFile
$DiscoveryID = $DiscoveryName -replace " ", "."
# Writes the Discovery ID to the XML Management Pack
$FindCategoryLine = Select-String $MPDiscoveryFile -pattern "<Category>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindCategoryLine] += "`n <Discovery ID=""$DiscoveryName"" Target=""$DiscoveryTarget"" Enabled=""true"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPDiscoveryFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$DiscoveryID"">`n <Name>$DiscoveryName</Name>`n <Description>$DiscoveryDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery Class
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DiscoveryClass TypeID=""$DiscoveryClass"">`n </DiscoveryClass>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Retrieves the details for the Class created previously
$MPClassContent = Get-Content $MPClassFile
# Finds all of the properties which were created from that particular class by searching the class.xml file
$FindProperties = ((Get-Content $MPClassFile) -match "<DisplayString ElementID=""$ClassID"" SubElementID") -replace "<DisplayString ElementID=""$ClassID"" SubElementID", "<Property PropertyID" -replace ">", " />"
# Adds all of the properties which were discovered in the Class previously created to the Discovery Class
$FindDiscoveryClassLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryClass" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryClassLine] += "`n $FindProperties"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Edits the DataSource line to prepare for it being a PowerShell Discovery
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DataSource ID=""DS"" TypeID=""Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider"" RunAs=""$DiscoveryRunAsAccount"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Adds the Registry Discovery Configuration to the XML
$FindDataSourceLine = Select-String $MPDiscoveryFile -pattern "<DataSource" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDataSourceLine] += "`n <ComputerName>$Target/Property[Type=""$DiscoveryTarget""]/NetworkName$</ComputerName>`n <RegistryAttributeDefinitions>`n </RegistryAttributeDefinitions>`n <Frequency>$Frequency</Frequency>`n <ClassId>$MPElement[Name=""$ClassID""]$</ClassId>`n <InstanceSettings>`n <Settings>`n <Setting>`n <Name>$MPElement[Name=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Name>`n <Value>$Target/Property[Type=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Value>`n </Setting>`n </Settings>`n </InstanceSettings>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
}
Function Add-SCOMMPRegistryKey
{
Param (
[String]$AttributeName = $(Read-Host -Prompt "Name of Property to discover"),
[String]$RegistryPath = $(Read-Host -Prompt "Registry path of property? Prefixed with HKLM"),
[String]$PathType = $(Read-Host -Prompt "Path Type i.e. 0 - to check Key Exists, 1 - Key value to be retrieved "),
[String]$AttributeType = $(Read-Host -Prompt "Attribute Type i.e. 0 - Boolean, 1- String, 2 - Integer, 3 - Float"),
[String]$ClassID = $(Read-Host -Prompt "ClassID which this will point to")
)
# Reloads the Class XML file with the new changes
$Data = "$" + "Data"
$ClassContent = Get-Content $MPDiscoveryFile
# Write Registry Key Attribute
$FindRegistryAttributeDefinitionLine = Select-String $MPDiscoveryFile -pattern "</RegistryAttributeDefinitions>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindRegistryAttributeDefinitionLine] += "`n <RegistryAttributeDefinition>`n <AttributeName>$AttributeName</AttributeName>`n <Path>$RegistryPath</Path>`n <PathType>$PathType</PathType>`n <AttributeType>$AttributeType</AttributeType>`n </RegistryAttributeDefinition>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Write Instance Value
$FindSettingsLine = Select-String $MPDiscoveryFile -pattern "</Settings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindSettingsLine] += "`n <Setting>`n <Name>$MPElement[Name=""$ClassID""]/$AttributeName$</Name>`n <Value>$Data/Values/$AttributeName$</Value>`n </Setting>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
}
Function Edit-SCOMMPAddRegistry
{
While($True) {
[int]$xMenuChoiceA = 0
while ( $xMenuChoiceA -lt 1 -or $xMenuChoiceA -gt 2 ){
Write-host "1. Add Registry Attribute"
Write-host "2. Exit"
[Int]$xMenuChoiceA = read-host "Please enter an option 1 to 2..."
}
Switch( $xMenuChoiceA ){
1{Add-SCOMMPRegistryKey -ClassID $ClassID}
2{Return}
}
}
}
Function Add-SCOMMPWMIDiscovery
{
Param (
[String]$DiscoveryName = $(Read-Host -Prompt "Name of Discovery"),
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$DiscoveryDescription = $(Read-Host -Prompt "Description of discovery"),
[String]$DiscoveryClass = $(Read-Host -Prompt "Discovery Class"),
[String]$Namespace = $(Read-Host -Prompt "Namespace to connect to"),
[String]$Query = $(Read-Host -Prompt "Type the WMI query to use"),
[String]$Frequency = $(Read-Host -Prompt "Frequency (seconds)"),
[String]$ClassID = $(Read-Host -Prompt "ClassID which this will point to")
)
# Reloads the Class XML file with the new changes
$Target = "$" + "Target"
$MPElement = "$" + "MPElement"
$Data = "$" + "Data"
$DiscoveryID = $DiscoveryName -replace " ", ""
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery ID to the XML Management Pack
$FindCategoryLine = Select-String $MPDiscoveryFile -pattern "<Category>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindCategoryLine] += "`n <Discovery ID=""$DiscoveryName"" Target=""$DiscoveryTarget"" Enabled=""true"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPDiscoveryFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$DiscoveryID"">`n <Name>$DiscoveryName</Name>`n <Description>$DiscoveryDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery Class
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DiscoveryClass TypeID=""$DiscoveryClass"">`n </DiscoveryClass>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Retrieves the details for the Class created previously
$MPClassContent = Get-Content $MPClassFile
# Finds all of the properties which were created from that particular class by searching the class.xml file
$FindProperties = ((Get-Content $MPClassFile) -match "<DisplayString ElementID=""$ClassID"" SubElementID") -replace "<DisplayString ElementID=""$ClassID"" SubElementID", "<Property PropertyID" -replace ">", " />"
# Adds all of the properties which were discovered in the Class previously created to the Discovery Class
$FindDiscoveryClassLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryClass" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryClassLine] += "`n $FindProperties"
$ClassContent | Set-Content $MPDiscoveryFile
# Edits the DataSource line to prepare for it being a WMI Discovery
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DataSource ID=""DS"" TypeID=""Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper"" RunAs=""$DiscoveryRunAsAccount"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Adds the WMI Discovery Configuration to the XML
$FindDataSourceLine = Select-String $MPDiscoveryFile -pattern "<DataSource" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDataSourceLine] += "`n <NameSpace>$NameSpace</NameSpace>`n <Query>$Query</Query>`n <Frequency>$Frequency</Frequency>`n <ClassID>$MPElement[Name=""$ClassID""]$</ClassID>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
#Writes the WMI Parameters
$FindClassIDLine = Select-String $MPDiscoveryFile -pattern "<ClassID>" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindClassIDLine] += "`n <InstanceSettings>`n <Settings>`n <Setting>`n <Name>$MPElement[Name=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Name>`n <Value>$Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Value>`n </Setting>`n <Setting>`n <Name>$MPElement[Name=""System!System.Entity""]/DisplayName$</Name>`n <Value>$Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Value>`n </Setting>`n </Settings>`n </InstanceSettings>"
$ClassContent | Set-Content $MPDiscoveryFile
}
Function Add-SCOMMPVBScriptDiscovery
{
Param (
[String]$ClassID = $(Read-Host -Prompt "ClassID"),
[String]$DiscoveryName = $(Read-Host -Prompt "Name of Discovery"),
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$DiscoveryDescription = $(Read-Host -Prompt "Description of discovery"),
[String]$DiscoveryClass = $(Read-Host -Prompt "Discovery Class"),
[String]$DiscoveryRunAsAccount = $(Read-Host -Prompt "Discovery Run As Account"),
[String]$IntervalSeconds = $(Read-Host -Prompt "Interval Seconds"),
[Parameter(Mandatory=$false)][String]$SyncTime = $(Read-Host -Prompt "Sync Time"),
[String]$MPClassFile = $(Read-Host -Prompt "MP Class File"),
[String]$MPDiscoveryFile = $(Read-Host -Prompt "MP Discovery File"),
[String]$ScriptName = $(Read-Host -Prompt "Script Name"),
[String]$ScriptBody = $(Read-Host -Prompt "Script Body"),
[String]$TimeoutSeconds = $(Read-Host -Prompt "Timeout Seconds")
)
# Reloads the Class XML file with the new changes
$Target = "$" + "Target"
$MPElement = "$" + "MPElement"
$Data = "$" + "Data"
$DiscoveryID = $DiscoveryName -replace " ", ""
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery ID to the XML Management Pack
$FindCategoryLine = Select-String $MPDiscoveryFile -pattern "<Category>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindCategoryLine] += "`n <Discovery ID=""$DiscoveryName"" Target=""$DiscoveryTarget"" Enabled=""true"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPDiscoveryFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$DiscoveryID"">`n <Name>$DiscoveryName</Name>`n <Description>$DiscoveryDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the Discovery Class
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DiscoveryClass TypeID=""$DiscoveryClass"">`n </DiscoveryClass>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Retrieves the details for the Class created previously
$MPClassContent = Get-Content $MPClassFile
# Finds all of the properties which were created from that particular class by searching the class.xml file
$FindProperties = ((Get-Content $MPClassFile) -match "<DisplayString ElementID=""$ClassID"" SubElementID") -replace "<DisplayString ElementID=""$ClassID"" SubElementID", "<Property PropertyID" -replace ">", " />"
# Adds all of the properties which were discovered in the Class previously created to the Discovery Class
$FindDiscoveryClassLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryClass" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveryClassLine] += "`n $FindProperties"
$ClassContent | Set-Content $MPDiscoveryFile
# Edits the DataSource line to prepare for it being a WMI Discovery
$FindDiscoveryTypesLine = Select-String $MPDiscoveryFile -pattern "</DiscoveryTypes" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDiscoveryTypesLine] += "`n <DataSource ID=""DS"" TypeID=""Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper"" RunAs=""$DiscoveryRunAsAccount"">"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Adds the VBScript Discovery Configuration to the XML
$FindDataSourceLine = Select-String $MPDiscoveryFile -pattern "<DataSource" | ForEach-Object {$_.LineNumber -1}
$ClassContent[$FindDataSourceLine] += "`n <IntervalSeconds>$IntervalSeconds</IntervalSeconds>`n <SyncTime>$SyncTime</SyncTime>`n <ScriptName>$ScriptName</ScriptName>`n <Arguments>$MPElement$ $Target/Id$ $Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Arguments>`n <ScriptBody>$IncludeFileContent/$ScriptBody$</ScriptBody>`n <TimeoutSeconds>$TimeoutSeconds</TimeoutSeconds>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
#Writes the VBScript Parameters
#$FindClassIDLine = Select-String $MPDiscoveryFile -pattern "<ClassID>" | ForEach-Object {$_.LineNumber -1}
#$ClassContent[$FindClassIDLine] += "`n <InstanceSettings>`n <Settings>`n <Setting>`n <Name>$MPElement[Name=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Name>`n <Value>$Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/PrincipalName$</Value>`n <Parameter>`n <Name>managedEntityID</Name>`n <Value>$Target/Id$</Value>`n </Parameter>`n <Parameter>`n <Name>computerName</Name>`n <Value>$Target/Host/Property[Type=""$DiscoveryTarget""]/PrincipalName$</Value>`n </Parameter>`n </Parameters>`n <TimeoutSeconds>$TimeoutSeconds</TimeoutSeconds>"
#$ClassContent | Set-Content $MPDiscoveryFile
}
Function Add-SCOMMPComputerGroupDiscovery
{
Param (
[String]$DiscoveryName = $(Read-Host -Prompt "Name of Discovery"),
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$DiscoveryDescription = $(Read-Host -Prompt "Description of discovery"),
[String]$ClassID = $(Read-Host -Prompt "ClassID which this will point to"),
[String]$MPDiscoveryFile = $(Read-Host -Prompt "Where will the discovery file be saved")
)
# Reloads the Class XML file with the new changes
$MPElement = "$" + "MPElement"
$DiscoveryID = ""
$ClassContent = Get-Content $MPDiscoveryFile
# Write Computer Group Discovery
$FindDiscoveriesLine = Select-String $MPDiscoveryFile -pattern "</Discoveries>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveriesLine] += "`n <Discovery ID=""$DiscoveryName"" Target=""$DiscoveryTarget"" Enabled=""false"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"">`n <Category>Discovery</Category>`n <DiscoveryTypes />`n <DataSource ID=""DS"" TypeID=""SC!Microsoft.SystemCenter.GroupPopulator"">`n <RuleId>$MPElement$</RuleId>`n <GroupInstanceId>$MPElement[Name=""$DiscoveryName""]$</GroupInstanceId>`n <MembershipRules>`n <MembershipRule>`n <MonitoringClass>$MPElement[Name=""Windows!Microsoft.Windows.Computer""]$</MonitoringClass>`n <RelationshipClass>$MPElement[Name=""SC!Microsoft.SystemCenter.ComputerGroupContainsComputer""]$</RelationshipClass>`n <Expression>`n <Contains>`n <MonitoringClass>$MPElement[Name=""$ClassID""]$</MonitoringClass>`n </Contains>`n </Expression>`n </MembershipRule>`n </MembershipRules>`n </DataSource>`n </Discovery>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPDiscoveryFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$DiscoveryName"">`n <Name>$DiscoveryName</Name>`n <Description>$DiscoveryDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
}
Function Add-SCOMMPInstanceGroupDiscovery
{
Param (
[String]$DiscoveryName = $(Read-Host -Prompt "Name of Discovery"),
[String]$DiscoveryTarget = $(Read-Host -Prompt "Class ID which discovery is targeted to"),
[String]$DiscoveryDescription = $(Read-Host -Prompt "Description of discovery"),
[String]$ClassID = $(Read-Host -Prompt "ClassID which this will point to"),
[String]$MPDiscoveryFile = $(Read-Host -Prompt "Where will the discovery file be saved")
)
# Reloads the Class XML file with the new changes
$MPElement = "$" + "MPElement"
$ClassContent = Get-Content $MPDiscoveryFile
# Write Computer Group Discovery
$FindDiscoveriesLine = Select-String $MPDiscoveryFile -pattern "</Discoveries>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindDiscoveriesLine] += "`n <Discovery ID=""$DiscoveryName"" Target=""$DiscoveryTarget"" Enabled=""false"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"">`n <Category>Discovery</Category>`n <DiscoveryTypes />`n <DataSource ID=""DS"" TypeID=""SC!Microsoft.SystemCenter.GroupPopulator"">`n <RuleId>$MPElement$</RuleId>`n <GroupInstanceId>$MPElement[Name=""$DiscoveryName""]$</GroupInstanceId>`n <MembershipRules>`n <MembershipRule>`n <MonitoringClass>$MPElement[Name=""Windows!Microsoft.Windows.Computer""]$</MonitoringClass>`n <RelationshipClass>$MPElement[Name=""SCIG!Microsoft.SystemCenter.InstanceGroupContainsEntities""]$</RelationshipClass>`n <Expression>`n <Contains>`n <MonitoringClass>$MPElement[Name=""$ClassID""]$</MonitoringClass>`n </Contains>`n </Expression>`n </MembershipRule>`n </MembershipRules>`n </DataSource>`n </Discovery>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPDiscoveryFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$DiscoveryName"">`n <Name>$DiscoveryName</Name>`n <Description>$DiscoveryDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPDiscoveryFile
# Reloads the Class XML file with the new changes
$ClassContent = Get-Content $MPDiscoveryFile
}
Function Create-PowerShellScript
{
Param (
[String]$ScriptName = (Read-Host -Prompt "Script Name"),
[String]$MPClassFile = (Read-Host -Prompt "Class file created previously to use script to discover")
)
# Wrties variable values which are specific to Visual Studios
$Instance = "$" + "instance"
$SourceID = "$" + "sourceid"
$ManagedEntityId = "$" + "managedEntityId"
$Computername = "$" + "computerName"
$api = "$" + "api"
$discoveryData = "$" + "discoveryData"
# Writes the PowerShell Discovery script logic
Add-Content $ScriptName "param($sourceId,$managedEntityId,$computerName)`n `n$api = new-object -comObject 'MOM.ScriptAPI'`n$discoveryData = $api.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)"
Add-Content $ScriptName "`n$Instance = $discoveryData.CreateClassInstance(""$MPElement[Name='$ClassID']$"")`n$instance.AddProperty(""$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$"", $computerName) "
Add-Content $ScriptName "`n <Insert Script Here>"
ForEach ($line in $PropertiesDetection) {Add-Content $ScriptName "`n$Instance.AddProperty(""$MPElement[Name='$ClassID']/$line$,#Add Variable Here to Discovery this property#"")"}
Add-Content $ScriptName "`n$discoveryData.AddInstance($instance)"
Add-Content $ScriptName "`n$discoveryData"
Write-Host "Edit the PowerShell script to contain your script portion for the discovery. Start from under the $Discoverydata line" -ForegroundColor Yellow
Write-Host "The Script will contain the properties lines. Make sure you add the variable next to the "\," and comments character to assure that the property will be discovered by your script portion" -ForegroundColor Yellow
}
Function Create-VBScript
{
Param (
[String]$ScriptName = (Read-Host -Prompt "Script Name"),
[String]$MPClassFile = (Read-Host -Prompt "Class file created previously to use script to discover")
)
# Wrties variable values which are specific to Visual Studios
$Instance = "$" + "instance"
$SourceID = "$" + "sourceid"
$ManagedEntityId = "$" + "managedEntityId"
$Computername = "$" + "computerName"
$api = "$" + "api"
$discoveryData = "$" + "discoveryData"
$MPElement = "$" + "MPElement"
# Write VBScript
Add-Content $ScriptName "SourceId = WScript.Arguments(0)"
Add-Content $ScriptName "ManagedEntityId = WScript.Arguments(1)"
Add-Content $ScriptName "sComputerName = WScript.Arguments(2)"
Add-Content $ScriptName "`nSet oAPI = CreateObject(""MOM.ScriptAPI"")"
Add-Content $ScriptName "Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)"
Add-Content $ScriptName "`nFor i = 1 to 3"
Add-Content $ScriptName "Set oInstance = oDiscoveryData.CreateClassInstance (""$MPElement[Name='$ClassID']$"") "
Add-Content $ScriptName "oInstance.AddProperty ""$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$"", sComputerName"
ForEach ($line in $PropertiesDetection) {Add-Content $ScriptName "oInstance.AddProperty ""$MPElement[Name='$ClassID']/$line$"","}
Write-Host "Edit the VB script to contain your script portion for the discovery. Start from under the Discoverydata line" -ForegroundColor Yellow
Write-Host "The Script will contain the properties lines. Make sure you add the variable next to the "\," and comments character to assure that the property will be discovered by your script portion" -ForegroundColor Yellow
}
Function New-SCOMMPView
{
Param (
[String]$MPViewFile = $(Read-Host -Prompt "Where the View File will be created")
)
Add-Content $MPViewFile "<ManagementPackFragment SchemaVersion=""2.0"" xmlns:xsd="" `n" id="1375652192">http://www.w3.org/2001/XMLSchema"">`n
<Presentation>`n <Views>`n </Views>`n <FolderItems>`n </FolderItems>`n </Presentation>`n <LanguagePacks>`n <LanguagePack ID=""ENU"" IsDefault=""true"">`n <DisplayStrings>`n </DisplayStrings>`n </LanguagePack>`n </LanguagePacks>`n</ManagementPackFragment>"
}
Function Add-SCOMMPView
{
Param (
[String]$ViewName = $(Read-Host -Prompt "Name of view"),
[String]$ViewID = $(Read-Host -Prompt "Name of viewID"),
[String]$ViewTarget = $(Read-Host -Prompt "Which class will the view display"),
[String]$ViewType = $(Read-Host -Prompt "Type of view to create"),
[String]$FolderID = $(Read-Host -Prompt "Folder where the view will be added"),
[String]$MPViewFile = $(Read-Host -Prompt "Where the View File will be created")
)
# Sets ViewType
If ($ViewType -eq "StateView") {$ViewType = "SC!Microsoft.SystemCenter.StateViewType"}
If ($ViewType -eq "AlertView") {$ViewType = "SC!Microsoft.SystemCenter.AlertViewType"}
If ($ViewType -eq "EventView") {$ViewType = "SC!Microsoft.SystemCenter.EventViewType"}
If ($ViewType -eq "OverridesSummaryView") {$ViewType = "SC!Microsoft.SystemCenter.OverridesSummaryViewType"}
# Wrties variable values which are specific to Visual Studios
#$ViewID = $ViewName -replace " ", "."
$ClassContent = Get-Content $MPViewFile
$ViewTarget = $ViewTarget -replace " ", "."
# Writes the view XML to the management pack
$FindViewsline = Select-String $MPViewFile -pattern "</views>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindViewsline] += "`n <View ID=""$ViewID"" Accessibility=""Internal"" Target=""$ViewTarget"" TypeID=""$ViewType"" Visible=""true"">`n <Category>Operations</Category>`n </View>"
$ClassContent | Set-Content $MPViewFile
# Reload content
$ClassContent = Get-Content $MPViewFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPViewFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$ViewID"">`n <Name>$ViewName</Name>`n <Description>$ViewDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPViewFile
#Reload content
$ClassContent = Get-Content $MPViewFile
# Writes the View to be placed in a specific folder
$FindFolderItemsLine = Select-String $MPViewFile -pattern "</FolderItems>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindFolderItemsLine] += "`n <FolderItem ElementID=""$ViewID"" Folder=""$FolderID"" ID=""$ViewID.folderitem"" />"
$ClassContent | Set-Content $MPViewFile
}
Function New-SCOMMPFolder
{
Param (
[String]$MPFolderFile = $(Read-Host -Prompt "Where the folder File will be created")
)
Add-Content $MPFolderFile "<ManagementPackFragment SchemaVersion=""2.0"" xmlns:xsd="" `n" id="1493969780">http://www.w3.org/2001/XMLSchema"">`n
<Presentation>`n <Folders>`n </Folders>`n <FolderItems>`n </FolderItems>`n </Presentation>`n <LanguagePacks>`n <LanguagePack ID=""ENU"" IsDefault=""true"">`n <DisplayStrings>`n </DisplayStrings>`n </LanguagePack>`n </LanguagePacks>`n</ManagementPackFragment>"
}
Function Add-SCOMMPFolder
{
Param (
[String]$FolderName = $(Read-Host -Prompt "Name of folder"),
[String]$FolderID = $(Read-Host -Prompt "Name of folderID"),
[String]$FolderParent = $(Read-Host -Prompt "Where will the folder be"),
[String]$MPFolderFile = $(Read-Host -Prompt "Where the folder File will be created")
)
# Sets Folder Parent
If ($FolderParent -eq "Root") {$FolderParent = "SC!Microsoft.SystemCenter.Monitoring.ViewFolder.Root"}
# Wrties variable values which are specific to Visual Studios
#$FolderID = $FolderName -replace " ", "."
$ClassContent = Get-Content $MPFolderFile
# Writes the Folder XML to the management pack
$FindFoldersline = Select-String $MPFolderFile -pattern "</Folders>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindFoldersline] += "`n <Folder ID=""$FolderID"" Accessibility=""Internal"" ParentFolder=""$FolderParent"" />"
$ClassContent | Set-Content $MPFolderFile
#Reload content
$ClassContent = Get-Content $MPFolderFile
# Writes the DisplayStrings to the XML so SCOM can read the display names correctly
$FindLastDisplayStringLine = Select-String $MPFolderFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$FolderID"">`n <Name>$FolderName</Name>`n <Description>$FolderDescription</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPFolderFile
}
Function Edit-SCOMMPViewsFolders
{
While($True) {
[int]$xMenuChoiceA = 0
while ( $xMenuChoiceA -lt 1 -or $xMenuChoiceA -gt 3 ){
Write-host "1. Create New View"
Write-host "2. Create New Folder"
Write-Host "3. Exit"
[Int]$xMenuChoiceA = read-host "Please enter an option 1 to 4..." }
Switch( $xMenuChoiceA ){
1{Write-Host "The following classes have been detected" -ForegroundColor Green
Write-Host $ClassesDetectionAdd-SCOMMPView -MPViewFile $MPViewFile}
2{Add-SCOMMPFolder -MPFolderFile $MPFolderFile
$FolderDetection = ((Get-Content $MPFolderFile) -match "<DisplayString ElementID" -notmatch "SubElementID") -replace "<DisplayString ElementID=""", "" -replace """", "" -replace ">", ""
Write-Host "The following folders have been detected which you can use to decide where to add views to" -ForegroundColor Green
Write-Host $FolderDetection
}
3{Return}
}
}
}
Function New-SCOMMPMonitorRule
{
Param (
[String]$MPMonitorRuleFile = $(Read-Host -Prompt "Where will the xml file be saved")
)
Add-Content $MPMonitorRuleFile "<ManagementPackFragment SchemaVersion=""2.0"" xmlns:xsd="" `n" id="1206996623">http://www.w3.org/2001/XMLSchema"">`n
<Monitoring>`n <Rules>`n </Rules>`n <Monitors>`n </Monitors>`n</Monitoring>`n <Presentation>`n <StringResources>`n </StringResources>`n </Presentation>`n <LanguagePacks>`n <LanguagePack ID=""ENU"" IsDefault=""true"">`n <DisplayStrings>`n </DisplayStrings>`n </LanguagePack>`n </LanguagePacks>`n</ManagementPackFragment>"
}
Function Add-SCOMMPWindowsEventMonitor
{
Param (
[String]$MonitorName = $(Read-Host -Prompt "Name of the Monitor"),
[String]$MonitorEnabled = $(Read-Host -Prompt "Is the Monitor enabled (true or false in lowercase)"),
[String]$MonitorTarget = $(Read-Host -Prompt "Monitor target"),
##[String]$MonitorType = $(Read-Host -Prompt "Monitor type"),
[String]$MonitorRunAsAccount = $(Read-Host -Prompt "Run As Account for monitor"),
[String]$AlertOnState = $(Read-Host -Prompt "What health status should the monitor alert on? Error or Warning"),
[String]$AlertPriority = $(Read-Host -Prompt "Alert Priority - High, Normal or Low"),
[String]$AlertSeverity = $(Read-Host -Prompt "Alert Severity (Error or Warning)"),
[String]$AlertMessage = $(Read-Host -Prompt "Alert message"),
[String]$UnhealthyLogName = $(Read-Host -Prompt "Name of Unhealthy Event log"),
##[String]$UnhealthyOperatorLogName = $(Read-Host -Prompt "How should the Unhealthy LogName be discovered"),
[String]$UnhealthyEventDisplayNumber = $(Read-Host -Prompt "Unhealthy EventID Number"),
##[String]$UnhealthyOperatorEventDisplayNumber = $(Read-Host -Prompt "How should the Unhealthy Event Display Number be discovered"),
[String]$UnhealthyPublisherName = $(Read-Host -Prompt "Name of Unhealthy Source"),
##[String]$UnhealthyOperatorPublisherName = $(Read-Host -Prompt "How should the Unhealthy Publisher name be discovered"),
##[String]$AlertSupression1 = $(Read-Host -Prompt "Which parameter should be used to identify duplicate alerts"),
##[String]$AlertSupression2 = $(Read-Host -Prompt "Which parameter should be used to identify duplicate alerts"),
[String]$HealthyLogName = $(Read-Host -Prompt "Name of healthy Event log"),
##[String]$HealthyOperatorLogName = $(Read-Host -Prompt "How should the healthy LogName be discovered"),
[String]$HealthyEventDisplayNumber = $(Read-Host -Prompt "healthy EventID Number"),
##[String]$HealthyOperatorEventDisplayNumber = $(Read-Host -Prompt "How should the healthy Event Display Number be discovered"),
[String]$HealthyPublisherName = $(Read-Host -Prompt "Name of healthy Source"),
##[String]$HealthyOperatorPublisherName = $(Read-Host -Prompt "How should the healthy Publisher name be discovered"),
[String]$MPMonitorRuleFile = $(Read-Host -Prompt "Where will the xml file be saved")
)
# Sets Monitor Target
If ($MonitorTarget -eq "WindowsComputer") {$MonitorTarget = "Windows!Microsoft.Windows.ComputerRole"}
If ($MonitorTarget -eq "WindowsApplicationComponent") {$MonitorTarget = "Windows!Microsoft.Windows.ApplicationComponent"}
If ($MonitorTarget -eq "WindowsLocalApplication") {$MonitorTarget = "Windows!Microsoft.Windows.LocalApplication"}
If ($MonitorTarget -eq "UnixComputer") {$MonitorTarget = "Unix!Microsoft.Unix.ComputerRole"}
If ($MonitorTarget -eq "ComputerGroup") {$MonitorTarget = "SC!Microsoft.SystemCenter.ComputerGroup"}
If ($MonitorTarget -eq "InstanceGroup") {$MonitorTarget = "SCIG!Microsoft.SystemCenter.InstanceGroup"}
# Wrties variable values which are specific to Visual Studios
$Target = "$" + "Target"
$Data = "$" + "Data"
$ClassContent = Get-Content $MPMonitorRuleFile
$MonitorID = $MonitorName -replace " ", "."
$AlertMessageID = "$MonitorID.AlertMessage"
# Write Monitor
$FindMonitorsLine = Select-String $MPMonitorRuleFile -pattern "</Monitors>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindMonitorsLine] += "`n <UnitMonitor ID=""$MonitorID"" Accessibility=""Internal"" Enabled=""$MonitorEnabled"" Target=""$MonitorTarget"" ParentMonitorID=""Health!System.Health.AvailabilityState"" Remotable=""true"" Priority=""Normal"" TypeID=""Windows!Microsoft.Windows.2SingleEventLog2StateMonitorType"" ConfirmDelivery=""false"" RunAs=""$MonitorRunAsAccount"">`n <Category>AvailabilityHealth</Category>`n <AlertSettings AlertMessage=""$AlertMessageID"">`n <AlertOnState>$AlertOnState</AlertOnState>`n <AutoResolve>true</AutoResolve>`n <AlertPriority>$AlertPriority</AlertPriority>`n <AlertSeverity>MatchMonitorHealth</AlertSeverity>`n <AlertParameters>`n <AlertParameter1>$Data/Context/EventDescription$</AlertParameter1>`n </AlertParameters>`n </AlertSettings>`n <OperationalStates>`n <OperationalState ID=""FirstEventRaised"" MonitorTypeStateID=""FirstEventRaised"" HealthState=""$AlertSeverity"" />`n <OperationalState ID=""SecondEventRaised"" MonitorTypeStateID=""SecondEventRaised"" HealthState=""Success"" />`n </OperationalStates>`n <Configuration>`n <FirstComputerName>$Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/NetworkName$</FirstComputerName>`n <FirstLogName>$UnhealthyLogName</FirstLogName>`n <FirstExpression>`n <And>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery Type=""UnsignedInteger"">EventDisplayNumber</XPathQuery> `n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value Type=""UnsignedInteger"">$UnhealthyEventDisplayNumber</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery Type=""String"">PublisherName</XPathQuery>`n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value Type=""String"">$UnhealthyPublisherName</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n <Expression>`n </Expression>`n </And>`n </FirstExpression>`n <SecondComputerName>$Target/Host/Property[Type=""Windows!Microsoft.Windows.Computer""]/NetworkName$</SecondComputerName>`n <SecondLogName>$HealthyLogName</SecondLogName>`n <SecondExpression>`n <And>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery Type=""UnsignedInteger"">EventDisplayNumber</XPathQuery>`n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value Type=""UnsignedInteger"">$HealthyEventDisplayNumber</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery Type=""String"">PublisherName</XPathQuery>`n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value Type=""String"">$HealthyPublisherName</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n <Expression>`n </Expression>`n </And>`n </SecondExpression>`n </Configuration>`n </UnitMonitor>"
$ClassContent | Set-Content $MPMonitorRuleFile
# Reload XML File
$ClassContent = Get-Content $MPMonitorRuleFile
# Write String Resources
$FindStringResourcesLine = Select-String $MPMonitorRuleFile -pattern "</StringResources>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindStringResourcesLine] += "`n<StringResource ID=""$AlertMessageID"" />"
$ClassContent | Set-Content $MPMonitorRuleFile
# Reload XML File$
$ClassContent = Get-Content $MPMonitorRuleFile
# Write display strings
$FindLastDisplayStringLine = Select-String $MPMonitorRuleFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$MonitorID"">`n <Name>$MonitorName</Name>`n <Description>$MonitorDescription</Description>`n </DisplayString>`n <DisplayString ElementID=""$AlertMessageID"">`n <Name>$AlertMessageID</Name>`n <Description>$AlertMessage</Description>`n </DisplayString>`n <DisplayString ElementID=""$MonitorID"" SubElementID=""FirstEventRaised"">`n <Name>FirstEventRaised</Name>`n <Description>FirstEventRaised</Description>`n </DisplayString>`n <DisplayString ElementID=""$MonitorID"" SubElementID=""SecondEventRaised"">`n <Name>SecondEventRaised</Name>`n <Description>SecondEventRaised</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPMonitorRuleFile
}
Function Add-SCOMMPWindowsEventRule
{
Param (
[String]$RuleName = $(Read-Host -Prompt "Name of the Rule"),
[String]$RuleEnabled = $(Read-Host -Prompt "Is the rule enabled"),
[String]$RuleTarget = $(Read-Host -Prompt "Rule target"),
##[String]$RuleType = $(Read-Host -Prompt "Rule type"),
[String]$RuleRunAsAccount = $(Read-Host -Prompt "Run As Account for rule"),
[String]$LogName = $(Read-Host -Prompt "Name of Event log"),
[String]$EventDisplayNumber = $(Read-Host -Prompt "EventID Number"),
[String]$PublisherName = $(Read-Host -Prompt "Name of Source"),
[String]$AlertMessage = $(Read-Host -Prompt "Alert message"),
[String]$Priority = $(Read-Host -Prompt "Priority Level (1 = high, 2 = Normal, 3 = Low"),
[String]$Severity = $(Read-Host -Prompt "Severity Level (1 = Critical, 2 = Warning, 3 = Information"),
[String]$MPMonitorRuleFile = $(Read-Host -Prompt "Where will the xml file be saved")
)
# Sets Monitor Target
If ($RuleTarget -eq "WindowsComputer") {$RuleTarget = "Windows!Microsoft.Windows.ComputerRole"}
If ($RuleTarget -eq "WindowsApplicationComponent") {$RuleTarget = "Windows!Microsoft.Windows.ApplicationComponent"}
If ($RuleTarget -eq "WindowsLocalApplication") {$RuleTarget = "Windows!Microsoft.Windows.LocalApplication"}
If ($RuleTarget -eq "UnixComputer") {$RuleTarget = "Unix!Microsoft.Unix.ComputerRole"}
If ($RuleTarget -eq "ComputerGroup") {$RuleTarget = "SC!Microsoft.SystemCenter.ComputerGroup"}
If ($RuleTarget -eq "InstanceGroup") {$RuleTarget = "SCIG!Microsoft.SystemCenter.InstanceGroup"}
# Wrties variable values which are specific to Visual Studios
$Data = "$" + "Data"
$MPElement = "$" + "MPElement"
$RuleID = $RuleName -replace " ", "."
$AlertMessageID = "$MonitorID.AlertMessage"
$ClassContent = Get-Content $MPMonitorRuleFile
# Write Rule
$FindRulesLine = Select-String $MPMonitorRuleFile -pattern "</Rules>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindRulesLine] += "`n <Rule ID=""$RuleID"" Target=""$RuleTarget"" Enabled=""$RuleEnabled"" ConfirmDelivery=""false"" Remotable=""true"" Priority=""Normal"" DiscardLevel=""100"">`n <Category>Alert</Category>`n <DataSources>`n <DataSource ID=""DS"" TypeID=""Windows!Microsoft.Windows.EventProvider"" RunAs=""$RuleRunAsAccount"">`n <LogName>$LogName</LogName>`n <Expression>`n <And>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery>Channel</XPathQuery>`n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value>$LogName</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery>EventDisplayNumber</XPathQuery>`n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value>$EventDisplayNumber</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n <Expression>`n <SimpleExpression>`n <ValueExpression>`n <XPathQuery>PublisherName</XPathQuery>`n </ValueExpression>`n <Operator>Equal</Operator>`n <ValueExpression>`n <Value>$PublisherName</Value>`n </ValueExpression>`n </SimpleExpression>`n </Expression>`n </And>`n </Expression>`n </DataSource>`n </DataSources>`n <ConditionDetection ID=""CD"" TypeID=""System!System.ExpressionFilter"" RunAs=""$RuleRunAsAccount"">`n <Expression>`n <RegExExpression>`n <ValueExpression>`n <XPathQuery>PublisherName</XPathQuery>`n </ValueExpression>`n <Operator>MatchesRegularExpression</Operator>`n <Pattern>$PublisherName</Pattern>`n </RegExExpression>`n </Expression>`n </ConditionDetection>`n <WriteActions>`n <WriteAction ID=""Alert"" TypeID=""Health!System.Health.GenerateAlert"">`n <Priority>$Priority</Priority>`n <Severity>$Severity</Severity>`n <AlertMessageId>$MPElement[Name=""$AlertMessageID""]$</AlertMessageId>`n <AlertParameters>`n <AlertParameter1>$Data/EventDescription$</AlertParameter1>`n </AlertParameters>`n <Suppression>`n <SuppressionValue>$Data/EventDescription$</SuppressionValue>`n </Suppression>`n </WriteAction>`n </WriteActions>`n </Rule>"
$ClassContent | Set-Content $MPMonitorRuleFile
# Reload XML File
$ClassContent = Get-Content $MPMonitorRuleFile
# Write String Resources
$FindStringResourcesLine = Select-String $MPMonitorRuleFile -pattern "</StringResources>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindStringResourcesLine] += "`n<StringResource ID=""$AlertMessageID"" />"
$ClassContent | Set-Content $MPMonitorRuleFile
# Reload XML File
$ClassContent = Get-Content $MPMonitorRuleFile
# Write display strings
$FindLastDisplayStringLine = Select-String $MPMonitorRuleFile -pattern "</DisplayStrings>" | ForEach-Object {$_.LineNumber -2}
$ClassContent[$FindLastDisplayStringLine] += "`n <DisplayString ElementID=""$MonitorID"">`n <Name>$MonitorName</Name>`n <Description>$MonitorDescription</Description>`n </DisplayString>`n <DisplayString ElementID=""$AlertMessageID"">`n <Name>$AlertMessageID</Name>`n <Description>$AlertMessage</Description>`n </DisplayString>"
$ClassContent | Set-Content $MPMonitorRuleFile
}
Function Edit-SCOMMPMonitorRule
{
While($True) {
[int]$xMenuChoiceA = 0
while ( $xMenuChoiceA -lt 1 -or $xMenuChoiceA -gt 3 ){
Write-host "1. Add Windows Event Monitor"
Write-host "2. Add Windows Event Rule"
Write-Host "3. Exit"
[Int]$xMenuChoiceA = read-host "Please enter an option 1 to 3..."
}
Switch( $xMenuChoiceA ){
1{Add-SCOMMPWindowsEventMonitor -MPMonitorRuleFile $MPMonitorRuleFile}
2{Add-SCOMMPWindowsEventRule -MPMonitorRuleFile $MPMonitorRuleFile}
3{Return}
}
}
}
#Function New-SCOMMPRule
#Function Edit-SCOMMPDiscovery
#Function Edit-SCOMMPMonitor
#Function Edit-SCOMMPRule
#####################################################################################################################################
#Create SCOM Management Pack
# Questions to create SCOM Management Pack
cls
Write-Host "SCOM Managament Pack Creation Script" -ForegroundColor Green
Write-Host ""
Write-Host "There will be a series of questions to help build the management pack and will output seperate files for you to copy the XML code and add into Visual Studios" -ForegroundColor Green
Write-Host ""
Write-Host "Note: If creating an Instance Group make sure that you add the SystemCenter.InstanceGroup.Library management pack to your references in Visual Studios and change the alias name to SCIG" -ForegroundColor Yellow
Write-Host ""
Write-Host ""
$ManagementPackName = Read-Host "Name of Management Pack"
$PlatformType = Read-Host "Which platform is the Management Pack based on? Windows or Unix"
If ($PlatformType -eq "Windows") {$PlatformType = "Windows!Microsoft.Windows.ComputerRole"}
ElseIf ($PlatformType -eq "Unix") {$PlatformType = "Unix!Microsoft.Unix.ComputerRole"}
Else
{Write-Host "Invalid answer. Please run script again and choose an appropriate Platform Type" -ForegroundColor Red; break}
$DiscoveryMethod = Read-Host "How the SCOM Objects will be discovered? PowerShell,Registry, WMI or VBScript"
If ($DiscoveryMethod -eq "PowerShell") {$DiscoveryMethod = "Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider"}
ElseIf ($DiscoveryMethod -eq "Registry") {$DiscoveryMethod = "Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider"}
ElseIf ($DiscoveryMethod -eq "WMI") {$DiscoveryMethod = "Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper"}
ElseIf ($DiscoveryMethod -eq "VBScript") {$DiscoveryMethod = "Windows!Microsoft.Windows.TimedScript.DiscoveryProvider"}
Else
{Write-Host "Invalid answer. Please run script again and choose an appropriate DiscoveryMethod" -ForegroundColor Red; break}
$FileLocation = Read-Host "Where will the files be saved"
Write-Host Management Pack Name will be $ManagementPackName
Write-Host Location of the XML files will be placed in $FileLocation
$Proceed = Read-Host "OK to Proceed with Management Pack creation?"
If ($Proceed -eq "No") {break}
###################################################################################################################################
# Create Class File
cls
Write-Host "Writing Class file for management pack" -ForegroundColor Green
$MPClassFile = "$FileLocation\$ManagementPackName.class.xml"
New-SCOMMPClass -MPClassFile $MPClassFile
$MPClassFileExists = Get-Item $MPClassFile
If ($MPClassFileExists -ne $null) {Write-Host "Class file successfully created" -ForegroundColor Yellow}
Write-Host ""
Write-Host "Now you will be asked to add your Classes and Properties" -ForegroundColor Yellow
Edit-SCOMMPClass
$ClassesDetection = ((Get-Content $MPClassFile) -match "<DisplayString ElementID" -notmatch "SubElementID") -replace "<DisplayString ElementID=""", "" -replace """", "" -replace ">", ""
Write-Host ""
Write-Host "The following classes have been detected" -ForegroundColor Green
Write-Host $ClassesDetection
Write-Host ""
$ClassIDPropertyExtract = Read-Host "Which class do you wish to extract properties from?"
$PropertiesDetection = ((Get-Content $MPClassFile) -match "<DisplayString ElementID=""$ClassIDPropertyExtract"" SubElementID") -replace "<DisplayString ElementID=""$ClassIDPropertyExtract"" SubElementID=""","" -replace """", "" -replace ">", ""
$PropertiesDetection = $PropertiesDetection.trim()
$RunAsAccount = ((Get-Content $MPClassFile) -match "<DisplayString ElementID" -match "Account") -replace "<DisplayString ElementID=""", "" -replace """", "" -replace ">", ""
$RunAsAccount = $RunAsAccount.trim()
Write-Host ""
Write-Host "The following classes have been detected" -ForegroundColor Green
Write-Host $ClassesDetection
Write-Host ""
$ClassID = Read-Host "Which class do you wish to create a discovery for"
$ClassName = $ClassID -replace ".", " "
$ComputerGroupCreation = Read-Host "Do you wish to create a ComptuerGroup?"
If ($ComputerGroupCreation -eq "Yes")
{Add-SCOMMPClass -MPClassFile $MPClassFile -ClassName "$ClassID.ComputerGroup" -ClassType ComputerGroup -ClassDescription "Computer group for $ClassID" -Abstract "false" -Hosted "false" -Singleton "true"}
$InstanceGroupCreation = Read-Host "Do you wish to create a InstanceGroup?"
If ($InstanceGroupCreation -eq "Yes")
{Add-SCOMMPClass -MPClassFile $MPClassFile -ClassName "$ClassID.InstanceGroup" -ClassType InstanceGroup -ClassDescription "Instance group for $ClassID" -Abstract "false" -Hosted "false" -Singleton "true"}
# Manual creation of class and properties. Just remove # from lines below and put a hash on the Edit-SCOMMPClass command
#Add-SCOMMPClass -ClassName "" -ClassType "" -ClassDescription "" -MPClassFile $MPClassFile
#Add-SCOMMPClassProperty -PropertyName "" -PropertyType "" -PropertyDescription "" -AffectedClassID "" -MPClassFile $MPClassFile
#Add-SCOMMPRunAsAccount -SecureReferenceName "" -SecureReferenceDescription "" -MPClassFile $MPClassFile
####################################################################################################################################
# Create Discovery File
Write-Host ""
Write-Host "Writing Discovery file for management pack" -ForegroundColor Green
$MPDiscoveryFile = "$FileLocation\$ManagementPackName.Discovery.xml"
New-SCOMMPDiscovery -MPDiscoveryFile $MPDiscoveryFile -DiscoveryTarget $PlatformType
$MPDiscoveryFileExists = Get-Item $MPDiscoveryFile
If ($MPDiscoveryFileExists -ne $null) {Write-Host "Discovery file successfully created" -ForegroundColor Yellow}
If ($DiscoveryMethod -eq "Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider") {
Add-SCOMMPPowerShellDiscovery -MPClassFile $MPClassFile -MPDiscoveryFile $MPDiscoveryFile -ClassID $ClassID -DiscoveryName "$ClassID.Discovery" -DiscoveryClass $ClassID -ScriptName "$ClassID.Discovery.ps1" -ScriptBody "$ClassID.Discovery.ps1" -DiscoveryRunAsAccount $RunAsAccount -DiscoveryTarget "Windows!Microsoft.Windows.ComputerRole"
Create-PowerShellScript -ScriptName "$FileLocation\$ClassID.Discovery.ps1" -MPClassFile $MPClassFile
}
If ($DiscoveryMethod -eq "Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider") {
Add-SCOMMPRegistryDiscovery -MPClassFile $MPClassFile -MPDiscoveryFile $MPDiscoveryFile -ClassID $ClassID -DiscoveryName "$ClassID.Discovery" -DiscoveryClass $ClassID -DiscoveryRunAsAccount $RunAsAccount -DiscoveryTarget $PlatformType
Write-Host ""
Write-Host "The following propeties have been detected which can be used as Attribute Name" -ForegroundColor Green
Write-Host ""
Write-Host $PropertiesDetection
Write-Host ""
Edit-SCOMMPAddRegistry
}
If ($DiscoveryMethod -eq "Windows!Microsoft.Windows.TimedScript.DiscoveryProvider") {
Add-SCOMMPVBScriptDiscovery -MPClassFile $MPClassFile -MPDiscoveryFile $MPDiscoveryFile -ClassID $ClassID -DiscoveryName "$ClassID.Discovery" -DiscoveryClass $ClassID -ScriptName "$ClassID.Discovery.ps1" -ScriptBody "$ClassID.Discovery.ps1" -DiscoveryRunAsAccount $RunAsAccount -DiscoveryTarget "Windows!Microsoft.Windows.ComputerRole"
Create-VBScript -ScriptName "$FileLocation\$ClassID.Discovery.vbs" -MPClassFile $MPClassFile
}
If ($DiscoveryMethod -eq "Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper") {
Add-SCOMMPWMIDiscovery -MPClassFile $MPClassFile -MPDiscoveryFile $MPDiscoveryFile -ClassID $ClassID -DiscoveryName "$ClassID.Discovery" -DiscoveryClass $ClassID -ScriptName "$ClassID.Discovery.ps1" -ScriptBody "$ClassID.Discovery.ps1" -DiscoveryRunAsAccount $RunAsAccount -DiscoveryTarget "Windows!Microsoft.Windows.ComputerRole"
}
If ($ComputerGroupCreation -eq "Yes")
{Add-SCOMMPComputerGroupDiscovery -MPDiscoveryFile $MPDiscoveryFile -DiscoveryName "$ClassID.ComputerGroupDiscovery" -DiscoveryTarget $PlatformType -ClassID $ClassID -DiscoveryDescription "Computer group for $ClassID"}
If ($InstanceGroupCreation -eq "Yes")
{Add-SCOMMPInstanceGroupDiscovery -MPDiscoveryFile $MPDiscoveryFile -DiscoveryName "$ClassID.InstanceGroupDiscovery" -DiscoveryTarget $PlatformType -ClassID $ClassID -DiscoveryDescription "Computer group for $ClassID"}
#Add-SCOMMPPowerShellDiscovery -DiscoveryName DWJ.Citrix.Computer.Discovery -DiscoveryTarget Windows!Microsoft.Windows.ComputerRole -DiscoveryDescription Test -DiscoveryClass DWJ.Citrix.Computer -DiscoveryRunAsAccount DWJ.Citrix.Action.Account -IntervalSeconds 300 -SyncTime 0 -ScriptName DWJCitrixComputerDiscovery.ps1 -ScriptBody DWJCitrixComputerDiscovery.ps1 -TimeoutSeconds 300 -MPClassFile C:\Temp\DWJCitrixClass.xml -MPDiscoveryFile $MPDiscoveryFile -ClassID DWJ.Citrix.Computer
########################################################################################################################################
# Create Folder File
Write-Host ""
Write-Host "Writing Folder file for management pack" -ForegroundColor Green
$MPFolderFile = "$FileLocation\$ManagementPackName.Folder.xml"
New-SCOMMPFolder -MPFolderFile $MPFolderFile
$MPFolderFileExists = Get-Item $MPFolderFile
If ($MPFolderFileExists -ne $null) {Write-Host "Folder file successfully created" -ForegroundColor Yellow}
Add-SCOMMPFolder -MPFolderFile $MPFolderFile -FolderID "$ClassID.Folder" -FolderName $ManagementPackName -FolderParent Root
#######################################################################################################################################
# Create View File
Write-Host ""
Write-Host "Writing view file for management pack" -ForegroundColor Green
$MPViewFile = "$FileLocation\$ManagementPackName.View.xml"
New-SCOMMPView -MPViewFile $MPViewFile
$MPViewFileExists = Get-Item $MPViewFile
If ($MPViewFileExists -ne $null) {Write-Host "View file successfully created" -ForegroundColor Yellow}
Add-SCOMMPView -MPViewFile $MPViewFile -ViewID "$ClassID.View" -FolderID "$ClassID.Folder"
###############################################################################################################################################
# Oppourtunity to add more to management packs
$AddViewsorFolders = Read-Host "Do you wish to add more views or folders"
If ($AddViewsorFolders -eq "Yes")
{Edit-SCOMMPViewsFolders}
$AddMonitorsorRules = Read-Host "Do you wish to add monitors or rules"
If ($AddMonitorsorRules -eq "Yes")
{ Write-Host ""
Write-Host "Writing Monitor & Rules file for management pack" -ForegroundColor Green
$MPMonitorRuleFile = "$FileLocation\$ManagementPackName.MonitorRules.xml"
New-SCOMMPMonitorRule -MPMonitorRuleFile $MPMonitorRuleFile
$MPMonitorRuleFileExists = Get-Item $MPMonitorRuleFile}
If ($MPMonitorRuleFileExists -ne $null) {Write-Host "Monitor & Rules successfully created" -ForegroundColor Yellow}
Edit-SCOMMPMonitorRule
###############################################################################################################################################
# Management Pack Creation Completed
Write-Host ""
Write-Host "Management Pack is now created. Please create a visual studios project and copy the information from the files created from this script" -ForegroundColor Green



