Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Wednesday, February 28, 2018

SCCM: Copy product categories from WSUS to SUP

For a project where Patch Management was migrated from WSUS to SCCM (SUP with new WSUS) i needed to create a list of product categories and sync them with the categories in SCCM.

This script retrieves a list of selected product categories from an WSUS server and searches for the corresponding category on your Software Update Point. It then will enable the subscription for this specific category.

As a precaution you have to change the scanOnly variable to actually enable this/

Before all this, the script will first create a backup of your current selected categories and export it to a timestamped CSV file.

#requirements

  • SCCM console installed
  • WSUS console installed 


Script


Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" # Import the ConfigurationManager.psd1 module 
$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-Location "$($SiteCode.Name):\"

$supCatBackupPath = "C:\SCCM_SUP_Subscribed_ProductCategories_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$onlyScan = $true #Change this to $False if you are sure to change the Software Update Point categories.

#get current selected SUP categories
$subscribedCats = Get-CMSoftwareUpdateCategory -Fast | ? { $_.IsSubscribed -And $_.CategoryTypeName -eq "ProductFamily" -Or $_.CategoryTypeName -eq "Product" }
#backup to CSV file
$subscribedCats | Export-CSV -Path $supCatBackupPath -Delimiter ";" 

$wsusserver = "myWSUSserver"
$wsusport = 8530

[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | Out-Null
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False,$wsusport)
$wsusSubscription = $wsus.GetSubscription()
$selectedProducts = $wsusSubscription.GetUpdateCategories() | Select Title
$selectedProducts

$selectedProducts.Title | % { 
    $_
    $supCat = Get-CMSoftwareUpdateCategory -Fast -Name "$_"
    if($supCat.IsSubscribed -eq $False) {
        Write-Host -ForegroundColor Red "Not subscribed"
        if($onlyScan -eq $False) {
            $supCat.IsSubscribed = $true
            $supCat.Put()
        } else {
            Write-Host "scan only, not changing..."
        }
    } else {
        Write-Host "Already subscribed"
    }
}

Thursday, January 18, 2018

SCCM - Download Software Updates with PowerShell

After you setup your new SCCM environment, it can be time consuming to download all Software Updates and place them in the right deployment package. This is an example of how you could automate that with PowerShell. It will download all software updates contained in the given Software Update Group and will save and download them to an already created deployment package.
$sugDeployment = "Deployment Group - 2017 - Microsoft Updates - Non-OS"
$dpkg = "Deployment Package - 2017 - Microsoft Updates - Non-OS"
$supLanguages = @("English","Dutch")
Get-CMSoftwareUpdateGroup -Name $sugDeployment | Save-CMSoftwareUpdate -DeploymentPackageName $dpkg -Verbose -SoftwareUpdateLanguage $supLanguages
Creating a deployment package with PowerShell is also possible, but remember you need to create the path on the filesystem yourself.

Thursday, December 14, 2017

PowerShell: Encapsulate 64 bit cmdlet in a 32 bit context

Found a rather old but nice tip from Neil Peterson to tackle a challenge executing Powershell 64 bit cmdlets from a 32 bit execution context (Orchestrator in his example). Just wanted to share this and add it to my own blog for enhancing my toolbox.
#living in a 32 bit universe

#starting PowerShell 'sysnative' version and thus 64 bit
#more info: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx

$ClusterNodes = .$env:windir\sysnative\WindowsPowerShell\v1.0\powershell.exe {

 #living in a 64 bit universe
 Get-ClusterNode -Cluster clustername

}

Monday, July 3, 2017

SCOM: Using [bracket] NoteProperties in PowerShell

What are those brackets [] in PowerShell!!?? When you query class instances, you'll see a numer of properties available of the type 'NoteProperty'. Direct or inherited from parent classes. To use or filter on these class instance properties in PowerShell, you need to use a specific syntax.

 You either enclose with single quotes or escape with backtick. In this example i'm using an instance of the 'Windows Server' class from one of the default SCOM management packs. This class inherits the property 'IPAddress' from the base class 'Windows Computer'.

 Here are the useable options for PowerShell:
#Get all available properties
Get-SCOMClass -DisplayName "Windows Server" | Get-SCOMClassInstance | Get-Member
...
[Microsoft.Windows.Computer].ActiveDirectoryObjectSid
[Microsoft.Windows.Computer].ActiveDirectorySite
[Microsoft.Windows.Computer].DNSName
[Microsoft.Windows.Computer].DomainDnsName
[Microsoft.Windows.Computer].ForestDnsName
[Microsoft.Windows.Computer].HostServerName
[Microsoft.Windows.Computer].IPAddress
[Microsoft.Windows.Computer].IsVirtualMachine
[Microsoft.Windows.Computer].LastInventoryDate
[Microsoft.Windows.Computer].LogicalProcessors
[Microsoft.Windows.Computer].NetbiosComputerName
[Microsoft.Windows.Computer].NetbiosDomainName
[Microsoft.Windows.Computer].NetworkName
[Microsoft.Windows.Computer].OffsetInMinuteFromGreenwichTime
[Microsoft.Windows.Computer].OrganizationalUnit
[Microsoft.Windows.Computer].PhysicalProcessors
[Microsoft.Windows.Computer].PrincipalName
[Microsoft.Windows.Computer].VirtualMachineName
...

#
# Using a NoteProperty
# ** Where-Object / ForEach-Object clause **

{ $_.'[Microsoft.Windows.Computer].IPAddress'.Value }

# ** Select-Object **
Select-Object ``[Microsoft.Windows.Computer`].IPAddress
Select-Object *.IPAddress

# ** Change column name or object property name **
# Looks like the syntax for Where-Object, but 'Value' subproperty is not specified!
Select-Object @{Expression={$_.'[Microsoft.Windows.Computer].IPAddress'};Label="IP"}

Wednesday, September 28, 2016

SCCM: Using Cmdlets from SCCM PowerShell Module

If you want to use PowerShell with SCCM, you can do two things.
  • Load the PowerShell through the SCCM Console (left top corner: Connect via Windows PowerShell)
  • Load the PowerShell module manually
When you use the manual method, the SCCM PS drive should be loaded automatically.
import-module($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + '\ConfigurationManager.psd1')

You can verify this with the command Get-PSDrive command
Get-PSDrive -PSProvider CMSite

When the CMSite PowerShell Drive is not available, you can create it yourself and connect to the SCCM site. The only parameter you need is the name of the Site Server which hosts the SMS Provider. This is usually the Primary Site Server.
How to add the CMSite PSDrive manually:
New-PSDrive -Name "SCCM" -PSProvider CMSite -Root "<SCCM_SERVER>"
cd SCCM:
Of course you can use whatever name you want.

More info:
http://www.hasmug.com/2016/04/25/easily-document-configmgr-client-settings-with-powershell/ (thanks for the csv function!)
http://www.verboon.info/2013/05/powershell-script-to-retrieve-sccm-2012-client-settings/
https://blogs.technet.microsoft.com/enterprisemobility/2013/03/27/powershell-connecting-to-configuration-manager/

Monday, May 30, 2016

SCOM: View Folder Path hierarchy (PowerShell)

So we're six years older and still there was a small thing that I still had not fixed. It concerned the full view folder path of a SCOM Monitoring View.

In the past I wrote numerous PowerShell scripts which involved the views. Now I finally found some time to create a function to get the folder hierarchy of a given View by it's ID (guid).
Why I never thought about solving it like this, i don't know, but it appeared to be not that hard. It's a simple recursive function.

In the future I'll update the existing scripts concerning the User Scopes and will also upload a nice script which shows a complete report about all the dependancies between Management Packs and their objects used in User Roles and Notifications. This comes in handy, when you want to phase out management packs but don't know whether there are User Roles and Notification Subscriptions involved.

Enjoy.

  • $computerName should have a name of a valid Management Server
  • $viewId needs to have a valid guid of an existing view in your SCOM environment.
New-SCOMManagementGroupConnection -ComputerName $computerName
$mg = Get-SCOMManagementGroup

function GetFolderHierarchy($folderId,$folderpath) {

    $parentfolderid = $null
    $tmpfolder = $mg.GetMonitoringFolder($folderId)   
    $tmpfolderdisplayname = $tmpfolder.DisplayName

    if ($folderpath -eq "" -Or $folderpath -eq $null) {
        $folderpath = $tmpfolderdisplayname
    } else {
        $folderpath = $tmpfolderdisplayname + "\" + $folderpath
    }

    $parentfolderid = $tmpfolder.ParentFolder.id.Guid

    if ($parentfolderid -ne "" -And $parentfolderid -ne $null -And $tmpfolder.name -ne "Microsoft.SystemCenter.Monitoring.ViewFolder.Root") {
        GetFolderHierarchy $parentfolderid $folderpath
    } else { 
        return $folderpath
    }

}

function GetViewHierarchy($viewId) { 

    $tmpview = $mg.GetMonitoringView($viewId)
    $parentfolderid = $tmpview.ParentFolderIds.Guid | Select -First 1
    if($parentfolderid -ne "" -And $parentfolderid -ne $null) {
        $fullpath = GetFolderHierarchy $parentfolderid
        return $fullpath + "\" + $tmpview.DisplayName
    }    
}

GetViewHierarchy $viewId

Wednesday, March 23, 2016

SCOM: Compare MP's between Management Groups with PowerShell

A short blog post about comparing management packs between SCOM environments I know there are tools available to compare management packs, but that's no fun. Creating this compare script with PowerShell to accomplish the same didn't cost me that much time. And of course, doing it yourself with PowerShell is just more fun. So here it is.

This script gives you a gridview with the differences, as well as an CSV output file.
#Compares unsealed/sealed MP's between two management groups
#Author: Michiel Wouters
#Date: 23-03-2016

[CmdletBinding()]
Param(
   [Parameter(Mandatory=$False)]
   [string]$ms1="server1", # A management server of the source environment, default value
   
   [Parameter(Mandatory=$False)]
   [string]$ms2="server2", # A management server of the target environment, default value

   [Parameter(Mandatory=$False)]
   [boolean]$Sealed=$True
  
)

New-SCOMManagementGroupConnection -ComputerName $ms1
$mmgtgrpconn1 = Get-SCOMManagementGroupConnection -ComputerName $ms1

New-SCOMManagementGroupConnection -ComputerName $ms2
$mmgtgrpconn2 = Get-SCOMManagementGroupConnection -ComputerName $ms2

Set-SCOMManagementGroupConnection -Connection $mmgtgrpconn1
$mgmtgrp1mps = Get-SCOMManagementPack | ? {$_.Sealed -eq $Sealed} | Select DisplayName, Name, Version | Sort DisplayName

Set-SCOMManagementGroupConnection -Connection $mmgtgrpconn2
$mgmtgrp2mps = Get-SCOMManagementPack | ? {$_.Sealed -eq $Sealed} | Select DisplayName, Name, Version | Sort DisplayName


#set SynWindow for compare object
if($mgmtgrp2mps.Count -gt $mgmtgrp1mps.count) { 
    $SyncWindow = [math]::Ceiling($mgmtgrp2mps.Count/2)
}  else { 
    $SyncWindow = [math]::Ceiling($mgmtgrp1mps.Count/2)
}

$comparison = Compare-Object -ReferenceObject $mgmtgrp1mps -DifferenceObject $mgmtgrp2mps -Property DisplayName, Name, Version -SyncWindow $SyncWindow | Sort DisplayName
#output to screen
$comparison | Out-GridView
#output to csv file
$comparison | Export-CSV -Path .\SCOM_MPDiff_$(Get-Date -Format "yyyyMMdd_HHmm").csv -NoTypeInformation -Delimiter ";"

Screenshots:



Tuesday, November 11, 2014

Powershell: Searching for special characters? Get them all!

Today I wanted to see if I could add a checkbox like character to a custom table from Powershell.

Because of the nature of a command line script, I wanted to see if there were any interesting character codes to do this.
In Powershell you can use specific characters with the command [char]#.

You can use this command line to output all characters from a specific range (default is 0-10000). Have fun!
for($i=0;$i -le 10000;$i++){Write-Host -NoNewLine "$i $([char]$i) "; $k++ ; if($k -ge 15){Write-Host "";$k=0}}

Output looks like this:
9819 ♛ 9820 ♜ 9821 ♝ 9822 ♞ 9823 ♟ 9824 ♠ 9825 ♡ 9826 ♢ 9827 ♣ 9828 ♤ 9829 ♥ 9830 ♦ 9831 ♧ 9832 ♨ 9833 ♩ 
9834 ♪ 9835 ♫ 9836 ♬ 9837 ♭ 9838 ♮ 9839 ♯ 9840 ♰ 9841 ♱ 9842 ♲ 9843 ♳ 9844 ♴ 9845 ♵ 9846 ♶ 9847 ♷ 9848 ♸ 
9849 ♹ 9850 ♺ 9851 ♻ 9852 ♼ 9853 ♽ 9854 ♾ 9855 ♿ 9856 ⚀ 9857 ⚁ 9858 ⚂ 9859 ⚃ 9860 ⚄ 9861 ⚅ 9862 ⚆ 9863 ⚇ 
9864 ⚈ 9865 ⚉ 9866 ⚊ 9867 ⚋ 9868 ⚌ 9869 ⚍ 9870 ⚎ 9871 ⚏ 9872 ⚐ 9873 ⚑ 9874 ⚒ 9875 ⚓ 9876 ⚔ 9877 ⚕ 9878 ⚖ 
9879 ⚗ 9880 ⚘ 9881 ⚙ 9882 ⚚ 9883 ⚛ 9884 ⚜ 9885 ⚝ 9886 ⚞ 9887 ⚟ 9888 ⚠ 9889 ⚡ 9890 ⚢ 9891 ⚣ 9892 ⚤ 9893 ⚥ 
9894 ⚦ 9895 ⚧ 9896 ⚨ 9897 ⚩ 9898 ⚪ 9899 ⚫ 9900 ⚬ 9901 ⚭ 9902 ⚮ 9903 ⚯ 9904 ⚰ 9905 ⚱ 9906 ⚲ 9907 ⚳ 9908 ⚴ 
9909 ⚵ 9910 ⚶ 9911 ⚷ 9912 ⚸ 9913 ⚹ 9914 ⚺ 9915 ⚻ 9916 ⚼ 9917 ⚽ 9918 ⚾ 9919 ⚿ 9920 ⛀ 9921 ⛁ 9922 ⛂ 9923 ⛃ 
9924 ⛄ 9925 ⛅ 9926 ⛆ 9927 ⛇ 9928 ⛈ 9929 ⛉ 9930 ⛊ 9931 ⛋ 9932 ⛌ 9933 ⛍ 9934 ⛎ 9935 ⛏ 9936 ⛐ 9937 ⛑ 9938 ⛒ 
9939 ⛓ 9940 ⛔ 9941 ⛕ 9942 ⛖ 9943 ⛗ 9944 ⛘ 9945 ⛙ 9946 ⛚ 9947 ⛛ 9948 ⛜ 9949 ⛝ 9950 ⛞ 9951 ⛟ 9952 ⛠ 9953 ⛡ 
9954 ⛢ 9955 ⛣ 9956 ⛤ 9957 ⛥ 9958 ⛦ 9959 ⛧ 9960 ⛨ 9961 ⛩ 9962 ⛪ 9963 ⛫ 9964 ⛬ 9965 ⛭ 9966 ⛮ 9967 ⛯ 9968 ⛰ 
9969 ⛱ 9970 ⛲ 9971 ⛳ 9972 ⛴ 9973 ⛵ 9974 ⛶ 9975 ⛷ 9976 ⛸ 9977 ⛹ 9978 ⛺ 9979 ⛻ 9980 ⛼ 9981 ⛽ 9982 ⛾ 9983 ⛿ 
9984 ✀ 9985 ✁ 9986 ✂ 9987 ✃ 9988 ✄ 9989 ✅ 9990 ✆ 9991 ✇ 9992 ✈ 9993 ✉ 9994 ✊ 9995 ✋ 9996 ✌ 9997 ✍ 9998 ✎ 
9999 ✏ 10000 ✐

Tuesday, May 22, 2012

Powershell: Split text file in multiple files

For importing computer entries in SCCM I had a rather big file with 35000 items in it. I wanted to take a phased approach and found a script to split the CSV file based on a number of lines per file. Script Center repository: http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Split-large-log-6f2c4da0

I tweaked the script a little bit, so only the parameters that are necessary are File Name and Number of Lines Per File.

$linecount = 0
$filenumber = 1

$sourcefilename = Read-Host "What is the full path and name of the log file to split? (e.g. D:\mylogfiles\mylog.txt) "
$destinationfolderpath = Split-Path $sourcefilename -parent

$srcfile = gci $sourcefilename
$filebasename = $srcfile.BaseName
$fileext = $srcfile.Extension

Get-Content $sourcefilename | Measure-Object | ForEach-Object { $sourcelinecount = $_.Count }

Write-Host "Your current file size is $sourcelinecount lines long"

$destinationfilesize = Read-Host "How many lines will be in each new split file? "

$maxsize = [int]$destinationfilesize
 
Write-Host File is $sourcefilename - destination is $destinationfolderpath - new file line count will be $destinationfilesize

Write-Host "Writing part: $destinationfolderpath\$filebasename`_part$filenumber$fileext"
$content = get-content $sourcefilename | % {
 #Add-Content $destinationfolderpath\$filebasename_$filenumber.txt "$_"
 Add-Content $destinationfolderpath\$filebasename`_part$filenumber$fileext "$_"
  $linecount ++
  If ($linecount -eq $maxsize) {
    $filenumber++
    $linecount = 0
    Write-Host "Writing part: $destinationfolderpath\$filebasename`_part$filenumber$fileext"
  }
}

Wednesday, May 25, 2011

SCOM: Get Overrides from Management Pack

Here's an example of how to retrieve all overrides from a specific management pack and get additional information about the overriden rule and override context.

Get-ManagementPack | Where {$_.DisplayName -match "Your Management Pack"} | Get-Override | % {Get-Rule -Id $_.Rule.Id | Select DisplayName
; Get-MonitoringClass -Id $_.Context.Id; Write-Host $_.Parameter: $_.Value}
To manage all your overrides you could use a tool like OverrideExplorer.

Thursday, February 17, 2011

SCOM: Account specified in the Run As Profile cannot be resolved - Troubleshooting using SSID

Update for SCOM 2012: SCOM 2012 does have a cmdlet for getting RunAs profiles: Get-SCOMRunAsProfile. As one of the commenters below added, if you want to get the SSID's in SCOM 2012, then use the cmdlet 'Get-SCOMRunAsAccount'.
Get-SCOMRunAsAccount | Sort Name | % {$string = $null;$_.SecureStorageId | % { 
 $string = $string + "{0:X2}" -f $_}
 $_.Name;" $string"
}

Written for SCOM 2007...
Update:
#Don't forget to add the OM2007 snapin
add-PsSnapIn "Microsoft.EnterpriseManagement.OperationsManager.Client" 
New-ManagementGroupConnection -ConnectionString:"scommssrv"
set-location "OperationsManagerMonitoring::" 

Some management packs require configuration of Run As Profiles.
This means that you configure associations between classes/objects and Run As Accounts. Whenever a workflow from a management pack is instructed to use a Run As Profile it will only work when the targeted class or object of the workflow is associated with an account. And last but not least, the Run As Account should be distributed to the servers on which that class exists.

This blogs shows you some tips on how to troubleshoot alerts associated with these kind of things.

When you misconfigure the Run As Profile, the following alert can popup in your console:
Account specified in the Run As Profile ">RunasAccountProfile<" cannot be resolved.

With some extra info:

Management Group: ###
Run As Profile: Company.Product.Role.Application.ActionAccountProfile
Account SSID: 0025F224C5251A6F4EEE112ACD9F0EB07D9178AFB500000000000000000000000000000000000000


This alert tells you that you associated the runas account, but the agent that tries to use the account, did not actually receive the account credentials.
So either you add the server to the distribution list, or you reconfigure the runas profile associations with beter classes/objects.

But he! I can't find the specified Run As Profile 'Company.Product.Role.Application.ActionAccountProfile'. That's right. That's the Name property shown in the description. If you want to find the Run As Profile as it's showed in the Operations Console, you will need the DisplayName. For that we could use the Operations Manager Shell:
Get-RunAsProfile ... oh, that cmdlet does not exist :(

What more does the alert message say? This is interesting:
Note: you may use the command shell to get the Run As Account display name by its SSID"

We could use the SSID from the alert message. The Ops Mgr Shell does have a cmdlet for showing the Run As Accounts.
The only problem we have here, is that the SSID mentioned in the alert description is a string type value. Cmdlet Get-RunAsAccount shows us that the SSID is stored as a byte array in the property SecureStorageId. So we can't compare these types.

For that i've created this script. It gets all Run As Account, formats the byte array SecureStorageId property to a readable string, and show the Run As Account DisplayName with it's SSID.
Get-RunAsAccount | Sort Name | % {$string = $null;$_.SecureStorageId | % { 
 $string = $string + "{0:X2}" -f $_}
 $_.Name;"  $string"
}

PowerShell does not have built-in functions for formatting numbers, therefore you can use the .Net formatting methods.

With this in mind you could add a string comparison to only show a match when the Alert Message SSID correspands with the SecureStorageId string ($string).
If you need help with that, leave a message.

Monday, February 7, 2011

SCOM: Find Notification Subscriptions for Subscriber

What to do when you want to delete a subscriber in SCOM, but you can't because get an error like this:

The notification recipient is subscribed to at least one notification subscription.
Please remove it from all notification subscriptions before deleting it.
.....cannot be deleted as its currently in use.


To solve this you would have to browse manually through all your notification subscriptions. But how much time would that take.
With this PowerShell script it takes 2 seconds!

Get-NotificationSubscription | foreach {
$ns = $_.DisplayName
$_.ToRecipients | foreach {
If ($_.Name -match "John") {
Write-Host $ns
}
}
}

Thursday, December 9, 2010

SCOM: Find Specific Members in User Roles (PowerShell)

Last week I was doing some User Role testing with a test account of mine. Normally I always use Active Directory groups for adding and removing members of a user role.
But for quick testing with some views I added my test account directly to several user roles.

I wanted to know in which user roles my test account was added.
Beneath is a PowerShell script to find members of a user role which name contains the given search criteria. The name is usually a (AD) User Account or Group, like Admin1234@domain.local or DOMAIN\Admin123.

#Find member of userrole which contains a specific text
#The search criteria is case-sensitive

$searchtext = "Admin"
Get-Userrole | Sort DisplayName | % { $userrole = $_.DisplayName;$_.Users | % { If($_.Contains("$searchtext")){ Write-Host -foregroundcolor yellow $userrole;Write-Host " $_"} }}

Wednesday, December 8, 2010

SCOM: Get Nested Group Members (Powershell)

When you create nested groups in SCOM you have to use workarounds to view the actual group members of a specific type, e.g. Windows Computer. Using 'View Members' only returns the nested groups and not the contained objects.

One of the ways to view the actual members of a group, is to create a 'State View'.
As a "filter" you then change the class type to show the data related to the type you want to see and then you select the group for scoping the returned data.

So in short terms, to view the nested group members
- Create a state view
- Change "Show data related to" to a class like 'Windows Computer'
- Change "Show data contained in a specific group" to the group of which you want the members.

But, there's quicker way to achieve this. Using Powershell you can retrieve the members of a nested group in a couple of seconds. I found out about 'Recursive' using the SCOM SDK.

$group = Get-MonitoringObject | Where { $_.DisplayName -eq "YourGroupName"}
$MonitoringClass = Get-MonitoringClass -Name "Microsoft.Windows.Computer"
$group.GetRelatedMonitoringObjects($MonitoringClass,"Recursive") | Select DisplayName

Wednesday, September 29, 2010

SCOM: Recipient address not valid - Find with PowerShell

One of the benefits of Operations Manager 2007 is the capability for users to create and maintain their own subscription notifications.

When a user adds a notification device to there recipient configuration, it's easy to make a small mistake. Whenever the Notifcation Server on the RMS trying to send a notification to a misconfigured address an alert is triggered, "Recipient address <address> is not valid."

The alert description shows in which subscription this address is used, but it's more important to know in which recipient this address can be found.

For that you can use this PowerShell script:

$searchcriteria = "yourtext"
Get-NotificationRecipient | foreach {
$addresses = $null;
$subname = $null;
$subname = $_.Name;
$addresses = $_.Devices | Where {
$_.Address -match $searchcriteria
}
if ($addresses -ne $null) {
Write-Host '***' $subname '***'; $addresses
}
}
As a one-liner:
$searchcriteria = "yourtext";Get-NotificationRecipient | foreach {$addresses = $null;$subname=$null;$subname = $_.Name;$addresses = $_.Devices | Where {$_.Address -match $searchcriteria }; if ($addresses -ne $null) { Write-Host '***' $subname '***'; $addresses}}

Thursday, July 1, 2010

SCOM: Find those heavy group discoveries

Two days ago on the 'The Operations Manager Support Team Blog' a blog was posted about editing Groups and the slow Operation Manager Console. They advise to consolidate the number of membershiprules and expressions in regular expression.

But how do you know which groups are eligable for a consolidation? Well, for that I created this script.
It retrieves groups that comply with the given user input for the 'DisplayName'. For every group the Discovery information is retrieved. If the Discovery Configuration matches the prededined thresholds for the number of MembershipRules and/or Expressions, the output will be in red. Otherwise it will be in green. The threshold can be changed at will.

Download: ShowGroupDiscoveryDatasourceConfiguration.ps1

#User-input only works from within a script!
$strGroup = Read-Host "Enter a group discovery name (wildcard) string";

$intMembershipRuleThreshold = 3;
$intMembershipRuleExpressionThreshold = 5;
$intMembershipRuleCount = 0;
$intMembershipRuleExpressionCount = 0;

#These Id's are the base Id's which are usually used when creating groups
$strInstanceGroupBaseClassId = "4ce499f1-0298-83fe-7740-7a0fbc8e2449" #Instance group
$strComputerGroupBaseClassId = "0c363342-717b-5471-3aa5-9de3df073f2a" #Computer group

Write-Host "Retrieving class that match:" $strGroup;
$colGroups = Get-MonitoringClass | where {$_.DisplayName -match "$strGroup" -and $_.Base -ne $null} | Sort-Object -Property DisplayName

if ($colGroups -ne $null) {
$colGroups | foreach {
If (($_.Base.Id.ToString() -eq $strInstanceGroupBaseClassId) -Or ($_.Base.Id.ToString() -eq $strComputerGroupBaseClassId)){
Write-Host "Class:" $_.DisplayName;
$colDiscoveries = $_.GetMonitoringDiscoveries();
#check if discoveries exist
If ($colDiscoveries.Count -ne 0) {
$colDiscoveries | foreach {
Write-Host " Discovery:";
$config = [xml] ("" + $_.DataSource.Configuration + "");
#check wether Discovery uses membership rules
$intMembershipRuleCount = $config.GetElementsByTagName("MembershipRule").Count;
If($intMembershipRuleCount -gt 0){
If ($intMembershipRuleCount -ge $intMembershipRuleThreshold){
Write-Host " MembershipRules:" $intMembershipRuleCount -ForeGroundColor red;
} else {
Write-Host " MembershipRules:" $intMembershipRuleCount -ForeGroundColor green;
}
$intIndex = 0;
$config.config.MembershipRules.MembershipRule | %{
$intIndex++;
$intMembershipRuleExpressionCount = $_.GetElementsByTagName("Expression").Count;
If ($intMembershipRuleExpressionCount -gt 0) {
Write-Host " Membership Rule #$intIndex";
If ($intMembershipRuleExpressionCount -ge $intMembershipRuleExpressionThreshold){
Write-Host " Expression count:" $intMembershipRuleExpressionCount -ForeGroundColor red;
} else {
Write-Host " Expression count:" $intMembershipRuleExpressionCount -ForeGroundColor green;
}
}
$intMembershipRuleExpressionCount = 0;
}
}
$config = $null;
$intMembershipRuleCount = 0;
}
}
}
}
}
(ps. Save it as a script to use interactive User Input.)

Friday, June 4, 2010

SCOM: Get-UserRole Views (PowerShell)

Currently I'm working on a OpsMgr Shell script to output the allowed Views for User Roles.

Current status: Working from User Role perspective to output views. Too bad, the folder hierarchy has to build from another perspective. There's a challenge!
$mgmtgrp = (Get-ManagementGroupConnection).ManagementGroupGet-UserRole | Select -First 1 | foreach { If($_.IsScopeFixed -ne $true){Write-Host "--"$_.DisplayName"--"$_.Scope.MonitoringViews | foreach { $arrViews += @($mgmtgrp.GetMonitoringView($_.First).DisplayName)}$arrViews = $arrViews | Sort-Object$arrViews$arrViews = $null}}

Monday, May 31, 2010

SCOM: Get-UserRole Group Scope (PowerShell)

Recently I wanted to document all the User Roles from a specific Management Group with their Group Scope and Views. Because their is no UI to see this quickly, besides scrolling through a list of disabled and enabled groups, I created this script.

SCOM PowerShell script for listing a User Role with it's Group Scope.
It returns all non-system* User Roles with a (sorted) list of groups from the Group Scope.
Stay tuned because i'm working on the 'Views' part.

Get-UserRole | Sort-Object DisplayName | foreach {If($_.IsSystem -ne $true){Write-Host "--" $_.DisplayName "--";If($_.Scope.MonitoringClasses -ne $null){$_.Scope.MonitoringClasses | foreach {Get-MonitoringClass -Id $_} | Sort-Object DisplayName | foreach {Write-Host "  "$_.displayName}}else{$_.Scope.MonitoringObjects | foreach {Get-MonitoringObject -Id $_} | Sort-Object DisplayName | foreach {Write-Host "  "$_.displayName}}}}
For better readability:
Get-UserRole | Sort-Object DisplayName | foreach { 
  If($_.IsSystem -ne $true)
  {
    Write-Host "--" $_.DisplayName "--"
    If($_.Scope.MonitoringClasses -ne $null){
      $_.Scope.MonitoringClasses | foreach {Get-MonitoringClass -Id $_} | Sort-Object DisplayName | foreach {Write-Host "  "$_.displayName}
    } else {
      $_.Scope.MonitoringObjects | foreach {Get-MonitoringObject -Id $_} | Sort-Object DisplayName | foreach {Write-Host "  "$_.displayName}
    }
  }
}
For SCOM 2012
#SCOM 2012
Get-SCOMUserRole | Sort-Object DisplayName | foreach { 
  If($_.IsSystem -ne $true)
  {
    Write-Host "--" $_.DisplayName "--"
    If($_.Scope.Objects -ne $null){
      $_.Scope.Objects | foreach {Get-SCOMClass -Id $_} | Sort-Object DisplayName | foreach {Write-Host "  "$_.displayName}
    }
    If ($_.Scope.Classes -ne $null) {
      $_.Scope.Classes | foreach {Get-SCOMClass -Id $_ -Id $_} | Sort-Object DisplayName | foreach {Write-Host "  "$_.displayName}
    }
  }
}

* = These roles are specified as System Roles:
Operations Manager Administrators
Operations Manager Advanced Operators
Operations Manager Authors
Operations Manager Operators
Operations Manager Read-Only Operators
Operations Manager Report Security Administrators

For exporting and importing complete user roles, see http://blogs.msdn.com/b/rslaten/archive/2008/11/03/exporting-and-importing-user-roles.aspx

Wednesday, March 25, 2009

SCOM: Maintenance Mode with PowerShell

There are situations where you want to set maintenance windows on certain machines within your SCOM infrastructure. This can be accomplised with the Operations Console or Command Shell.
The great advantage for SCOM (in comparison with MOM) is that maintance mode can be set on all monitored classes. So it's possible to set maintance mode for a webapplication, without setting your complete IIS webserver to maintenance mode.

This post is about the Command Shell. When you install the SCOM Command Shell (Powershell is a prequirement), you'll get access to numerous SCOM cmdlets for different managing tasks.

To get all cmdlets concerning 'MaintenanceWindow', type:
>get-operationsmanagercommand where-object { $_.Name -match "MaintenanceWindow"}

Below are some examples...

Create a new maintenance window for a computer
# Ask user for input
$strComputerName = Read-Host "Enter computer name"

$objComputer = Get-Agent | Where-Object {$_.Name -match $strComputerName}
$objComputer.HostComputer | New-MaintenanceWindow -StartTime:"3/25/2009 22:00" -EndTime:"3/25/2009 23:30" -Comment: "Server maintenance"

Create a new maintenance window for a group
# Ask user for input
$strGroupName = Read-Host "Enter group name"

$objGroup = get-monitoringobject | Where-Object {$_.DisplayName -eq $strGroupName}
$objGroupAgents = $objGroup.getrelatedmonitoringobjects()

# Looping throug group object
foreach ($objAgent in $objGroupAgents)
{
New-MaintenanceWindow -startTime::"3/25/2009 22:00" -EndTime:"3/25/2009 23:30"
-monitoringObject:$objComputer -comment:"Server group maintenance"
}

Create a new maintenance window on a Web Application
Below is a script that puts a Web Application in maintenance mode. Using the extra get-monitoringclass cmdlet resulted in a faster script, then only using the cmdlet get-monitoringobject with a where clause.
# Ask user for input
$strWebApp = Read-Host "Enter the Web Application name"

# Get class object
$objMonClass = get-monitoringclass where-object { $_.Name -eq "Microsoft.SystemCenter.WebApplication.Perspective"}

# Connect object and add Maintenance Window
get-monitoringobject -MonitoringClass $objMonClass | Where-Object { $_.DisplayName -match $strWebApp } | New-MaintenanceWindow -StartTime:"3/25/2009 22:00" -EndTime:"3/25/2009 23:30" -Comment: "Server maintenance"

.... more examples to come.

See http://www.systemcenterforum.org/downloads/scom-maintenance-mode-script-20/ for ready made scripts to add computer, groups to maintance mode including the related health service.