Just Another Maintenance Mode Script for SCOM 2007


This is based on Timoty Mc Fadden’s Remote Maintenance Mode scheduler:


for which many thanks!

I fiddled a little with the script, so it can be used to set a SCOM Group in Maintenance Mode, containing different kinds (types) of Objects.

I needed to do this for a customer, who performed regular maintenance on related

servers, but it wasn’t always necessary to put the entire computer in Maintenance Mode. It should be easy to add other classes as needed.

Here’s the code:


# Load Ops Mgr Snap-In
Add-PsSnapin “Microsoft.EnterpriseManagement.OperationsManager.Client”
# Go to Monitoring Drive
Set-Location “OperationsManagerMonitoring::”

# Connect to Management Group
$MGConn = New-ManagementGroupConnection -connectionString:$rootMS

If (!($MGConn))
Write-Host “Failed to connect to RMS”

# Go to RMS location on Monitoring Drive
Set-Location $rootMS;

# Instantiate objects for necessary classes
$GroupClass = Get-MonitoringClass -Name:System.Group
$windowsComputerClass = Get-MonitoringClass -Name:Microsoft.Windows.Computer
$IISServerRoleClass = Get-MonitoringClass -Name:Microsoft.Windows.InternetInformationServices.ServerRole
$WindowsClusterClass = Get-MonitoringClass -Name:Microsoft.Windows.Cluster

# Instantiate Group that was given as parameter
$GroupInstance = (Get-ManagementGroupConnection).ManagementGroup.GetPartialMonitoringObjects($GroupClass) | where {$_.DisplayName -eq $groupName}

if (!($GroupInstance))
 Write-Host “Specified Group not found”
# Function that activates the Maintenance Mode
Function PutInMaintMode ($Objects) {

ForEach($Object in $Objects)
Write-Host “Object Fullname: ” + $Object.FullName
$startTime = [DateTime]::Now
$endTime = $startTime.AddMinutes($minutes)

if($startMM -eq $true -and $Object.InMaintenanceMode -eq $false)
   New-MaintenanceWindow -startTime:$startTime -endTime:$endTime -comment:$comment -Reason:$reason -monitoringObject:$Object

# Retrieve all objects contained in the group.
# You can add classes here if necessary
$Computers = $groupInstance.GetRelatedMonitoringObjects($windowsComputerClass,[Microsoft.EnterpriseManagement.Common.TraversalDepth]::OneLevel)
$IISServers = $groupInstance.GetRelatedMonitoringObjects($IISServerRoleClass,[Microsoft.EnterpriseManagement.Common.TraversalDepth]::OneLevel)
$WindowsClusters = $groupInstance.GetRelatedMonitoringObjects($WindowsClusterClass,[Microsoft.EnterpriseManagement.Common.TraversalDepth]::OneLevel)

# Call the Maintenance Mode Function per Class
PutInMaintMode $Computers
PutInMaintMode $IISServers
PutInMaintMode $WindowsClusters


Active Directory Management Gateway Service RTMed !

The ADMG or

Active Directory Management Gateway Service or Active Directory Web Service

for Windows Server 2003 and Windows Server 2008 has RTMed !

I posted before about this component that enables you to use the

Powershell 2.0 AD Module to manage your Active Directories.

see: http://windowspowered.spaces.live.com/blog/cns!BF9377ED828F04EB!200.entry

So now not only on 2008 R2 but also on 2003,2003R2 and Windows 2008 Server (in RTM version this time)

download here:

Script GPO operations using PowerShell

If you are like me – so you’re both a PowerShell enthousiast and you don’t like repetitive (boring!) work,
you try to automate stuff that you need to do more than a few times.
In this case I was working with GPOs.
I needed to add lots of computer objects to a GPO’s security filtering list, you know what I mean:
In this case I couldn’t use groups, so I had to add all the objects seperately…(don’t ask)
Another challenge was, that it concerned a domain not trusted by my workstation’s domain.
I looked into the VBscripts that come with GPMC in Windows 2003 (in the ‘\Program FilesGPMC\Scripts’ Folder),
following command looks like it should work, but I doesn’t seem to work for user objects in a non-trusted domain,
and the script doesn’t seem to work for computer objects at all:
Cscript SetGPOPermissions.wsf "MyGPO" "MyServer" /Permission:Apply /Domain:wedonttrustyou.local
I also tried porting the script to PowerShell, using the same GPMgmt.GPM Com Interface,
but that seems to have issues as well, so there might be inherent issues with this interface and using it for
non-trusted domains, as far as I can tell.
I did find a good starting point for that kind of scripting, in an old Technet Magazine:
There is also some code for download there, including a ‘GPMC PowerShell Functions.txt’
If you load this in your Posh Profile or dot-source it in a session,
you have a lot of functions at your disposal, to do different Group Policy tasks.
But I had to look for an alternative…
I remembered I downloaded and installed the SDM GPMC Powershell CmdLets 1.3 once, but I hadn’t put much use in them yet..
Check out: http://www.sdmsoftware.com/freeware.php for these and other nice tools.
I even had The SDMSoftware.PowerShell.GPMC snap-in loaded already through my PoSh profile script, so I was ready to go!
I quickly discovered the Add-SDMgpoSecurity CmdLet, which looked right for the job.
After a few typos I had it working in a few minutes!
In a session, started with alternate credentials for the non-trusted domain,
I could use following command to get the job done:
Add-SDMgpoSecurity  -name "MyGPO" -Trustee "MyServer" -PermApply -Domain "wedonttrustyou.local"
After that I could pipe the entire list of computers to the command and relax,
and next time the command will be at my disposal at will (if I forget I can check this blogpost I guess 😉

ADWS beta for down level DCs is here

Good news for Active Directory Powershell scripters!
Microsoft is backporting the excellent Active Directory Web Service to Windows Server 2003/2008
This means you can use the Active Directory PowerShell Module from a Windows 7 or Windows Server 2008 R2 machine
to connect to a Windows 2003/2008 Active Directory and manage it using PowerShell.
I described the ADPM in an earlier blogpost:
Please read info about the Beta on the AD Powershell Blog:
You can also find a download link for the Beta there.

MOM 2005 Maintenance Mode through PowerShell

If you are still using MOM 2005 like the client I work for, you probably use some tool like
the MaintenanceModeUtility from the MOM 2005 SDK when you need to put multiple servers
in Maintenance mode.
We use(d) to use it, but I never liked this tool, it’s pretty slow because it needs to connect to MOM for every
single server and doesn’t have decent logging for success or failures.
Since MOM 2005 is pre-Powershell it doesn’t have built-in CmdLets like SCOM 2007,
 but there are .NET Assemblies that come with the product, so why not leverage those!
Using the C# source code that comes with the existing tool, I decided to port (part of it) it to PowerShell.
I also took a look at following excellent post that helped me get started:
You need to create a csv-file (srvlist.txt) which uses following header-format: Server,Domain
and fill it up with the servers you want to put in Maintenance mode.
Customize the length of your maintenance period and the reason and run the script.
It needs to be run from a Management Server, so you need Powershell there.
#Make sure Maintenance period in minutes is correct
#Customize reason for maintenance mode if necessary
# End Init
Remove-Item $LogFilePath
[System.Reflection.Assembly]::LoadFile("$($env:ProgramFiles)\Microsoft Operations Manager 2005\SDK Bin\Microsoft.Mom.Sdk.dll")
[System.Reflection.Assembly]::LoadFile("$($env:ProgramFiles)\Microsoft Operations Manager 2005\mom.context.dll")
$mom = [Microsoft.EnterpriseManagement.Mom.Administration]::GetAdministrationObject()
$cm = $mom.GetComputerMaintenanceObject()
$computerQuery = $mom.GetComputerQueryObject()
function ActivateMaintMode ($server,$domain,$MaintPeriod,$Reason)   {
   $foundComputer = $computerQuery.GetComputerByNameAndDomain($server, $domain)
   if ($foundcomputer -and !$foundcomputer.IsInMaintenanceMode) {
      $cm.SetMaintenanceMode($foundcomputer, $endMaintenanceAt, $Reason)
      Out-File -append -filepath $LogFilePath -inputobject "$server from domain $domain has been placed in Maintenance mode for $Maintperiod minutes"
   else {
      if ($foundcomputer.IsInMaintenanceMode) {Out-File -append -filepath $LogFilePath -inputobject "$server from domain $domain is already in Maintenance mode until $($foundComputer.MaintenanceOutTime.ToLocalTime()) – maintenance mode not updated" }
      else {Out-File -append -filepath $LogFilePath -inputobject "$server from domain $domain not found in MOM" }
Foreach($Machine in (import-csv ".\srvlist.txt")) {
ActivateMaintMode $Machine.Server $Machine.Domain $MaintPeriod $Reason

PowerShell WMI Alternate Credentials bug

Just a small post about a bug I ran into a few times already,
so you may not spend too much time trying to debug your script when in fact there’s nothing wrong with it:
There’s a known bug in PowerShell 1.0 when using WMI connections using alternate credentials to a remote machine.
For example, I was making a script to change the WINS client settings for a number of machines:
(Get-Wmiobject -comp MyServer -class "Win32_networkadapterconfiguration" -credential $creds | Where{$_.IpEnabled -Match "True"}).SetWinsServer("","")
The script failed with error: 0x80070005 (E_ACCESSDENIED)
because it was using the credentials the script was running with, not the credentials specified by the script.
The only way to fix this AFAIK, is to use Powershell 2.0 (CTP at this time so don’t use on production machines without care).
Or you can try running your entire script as an alternate user, but this isn’t very efficient if you want to run WMI commands against a large number of machines.

Active Directory PowerShell Module

The Good news there will be better support for Active Directory scripting using Windows Powershell (2.0)
The Bad news, at the time of writing, you will probably have to wait some time before you can use this in production,
because it’s only possible from a 2008R2 or a Windows-7 machine:
‘You can install Active Directory PowerShell by using any of the following methods:
By default, on a Windows Server 2008 R2 server when you install the AD DS or AD LDS server roles
By default, when you make a Windows Server 2008 R2 server a domain controller by running Dcpromo.exe
As part of the RSAT feature on a Windows Server 2008 R2 server
As part of the RSAT feature on a Windows 7 computer’
And also important:
‘If you want to use Active Directory PowerShell in Windows 7 to remotely manage an Active Directory domain, an AD LDS instance or configuration set, or an Active Directory Database Mounting Tool instance, you must have at least one Windows Server 2008 R2 domain controller in your domain or at least one instance in an AD LDS configuration set that is running on a Windows Server 2008 R2 server.’
‘For Active Directory PowerShell to function correctly, Windows PowerShell and the .NET Framework 3.5.1 must be installed on your Windows Server 2008 R2 or Windows 7 computer.’
(This probably has to do with the dependancy of the AD Module on the ‘Active Directory WebServices’ Service that exists in Win2008R2 and
serves as an interface between PowerShell and AD or AD LDS)

Anyhow it looks promising,

I’m posting a few examples, based on the Active Directory PowerShell Cookbook at:

There’s also an Active Directory PSDrive that you can access in the standard Powershell way,
you can access it like in following example:
New-PSDrive -Name ADDrive -PSProvider ActiveDirectory -Root "DC=lab,DC=net"
cd ADDrive:
cd ou=yourOUhere
I’m also posting some examples below that sound useful to me as I’ve needed similar things in the past and had to use a variety
of 3rd party tools and VBscripts. Those can now (or at least when W2K8R2/Windows Seven are mainstream) be replaced with mostly oneliner
Powershell code!
#Create a new Active Directory user
New-ADUser -SamAccountName Johnny -Name "Johnny" -AccountPassword (ConvertTo-SecureString -AsPlainText "p@ssw0rd" -Force) -Enabled $true -Path ‘OU=sandbox,DC=lab2,DC=int’
#Search for locked out accounts
Search-ADAccount -LockedOut | where {$_.ObjectClass -eq ‘user’}
#Resetting a Computer Account
Test-ComputerSecureChannel -Repair -Server myserver.test.net
#Finding Inactive or Unused Computers
$lastSetdate = [DateTime]::Now – [TimeSpan]::Parse("45")
Get-ADComputer -Filter {PasswordLastSet -le $lastSetdate} -Properties passwordLastSet -ResultSetSize $null | FT samaccountname,PasswordLastSet
#Changing the Maximum Number of Computers That a User Can Join to the Domain
Set-ADDomain Fabrikam.com -Replace @{"ms-ds-MachineAccountQuota"="2"}’
#Finding Computers with a Particular Operating System
Get-ADComputer -Filter ‘OperatingSystem -eq "Windows Server 2008 Enterprise"’
#Listing All the Computer Accounts in a Domain
Get-ADcomputer -Filter ‘Name -like "*"’
#Viewing the Direct Members of a Group
Get-ADGroupMember G1 | FT Name,ObjectClass -A
#Adding and Removing Members of a Group
Add-ADGroupMember -Identity AccGroup -Member Johnny
#Remove member from a Group
Remove-ADGroupMember -Identity AccGroup -Member Johnny
#Enumerating the OUs in a Domain
Get-ADOrganizationalUnit -Filter {Name -like ‘*’} | FT Name, DistinguishedName -A
#Enumerating the Objects in an OU
Get-ADObject -Filter ‘Name -like "*"’ -Searchbase ‘OU=myusers,DC=lab,DC=local’
#Viewing the RootDSE
#Viewing the Trusts for a Domain
Get-ADObject -Filter {objectClass -eq "trustedDomain"} -Properties TrustPartner,TrustDirection,trustType | FT Name,TrustPartner,TrustDirection,TrustType
#Finding the Operations Master Role Holders
Get-ADForest Fabrikam.com | FT SchemaMaster,DomainNamingMaster
Get-ADDomain Fabrikam.com | FT PDCEmulator,RIDMaster,InfrastructureMaster
 And there are a large number of additional Active Directory cmdlets available, have fun trying them!