<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cupfighter.net &#187; System Center Operations Manager 2007</title>
	<atom:link href="http://www.cupfighter.net/index.php/tag/system-center-operations-manager-2007/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cupfighter.net</link>
	<description>A blog by Schuberg Philis colleagues</description>
	<lastBuildDate>Tue, 20 Dec 2011 06:38:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Check SQL DB Free space</title>
		<link>http://www.cupfighter.net/index.php/2009/10/check-sql-db-free-space/</link>
		<comments>http://www.cupfighter.net/index.php/2009/10/check-sql-db-free-space/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 08:25:16 +0000</pubDate>
		<dc:creator>Jan Jacob Bos</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[SCOM 2007]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Database free space]]></category>
		<category><![CDATA[System Center Operations Manager 2007]]></category>

		<guid isPermaLink="false">http://www.cupfighter.net/?p=647</guid>
		<description><![CDATA[By default SQL Server database free space is not monitored by System Center Operations Manager 2007 when autogrow AND limited file size are on. Here is a custom monitor to monitor these databases.]]></description>
			<content:encoded><![CDATA[<p>System Center Operations Manager is monitoring DB space used by default if you have set the database to a fixed size. If you are using autogrowth with unlimited file growth, your diskspace monitoring will kick in when you are running out of disk space (don&#8217;t forget to customize these settings for large disks: you don&#8217;t want to get warned on a 500GB volume when there is only 2 GB free space).<br />
However, if you are using autogrow options with a limited size, then SCOM 2007 doesn&#8217;t generate alerts as also documented in the product knowledge tab for “DB Space Free (%)” Monitor:<br />
<code>This monitor checks the database percentage free space to ensure it is above the defined thresholds. A warning or error alert will be raised if it is below one of the defined thresholds.<br />
Databases that have autogrow set will never generate an alert regardless of the reported free space.</code><br />
If your database is filling up, you get the following error: Could not allocate space for object in database because the filegroup is full.<br />
To prevent this error and get warned in advance, I have written a custom monitor that will detect databases with the settings mentioned above and monitors database free space when autogrow AND limited file size are on.<br />
<span id="more-647"></span><br />
For detailed instruction on how to setup a monitor for monitoring SQL Server, have a look at: <a href="http://www.cupfighter.net/index.php/2009/10/check-your-sql-backup-automatically/">Check your SQL backup automatically</a>.</p>
<p><em>Script is updated on 26-11-2009, some bugs are fixed and it is now using the &#8220;SQL 2005 DB Engine&#8221; monitor instead of the &#8220;SQL 2005 DB&#8221; monitor. First I thought it would be better to handle all individual databases by SCOM. However is something is wrong with the script, SCOM generates an alert for every database. If you have a lot of databases on one server (I have servers with over 500 databases), it can generate a lot of alerts. Now only one alert per engine is generated. And the script takes only 3 seconds on my 500+ database server.</em></p>
<p>Here are the short instructions for this monitor:</p>
<li>Create 3 state Script monitor (also select a proper management pack to save your monitor)</li>
<li>Set Monitor Target to &#8220;SQL 2005 DB Engine&#8221;</li>
<li>Set running interval (between 15 and 60 minutes should be ok, depending on your situation)</li>
<li>Add the script (see below)</li>
<li>Add the following parameter:</li>
<p>$Target/Property[Type="MicrosoftSQLServerLibrary6064600!Microsoft.SQLServer.DBEngine"]/ConnectionString$</p>
<li>Set Unhealthy expression: Property[@Name='Status'] Equals Critical</li>
<li>Set Degradedexpression: Property[@Name='Status'] Equals Warning</li>
<li>Set Healthy expression: Property[@Name='Status'] Equals Healthy</li>
<li>Accept default health options</li>
<li>Check &#8220;generate alerts for this monitor&#8221;</li>
<li>Set &#8220;Generate an when&#8230; The monitor is in a critical or warning state&#8221;</li>
<li>Adjust Severity to &#8220;Match monitor&#8217;s health&#8221;</li>
<li>Use the following alert description:</li>
<p>Low DB Free space on $Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetbiosComputerName$ in instance  $Target/Property[Type="MicrosoftSQLServerLibrary6064600!Microsoft.SQLServer.DBEngine"]/ServiceName$, list of datafiles: $Data/Context/Property[@Name='DBList']$</p>
<p><code><br />
Dim i, oAPI, propertyBag, objShell<br />
Dim strStatus<br />
Dim objParameters, sConnectionString<br />
' define constants<br />
Const EVENT_TYPE_ERROR = 1<br />
Const EVENT_TYPE_WARNING = 2<br />
Const EVENT_TYPE_INFORMATION = 4<br />
' check parameters<br />
Set objParameters = WScript.Arguments<br />
If objParameters.Count <> 1 Then<br />
' Set objShell = Wscript.CreateObject("Wscript.Shell")<br />
' objShell.LogEvent EVENT_TYPE_ERROR, "This Script requires exactly 1 parameter: ConnectionString"<br />
WScript.Quit -1<br />
End If<br />
' map arguments to friendly names<br />
sConnectionString= objParameters(0)</p>
<p>' initialize SQL statement<br />
SQL = "SET NOCOUNT ON; " &#038; _<br />
"DECLARE @dbid int DECLARE @dbname sysname DECLARE @sql varchar(3000)  " &#038; _<br />
"CREATE TABLE #DBSpace ( " &#038; _<br />
"	DBName varchar (50), " &#038; _<br />
"	[Size] int, " &#038; _<br />
"	max_size int, " &#038; _<br />
"	growth int, " &#038; _<br />
"	is_percentage_growth bit, " &#038; _<br />
"	percentage_used real, " &#038; _<br />
"	[type] varchar(15), " &#038; _<br />
"	severity varchar(8)) " &#038; _<br />
"SET @dbid = (SELECT MIN(database_id) FROM master.sys.databases) " &#038; _<br />
"WHILE @dbid IS NOT NULL " &#038; _<br />
"  BEGIN  " &#038; _<br />
"	SET @dbname = (SELECT [name] FROM master.sys.databases WHERE database_id = @dbid) " &#038; _<br />
"	SET @sql = 'INSERT INTO #DBSpace SELECT dbname , [size], max_size, growth, is_percent_growth, percentage_used,  " &#038; _<br />
"		CASE   " &#038; _<br />
"			WHEN [type] = 0 THEN ''Database'' " &#038; _<br />
"			WHEN [type] = 1 THEN ''Transaction Log''  " &#038; _<br />
"		END AS [type],    " &#038; _<br />
"		CASE    " &#038; _<br />
"			WHEN is_percent_growth = 1 THEN   " &#038; _<br />
"				CASE     " &#038; _<br />
"				WHEN db.percentage_used < (100 - ((db.percentage_used / 100) * db.growth * 1.2)) AND db.percentage_used > (100 - ((db.percentage_used / 100) * db.growth * 2.5))  THEN   ''warning'' " &#038; _<br />
"				WHEN db.percentage_used > (100 - ((db.percentage_used / 100) * db.growth * 1.2)) THEN   ''critical''  " &#038; _<br />
"				ELSE ''healthy''  " &#038; _<br />
"				END   " &#038; _<br />
"			ELSE   " &#038; _<br />
"				CASE " &#038; _<br />
"				WHEN db.size < (db.max_size - (db.growth * 2)) AND db.size > (db.max_size - (db.growth * 4))  THEN   ''warning''	  " &#038; _<br />
"				WHEN db.size > (db.max_size - (db.growth * 2)) THEN   ''critical''  " &#038; _<br />
"				ELSE ''healthy''  " &#038; _<br />
"				END   " &#038; _<br />
"		END  AS severity   " &#038; _<br />
"	FROM    " &#038; _<br />
"		( SELECT ''' + @dbname + ''' as dbname, [size] , [type], [max_size], [growth] ,   " &#038; _<br />
"		[is_percent_growth] ,    " &#038; _<br />
"		(CAST([size] AS REAL) / CAST([max_size] AS REAL) * 100)  AS percentage_used    " &#038; _<br />
"		FROM [' + @dbname + '].sys.database_files )AS db   " &#038; _<br />
"		WHERE  max_size > 0 AND growth > 0 ' " &#038; _<br />
"	EXEC(@sql) " &#038; _<br />
"	SET @dbid = (SELECT MIN(database_id) FROM master.sys.databases WHERE database_id > @dbid)   " &#038; _<br />
"  END " &#038; _<br />
"SELECT * FROM #DBSpace WHERE severity <> 'healthy' " &#038; _<br />
"drop table #DBSpace"</p>
<p>On Error resume next<br />
' Setup Database connection<br />
Set cnADOConnection = CreateObject("ADODB.Connection")<br />
cnADOConnection.Provider = "sqloledb"<br />
cnADOConnection.ConnectionTimeout = 30<br />
strProv = "Server=" &#038; sConnectionString &#038; ";Database=Master;Trusted_Connection=yes"<br />
' open connection and execute query<br />
cnADOConnection.Open strProv<br />
  Set rsCustomDBSpaceMonitor = cnADOConnection.Execute(SQL)<br />
  do until rsCustomDBSpaceMonitor.EOF<br />
    strDatabase = CStr(rsCustomDBSpaceMonitor("DBName").Value)<br />
    if rsCustomDBSpaceMonitor("severity").Value = "warning" Then<br />
	strSeverityWarning = "Warning"<br />
	strList = strList &#038; "warning: " &#038; rsCustomDBSpaceMonitor("type").Value &#038; " " &#038; strDatabase &#038; " Percentage Used: " &#038; rsCustomDBSpaceMonitor("percentage_used").Value &#038; ", "<br />
    elseif rsCustomDBSpaceMonitor("severity").Value = "critical" Then<br />
	strSeverityCritical = "Critical"<br />
	strList = strList &#038; "Critical: " &#038; rsCustomDBSpaceMonitor("type").Value &#038; " " &#038; strDatabase &#038; " Percentage Used: " &#038; rsCustomDBSpaceMonitor("percentage_used").Value &#038; ", "<br />
    else<br />
	strSeverityHealthy = "Healthy"<br />
    End If<br />
    ' wscript.echo "percentage used " &#038;  rsCustomDBSpaceMonitor("percentage_used").Value</p>
<p>    Err.Clear<br />
    rsCustomDBSpaceMonitor.MoveNext<br />
    ' if 0 <> Err.number then Exit Do<br />
  loop<br />
' clean up connection<br />
rsCustomDBSpaceMonitor.close<br />
cnADOConnection.close</p>
<p>' Set SCOM parameters<br />
Set oAPI = CreateObject("MOM.ScriptAPI")<br />
' set state depending on Free space (order of next statemenst is important, if only in one row the state is critical, the state will be critical)<br />
If strSeverityHealthy = "Healthy" Then strStatus = "Healthy"<br />
If strSeverityWarning = "Warning" Then strStatus = "Warning"<br />
If strSeverityCritical = "Critical" Then strStatus = "Critical"</p>
<p>If strStatus = "Critical" Then<br />
' wscript.echo  strList<br />
Call oAPI.LogScriptEvent("SBPDBFreeSpaceMonitor", 3000, EVENT_TYPE_ERROR, "The Following datafiles are low on free space:" &#038; strList)</p>
<p>ElseIf strStatus = "Warning" Then<br />
' wscript.echo  strList<br />
Call oAPI.LogScriptEvent("SBPDBFreeSpaceMonitor", 3001, EVENT_TYPE_WARNING, "The Following datafiles are low on free space:" &#038; strList)<br />
Else<br />
' wscript.echo "healthy"<br />
Call oAPI.LogScriptEvent("SBPDBFreeSpaceMonitor", 3002, EVENT_TYPE_INFORMATION, "All datafiles on " &#038; sConnectionString &#038; " have enough free space")<br />
End If<br />
' Return values to SCOM to set state and generate Alert<br />
Set propertyBag = oAPI.CreatePropertyBag ()<br />
Call propertyBag.AddValue ("Status", strStatus)<br />
Call propertyBag.AddValue ("DBList", strList)<br />
Call oAPI.Return(propertyBag)<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cupfighter.net/index.php/2009/10/check-sql-db-free-space/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Check your SQL backup automatically</title>
		<link>http://www.cupfighter.net/index.php/2009/10/check-your-sql-backup-automatically/</link>
		<comments>http://www.cupfighter.net/index.php/2009/10/check-your-sql-backup-automatically/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 21:10:49 +0000</pubDate>
		<dc:creator>Jan Jacob Bos</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[SCOM 2007]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[System Center Operations Manager 2007]]></category>

		<guid isPermaLink="false">http://www.cupfighter.net/?p=604</guid>
		<description><![CDATA[Automatic SQL database backup check in System Center Operations Manager 2007.]]></description>
			<content:encoded><![CDATA[<p>Ever thought you had a good backup and it turned out it was missing when you needed a restore? Although a regular restore test is the least you can do, there is more. SQL Server stores backupinformation for all databases in msdb.dbo.backupset. A simple query shows you all databases that have no backup in the last two days:<br />
SELECT DatabaseName = d.name<br />
       ,LatetstBackUpDate   = ISNULL(CONVERT(VARCHAR(30),MAX(b.backup_finish_date),120),&#8217;No backup&#8217;)<br />
       ,&#8217;Days&#8217;       = MIN(DATEDIFF(hh,b.backup_finish_date,getdate())) / 24<br />
       ,&#8217;Hours&#8217;      = MIN(DATEDIFF(hh,b.backup_finish_date,getdate())) % 24<br />
	 FROM   master.sys.databases          d<br />
  	 LEFT OUTER JOIN msdb.dbo.backupset b ON d.name = b.database_name<br />
	 WHERE d.name NOT IN (&#8216;tempdb&#8217;,'model&#8217;)<br />
	 GROUP BY d.name<br />
	 HAVING ISNULL(MIN(DATEDIFF(hh,b.backup_finish_date,getdate())),999) >= 24 * 2 &#8212; change the 2 when you want to use a different amount of days<br />
	 ORDER BY d.name </p>
<p>Wait, there is more! You don&#8217;t want to run this query every day by hand is it? Of course you can run it as a scheduled job on your database server, but even that can be a time-consuming task if you have a lot of servers. It would be better to run this query from System Center Operations Manager. </p>
<p><span id="more-604"></span><br />
You can add the query in a System Center Opeations Management Monitor to deploy your backup check automatically to *all* SQL Servers within your organization. I&#8217;ll show you how to do it:<br />
Create a &#8220;Timed Script Two State Monitor&#8221; (don&#8217;t forget to select an appropriate management pack to save your monitor).<br />
Set the Monitor target to &#8220;SQL 2005 DB engine:<br />
<img src="http://www.cupfighter.net/wp-content/uploads/2009/10/CreateBackupMonitorStep2.jpg" alt="Create SQL Backup Monitor Step 2" title="Create SQL Backup Monitor Step 2" width="739" height="722" class="alignleft size-full wp-image-605" /><br />
In the next step, choose your schedule (once a day would be appropriate in most cases).<br />
In the script page, name your script (don&#8217;t forget to add .vbs extension).<br />
Paste the following script in the script box:</p>
<p><code><br />
Dim i, oAPI, propertyBag, objShell<br />
Dim strStatus<br />
Dim objParameters, sConnectionString</p>
<p>' define constants<br />
Const EVENT_TYPE_ERROR = 1<br />
Const EVENT_TYPE_WARNING = 2<br />
Const EVENT_TYPE_INFORMATION = 4</p>
<p>' check parameters<br />
Set objParameters = WScript.Arguments<br />
If objParameters.Count <> 1 Then<br />
  ' Set objShell = Wscript.CreateObject("Wscript.Shell")<br />
  ' objShell.LogEvent EVENT_TYPE_ERROR, "This Script requires exactly 1 parameter: ConnectionString"<br />
  WScript.Quit -1<br />
End If</p>
<p>' map arguments to friendly names<br />
sConnectionString= objParameters(0)</p>
<p>' initialize SQL statement<br />
SCRIPT_SQL = "SELECT DatabaseName = d.name  " &#038; _<br />
" ,LatetstBackUpDate = ISNULL(CONVERT(VARCHAR(30),MAX(b.backup_finish_date),120),'No backup')   " &#038; _<br />
" ,(MIN(DATEDIFF(dd,d.create_date,getdate())))  'age in days'   " &#038; _<br />
" ,'Days' = MIN(DATEDIFF(hh,b.backup_finish_date,getdate())) / 24   " &#038; _<br />
" ,'Hours' = MIN(DATEDIFF(hh,b.backup_finish_date,getdate())) % 24   " &#038; _<br />
" FROM master.sys.databases d   " &#038; _<br />
" LEFT OUTER JOIN msdb.dbo.backupset b ON d.name = b.database_name   " &#038; _<br />
" WHERE d.name NOT IN ('tempdb','model')   " &#038; _<br />
" GROUP BY d.name   " &#038; _<br />
" HAVING (ISNULL(MIN(DATEDIFF(hh,b.backup_finish_date,getdate())),999) >= 24 * 2  " &#038; _<br />
" 		AND ((MIN(DATEDIFF(hh,d.create_date,getdate()))  )  >= 1))   " &#038; _<br />
" ORDER BY d.name "</p>
<p>On Error resume next</p>
<p>' Setup Database connection<br />
Set cnADOConnection = CreateObject("ADODB.Connection")<br />
cnADOConnection.Provider = "sqloledb"<br />
cnADOConnection.ConnectionTimeout = 30<br />
strProv = "Server=" &#038; sConnectionString &#038; ";Database=master;Trusted_Connection=yes"</p>
<p>' open connection and execute query<br />
cnADOConnection.Open strProv<br />
Set rsLastBackup = cnADOConnection.Execute(SCRIPT_SQL)</p>
<p>i = 0</p>
<p>' check recordset for datbases without backup in last 48 hours<br />
do until rsLastbackup.EOF<br />
      strDatabase = CStr(rsLastbackup("DatabaseName").Value)<br />
      strList = strList &#038; strDatabase &#038; ", "<br />
      Err.Clear<br />
      rsLastbackup.MoveNext<br />
      if 0 <> Err.number then Exit Do<br />
      i = i + 1<br />
loop</p>
<p>' clean up connection<br />
rsLastBackup.close<br />
cnADOConnection.close</p>
<p>' Set SCOM parameters<br />
Set oAPI = CreateObject("MOM.ScriptAPI")</p>
<p>' set state depending on databases without backup<br />
If i > 0 Then<br />
  ' wscript.echo strList<br />
  Call oAPI.LogScriptEvent("SQLBackupCheck", 2000, EVENT_TYPE_WARNING, "There are databases not in backup last 48 hours:" &#038; strList)<br />
  strStatus = "Warning"<br />
Else<br />
  ' wscript.echo "healthy"<br />
  Call oAPI.LogScriptEvent("SQLBackupCheck", 2001, EVENT_TYPE_INFORMATION, "All databases in Backup correctly")<br />
  strStatus = "Healthy"<br />
End If</p>
<p>' Return values to SCOM to set state and generate Alert<br />
Set propertyBag = oAPI.CreatePropertyBag ()<br />
Call propertyBag.AddValue ("Status", strStatus)<br />
Call propertyBag.AddValue ("DBList", strList)<br />
Call oAPI.Return(propertyBag)<br />
</code></p>
<p>Click on the Button &#8220;Paramaters&#8230;&#8221; at the bottom of this step.<br />
Use the following code here, or select &#8220;Connection String (SQL DB Engine)&#8221; from the Target button.<br />
<code><br />
$Target/Property[Type="MicrosoftSQLServerLibrary6064600!Microsoft.SQLServer.DBEngine"]/ConnectionString$<br />
</code><br />
In the Unhealthy Expression step, add the following:Property[@Name='Status] Equals Warning<br />
<img src="http://www.cupfighter.net/wp-content/uploads/2009/10/CreateBackupMonitorStep5.jpg" alt="Create SQL Backup Monitor Step 5" title="Create SQL Backup Monitor Step 5" width="739" height="722" class="alignleft size-full wp-image-606" /></p>
<p>For the healthy expression add: Property[@Name='Status'] Equals Healthy<br />
In the next steps configure Health and Alerts according to your needs.</p>
<p>In the alert description you can use a text like this:<br />
No SQL backup in last 48 hours on $Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetbiosComputerName$ in instance $Target/Property[Type="MicrosoftSQLServerLibrary6064600!Microsoft.SQLServer.ServerRole"]/InstanceName$, list of databases: $Data/Context/Property[@Name='DBList']$</p>
<p>You are all done. The monitor will automatically run on all SQL Server instances to check when the last backup is made and warn you if that&#8217;s more than 2 days ago.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cupfighter.net/index.php/2009/10/check-your-sql-backup-automatically/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>System Center Operations Manager: Version Control</title>
		<link>http://www.cupfighter.net/index.php/2009/07/system-center-operations-manager-version-control/</link>
		<comments>http://www.cupfighter.net/index.php/2009/07/system-center-operations-manager-version-control/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 08:35:45 +0000</pubDate>
		<dc:creator>Jan Jacob Bos</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[SCOM 2007]]></category>
		<category><![CDATA[management pack]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[System Center Operations Manager 2007]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.cupfighter.net/?p=323</guid>
		<description><![CDATA[The current version of System Center Operations Manager 2007 doesn&#8217;t use version control for management packs. If you manage complex environments and use lot of custom monitoring, it would be nice to see when there is something changed and even better: easily fall back to your previous version in case an error slipped in. Another [...]]]></description>
			<content:encoded><![CDATA[<p>The current version of <strong>System Center Operations Manager 2007</strong> doesn&#8217;t use version control for management packs. If you manage complex environments and use lot of custom monitoring, it would be nice to see when there is something changed and even better: easily fall back to your previous version in case an error slipped in. Another benefit of version control is you have exported management packs ready to import in other environments: i.e. between acceptance and production or between customers in case you are managing multiple customers like we do.</p>
<p>I&#8217;ve written some scripts to automatically export all your unsealed management packs if there is something changed, write a version number and email the new managementpack with a summary of all differences.</p>
<p>Another script will import your version controlled management packs (if there is something changed).</p>
<p>Scripts are updated on 12-11-2009</p>
<p><span id="more-323"></span></p>
<p>To setup version control for Management Packs, you need the following:<br />
- ExportUnsealedMPs.ps1<br />
- ExportUnsealedMPs_Simple.ps1<br />
- ImportMPs.ps1<br />
- SCOMSettings.xml<br />
- A folder structure to save management packs<br />
- SVN and TortoiseSVN</p>
<p>Folder Structure<br />
SVN\SCOM<br />
Scripts<br />
SVNControlledMPs<br />
UnsealedMPs<br />
  &#8211; diff<br />
  &#8211; temp<br />
  &#8211; test1<br />
  &#8211; test2</p>
<p><strong>SVN </strong><br />
<a title="SVN" href="http://subversion.tigris.org/getting.html#windows" target="_blank">SVN</a> is needed to do commits directly from within the script. <a title="Tortoise SVN" href="http://tortoisesvn.net/downloads" target="_blank">TortoiseSVN</a> helps you to commit, update and compare files within the Explorer.<br />
<strong>Setup</strong><br />
After you setup SVN and Tortoise SVN and created the folder structure. You can create scheduled tasks to run the import and export jobs. It is a good idea to run the export at the end of the day to capture all changes of that day, I export them at 19:00.<br />
Best time to import the management packs is 13:30, you don’t want to get suprised at night if some import causes pages.</p>
<p>First run ExportUnsealedMPs_Simple.ps1 to get all unsealed management packs without version control.<br />
Commit your Unsealed Folder in SVN (before you do that, make sure you have marked xml files as text:<br />
Edit Tortoise Settings file, add the following lines<br />
Under [miscellany]:<br />
enable-auto-props = yes<br />
Under [auto-props]:<br />
*.xml = svn:mime-type=text/xml;svn:eol-style=native;svn:keywords=Rev Date</p>
<p>Run the export job, it should not export anything, since you are up-to-date.<br />
Change something in a management pack, update a description will do.<br />
Run the export job again, you should see it is updated, committed and an email is sent to the address mentioned in your settings file..<br />
ExportUnsealedMPs.ps1</p>
<blockquote><p>
#########################################################################################<br />
#											#<br />
# Author: Jan Jacob Bos 								#<br />
# Date: 17-01-2009									#<br />
# Version: 1.5										#<br />
#											#<br />
# Usage:   	ExportUnsealedMPs  							#<br />
#											#<br />
# Purpose: 	Script to export unsealed management packs with version control		#<br />
#   		Only if something is changed the version number is increased and	#<br />
#   		management pack is saved, committed in SVN and emailed			#<br />
#		 									#<br />
#########################################################################################</p>
<p># initialize settings from config file<br />
$xmlSettings=[xml](get-content &#8220;.\SCOMSettings.xml&#8221;)<br />
$ServerName = $xmlSettings.SCOMSettings.General | %{$_.RootMS} | select-object -unique<br />
$targetFilePath = $xmlSettings.SCOMSettings.General | %{$_.ExportFolder} | select-object -unique<br />
$SMTPServer = $xmlSettings.SCOMSettings.Mail | %{$_.SMTPServer} | select-object -unique<br />
$From = $xmlSettings.SCOMSettings.Mail | %{$_.From} | select-object -unique<br />
$To = $xmlSettings.SCOMSettings.Mail | %{$_.To} | select-object -unique</p>
<p>#Initializing the Ops Mgr 2007 Powershell provider<br />
   add-pssnapin &#8220;Microsoft.EnterpriseManagement.OperationsManager.Client&#8221; -ErrorVariable errSnapin ;<br />
   set-location &#8220;OperationsManagerMonitoring::&#8221; -ErrorVariable errSnapin ;<br />
   new-managementGroupConnection -ConnectionString:$Servername -ErrorVariable errSnapin ;<br />
   set-location $Servername -ErrorVariable errSnapin ;</p>
<p># initializing variables<br />
$Differences1 = &#8220;&#8221;<br />
$Differences2 = &#8220;&#8221;<br />
$VersionFirstpartCurrent = 0<br />
$RevisionCurrent = 0<br />
$VersionFirstpartFile = 0<br />
$RevisionFile = 0</p>
<p># Defining Functions<br />
function ExternalCommand([string]$Command, [string]$Parameter)<br />
{ $StartInfo = new-object System.Diagnostics.ProcessStartInfo<br />
  $StartInfo.FileName = $Command<br />
  $StartInfo.Arguments = $Parameter<br />
  $StartInfo.LoadUserProfile = $true<br />
  $StartInfo.UseShellExecute = $false<br />
  # Execute command<br />
  $proc = [System.Diagnostics.Process]::Start($StartInfo)<br />
  # Wait for command to finish<br />
  $proc.WaitForExit()<br />
} </p>
<p>function GetRevision {param ([string]$VersionNo, [REF]$VersionFirstpartOUT, [REF]$RevisionOUT)<br />
  # look for last dot in version number (is always in format: 1.0.0.0) we only change last number (revision)<br />
  [int]$count = $VersionNo.length &#8211; ($VersionNo.LastIndexOf(&#8220;.&#8221;) + 1)<br />
  [int]$LastDot = $VersionNo.length &#8211; $count<br />
  $VersionFirstpartOUT.Value = $versionNo.substring(0, $LastDot)<br />
  [int]$RevisionOUT.Value = $VersionNo.substring($LastDot , $count)<br />
}</p>
<p>function SendMail {param ([string]$Subject, [string]$Message, $Attachment)<br />
  # send mail<br />
  $msg = new-object Net.Mail.MailMessage<br />
  $smtp = new-object Net.Mail.SmtpClient($smtpServer)<br />
  $msg.From = $From<br />
  $msg.To.Add($To)<br />
  $msg.Subject = $Subject<br />
  $msg.Body = $Message<br />
  if ($Attachment -ne &#8220;&#8221;)<br />
    { $att = new-object Net.Mail.Attachment($Attachment)<br />
      $msg.Attachments.Add($att)<br />
    }<br />
  $smtp.Send($msg)<br />
  if ($Attachment -ne &#8220;&#8221;) {$att.Dispose()}<br />
}</p>
<p># get all unsealed management packs<br />
$mps = get-managementpack | where-object {$_.Sealed -eq $false -and $_.ContentReadable -eq $true}</p>
<p> foreach($mp in $mps)<br />
{ $ID = $mp.Name<br />
  $FileName = $ID + &#8220;.xml&#8221;<br />
  # Determine Revision Number from current MP<br />
  GetRevision $mp.version ([REF]$VersionFirstpartCurrent) ([REF]$RevisionCurrent)<br />
  # Retrieve the MP currently stored<br />
  # trap {&#8220;File not found &#8221; -f $_.Exception.Message}<br />
  # $fileExists = [system.IO.File]::Exists($targetFilePath + &#8220;\&#8221; + $Filename)<br />
  # If File doesn&#8217;t exist, it is a new management pack<br />
  # write-host &#8220;Filename: $fileExists &#8221;<br />
  if (-not [system.IO.File]::Exists($targetFilePath + &#8220;\&#8221; + $Filename))<br />
   { # write-host &#8220;Filename (within IF) $ID Version: $VersionFirstpartCurrent$RevisionCurrent&#8221;<br />
     $NewFileName = $targetFilePath + &#8220;\&#8221; + $FileName<br />
     export-managementpack -managementpack $mp -path $targetFilePath<br />
     ExternalCommand (&#8220;&#8221;"C:\Program Files\SVN\bin\svn.exe&#8221;"&#8221;) (&#8221; add &#8220;&#8221;$NewFilename&#8221;"&#8221;)<br />
     ExternalCommand (&#8220;&#8221;"C:\Program Files\SVN\bin\svn.exe&#8221;"&#8221;) (&#8221; commit -m &#8220;&#8221;$ID Version: $VersionFirstpartCurrent$revisionCurrent&#8221;" &#8220;&#8221;$NewFilename&#8221;"&#8221;)<br />
     # Send mail a new managementpack has been exported<br />
     write-host &#8220;a new managementpack has been exported&#8221;<br />
     $MailContent = &#8220;A new Management Pack: $Filename with Version $VersionFirstpartCurrent$revisionCurrent has been exported&#8221;<br />
     SendMail &#8220;New managementpack $Filename on $Servername in repository&#8221; $MailContent &#8220;&#8221;<br />
    }<br />
  else<br />
  {<br />
    $FileSavedMP = [system.IO.Directory]::GetFiles($targetFilePath, $Filename)<br />
    # write-host &#8220;Filename: $FileSavedMP&#8221;<br />
    # we need the file in xml format to get version info<br />
    $xmlSavedMP=[xml](get-content $FileSavedMP)<br />
    # we need the the file in text format to compare it with the current version<br />
    $txtSavedMP=(get-content $FileSavedMP)<br />
    # get version number from xml file<br />
    $xmlSavedMP.selectnodes(&#8220;/ManagementPack/Manifest/Identity&#8221;)|foreach {<br />
      $_.selectnodes(&#8220;Version&#8221;) | foreach {<br />
        $versionFile =  $_.get_InnerText()<br />
        write-host $ID $versionFile<br />
        # Determine Revision Number from file<br />
        GetRevision $versionfile ([REF]$VersionFirstpartFile) ([REF]$RevisionFile)<br />
        # check to see if version number is greater than the saved file<br />
        write-host &#8220;Revision Current version &#8221; $RevisionCurrent<br />
        write-host &#8220;Revision Saved Version &#8221; $RevisionFile<br />
        # if ($mp.version -gt $versionFile)<br />
        if ($RevisionCurrent -gt $RevisionFile)<br />
          # Current version number is higher, probably imported from another customer<br />
         { $NewFileName = $targetFilePath + &#8220;\&#8221; + $FileName<br />
	  export-managementpack -managementpack $mp -path $targetFilePath<br />
	  ExternalCommand (&#8220;&#8221;"C:\Program Files\SVN\bin\svn.exe&#8221;"&#8221;) (&#8221; commit -m &#8220;&#8221;$ID Version: $VersionFirstpartFile$revisionFile&#8221;" &#8220;&#8221;$NewFilename&#8221;"&#8221;)<br />
	  # Send mail a newer version is exported<br />
	  write-host &#8220;a newer version is exported&#8221;<br />
	  $MailContent = &#8220;Management Pack: $Filename with Version $VersionFirstpartCurrent$revisionCurrent has been updated in the repository&#8221;<br />
	  SendMail &#8220;Updated $Filename on $Servername in repository&#8221; $MailContent &#8220;&#8221;</p>
<p>        }<br />
        if ($RevisionCurrent -lt $RevisionFile)<br />
        { # Send mail could not export because saved file has higher revision number<br />
	  write-host &#8220;could not export because saved file has higher revision number&#8221;<br />
	  $MailContent = &#8220;Management Pack: $Filename with Version $VersionFirstpartFile$revisionFile could not be exported&#8221;<br />
	  SendMail &#8220;coud not export because saved file has higher revision number on $Servername&#8221; $MailContent &#8220;&#8221;<br />
        } </p>
<p>        # if version number is equal then we need to check if mgmt pack is changed<br />
        if ($RevisionCurrent -eq $RevisionFile)<br />
        { write-host &#8220;check if MP is changed&#8221;<br />
	  $TargetFilePathTemp = $targetFilePath + &#8220;\temp&#8221;<br />
	  export-managementpack -managementpack $mp -path $targetFilePathTemp<br />
          $FileCurrentMP = [system.IO.Directory]::GetFiles($targetFilePathTemp, $Filename)<br />
          $xmlCurrentMP =  [xml](get-content $FileCurrentMP)<br />
	  $txtCurrentMP =  (get-content $FileCurrentMP)<br />
          # Check if MP is changed<br />
          # write-host &#8220;Current MP Size&#8221; $FileCurrentMP.Size<br />
	  # Write-host &#8220;Saved Mp Size&#8221; $FileSavedMP.Size<br />
	  $TargetFilePathTest1 = $targetFilePath + &#8220;\test1\&#8221;<br />
	  $TargetFilePathTest2 = $targetFilePath + &#8220;\test2\&#8221;<br />
	  set-content -Encoding &#8220;Unicode&#8221; -Path $TargetFilePathTest1$Filename $txtCurrentMP<br />
	  set-content -Encoding &#8220;Unicode&#8221; -Path $TargetFilePathTest2$Filename $txtSavedMP<br />
	  # set-content -Path $TargetFilePathTest1$Filename $txtCurrentMP<br />
	  # set-content -Path $TargetFilePathTest2$Filename $txtSavedMP </p>
<p>  	  compare-object $txtCurrentMP $txtSavedMP |foreach{<br />
          if ($_.SideIndicator -eq &#8220;< =") {[string]$Differences1 = $Differences1 + $($_.InputObject)}<br />
          if ($_.SideIndicator -eq "=>&#8220;) {[string]$Differences2 = $Differences2 + $($_.InputObject)}<br />
          }</p>
<p>	  # if difference is empty, there are no changes<br />
	  if ($Differences1 -ine &#8220;&#8221; -or $Differences2 -ine &#8220;&#8221;)<br />
          { # MP is changed, we need to increment the version number<br />
	    write-host &#8220;Changes found&#8221;<br />
	    # read information from management pack<br />
	    $xmlCurrentMP.selectnodes(&#8220;/ManagementPack/Manifest/Identity&#8221;)|foreach {<br />
	    $_.selectnodes(&#8220;Version&#8221;) | foreach {<br />
	      [int]$revision = $revisionFile<br />
	      $revision++<br />
	      $NewVersion = $VersionFirstpartFile + $revision<br />
	      write-host &#8220;new version $NewVersion&#8221;<br />
	      # write new version number to file<br />
	      $_.set_InnerText($NewVersion)<br />
	      $NewFileName = $targetFilePath + &#8220;\&#8221; + $FileName<br />
	      $xmlCurrentMP.save($NewFileName)<br />
	      # write new version number to managementpack<br />
	      $mp.set_Version($NewVersion)<br />
	      $mp.AcceptChanges()<br />
#	      new-item -ItemType file -force $NewFileName -value $xmlCurrentMP<br />
#	      $xmlCurrentMP | Export-Clixml $NewFileName<br />
#	      set-content -Encoding &#8220;Unicode&#8221; -Path $NewFileName $xmlCurrentMP<br />
	      # commit changes in SVN<br />
	      ExternalCommand (&#8220;&#8221;"C:\Program Files\SVN\bin\svn.exe&#8221;"&#8221;) (&#8221; commit -m &#8220;&#8221;$ID Version: $VersionFirstpartFile$revision&#8221;" &#8220;&#8221;$NewFilename&#8221;"&#8221;)<br />
	      [string]$DiffFile = $targetFilePath + &#8220;\diff\$ID.txt&#8221;<br />
	      # Get differences from SVN<br />
	      ExternalCommand (&#8220;cmd.exe&#8221;) (&#8220;/c &#8220;&#8221;C:\Program Files\SVN\bin\svn.exe&#8221;" diff $NewFilename -r PREV >$DiffFile&#8221;)<br />
	      # get changes since last version stored in SVN<br />
	      [string]$DiffContentent = (get-content $DiffFile) </p>
<p>	      # send mail<br />
	      $MailContent = &#8220;Management Pack: $Filename Version MP: $NewVersion $DiffContentent&#8221;<br />
	      SendMail &#8220;New updates available on $Servername&#8221; $MailContent $NewFileName</p>
<p>	      # clean up<br />
	      $Differences1 = &#8220;&#8221;<br />
	      $Differences2 = &#8220;&#8221;<br />
	      }<br />
	    }<br />
          }<br />
        }<br />
      }<br />
    }<br />
  }<br />
}</p>
</blockquote>
<p>ExportUnsealedMPs_Simple.ps1</p>
<blockquote><p>
param ($ServerName)<br />
add-pssnapin “Microsoft.EnterpriseManagement.OperationsManager.Client”;<br />
set-location “OperationsManagerMonitoring::”;<br />
new-managementGroupConnection -ConnectionString:$ServerName;<br />
set-location $ServerName;</p>
<p>$mps = get-managementpack | where-object {$_.Sealed -eq $false}<br />
foreach($mp in $mps)<br />
{<br />
export-managementpack -managementpack $mp -path “E:\SVN\SCOM\UnsealedMPs”<br />
}</p>
</blockquote>
<p>ImportMPs.ps1</p>
<blockquote><p>#########################################################################################<br />
# Date: 17-01-2009        �<br />
# Version: 1.0         �<br />
#          �<br />
# Usage:    ImportMPs         �<br />
#         �<br />
# Purpose:  Script to import management packs with version control  �<br />
#     Only if a newer version is available the management pack is  �<br />
#  imported and an email is sent     �<br />
#           �<br />
#########################################################################################</p>
<p># initialize settings from config file<br />
$xmlSettings=[xml](get-content &#8220;.\SCOMSettings.xml&#8221;)<br />
$ServerName = $xmlSettings.SCOMSettings.General | %{$_.RootMS} | select-object -unique<br />
$Folder = $xmlSettings.SCOMSettings.General | %{$_.SVNControlledFolder} | select-object -unique<br />
$SMTPServer = $xmlSettings.SCOMSettings.Mail | %{$_.SMTPServer} | select-object -unique<br />
$From = $xmlSettings.SCOMSettings.Mail | %{$_.From} | select-object -unique<br />
$To = $xmlSettings.SCOMSettings.Mail | %{$_.To} | select-object -unique<br />
add-pssnapin &#8220;Microsoft.EnterpriseManagement.OperationsManager.Client&#8221;;<br />
set-location &#8220;OperationsManagerMonitoring::&#8221;;<br />
new-managementGroupConnection -ConnectionString:$ServerName;<br />
set-location $ServerName;</p>
<p>$SmtpClient = new-object system.net.mail.smtpClient<br />
$SmtpClient.host =<br />
$SmtpServer<br />
$Files = [system.IO.Directory]::GetFiles($Folder, &#8220;*.xml&#8221;)<br />
foreach($File in $Files) {<br />
Write-host &#8220;Importing &#8221; $File<br />
$xml=[xml](get-content $File)<br />
$xml.selectnodes(&#8220;/ManagementPack/Manifest&#8221;)|foreach {<br />
$_.selectnodes(&#8220;Identity/Version&#8221;) | foreach {<br />
# Check version number MP to import<br />
$versionFile =  $_.get_InnerText()<br />
[int]$countFile = $versionfile.length &#8211; ($versionFile.LastIndexOf(&#8220;.&#8221;) + 1)<br />
[int]$LastDotFile = $versionfile.length &#8211; $countFile<br />
[int]$revisionFile = $versionFile.substring($LastDotFile , $countFile)<br />
}<br />
$_.selectnodes(&#8220;Name&#8221;) | foreach {<br />
$NameFile = $_.get_InnerText()<br />
}<br />
}<br />
write-host &#8220;versionFile&#8221; $revisionFile<br />
write-host &#8220;NameFile&#8221; $NameFile</p>
<p>$mps = get-managementpack | where-object {$_.displayname -like $NameFile}</p>
<p>foreach($mp in $mps) {<br />
# Check version number current MP<br />
[string]$VersionMP = $mp.version<br />
[int]$countMP = $versionMP.length &#8211; ($versionMP.LastIndexOf(&#8220;.&#8221;) + 1)<br />
[int]$LastDotMP = $versionMP.length &#8211; $countMP<br />
[int]$revisionMP = $versionMP.substring($LastDotMP , $countMP)<br />
write-host &#8220;versionMP&#8221; $revisionMP</p>
<p>if($revisionFile -gt $revisionMP){<br />
# &#8220;File Newer, we can import&#8221;<br />
# need to set trap, to determine if import is successful<br />
trap {   &#8216;Error Category {0}, Error Type {1}, ID: {2}, Message: {3}&#8217; -f<br />
$_.CategoryInfo.Category, $_.Exception.GetType().FullName,<br />
$_.FullyQualifiedErrorID, $_.Exception.Message;   continue }<br />
install-managementpack $File<br />
if ($error) {<br />
$Title = &#8220;Something went wrong with import of $NameFile&#8221;<br />
$Body = &#8220;Name File $NameFile revision $revisionFile The Error message is: $error[0].Exception.Message&#8221;<br />
$SmtpClient.Send($from,$to,$title,$Body) �<br />
}<br />
else {  �<br />
$Title = &#8220;New updates are imported on $ServerName&#8221;<br />
$Body = &#8220;Name File &#8221; + $NameFile + &#8221; revision &#8221; + $revisionFile<br />
$SmtpClient.Send($from,$to,$title,$Body)<br />
}<br />
}<br />
if($revisionFile -lt $revisionMP){<br />
$Title = &#8220;Update of management pack failed, because of version conflict&#8221;<br />
$Body =  &#8220;Name File $NameFile  revision saved file $revisionFile Revision current MP $revisionMP&#8221;<br />
$SmtpClient.Send($from,$to,$title,$Body)<br />
}<br />
}<br />
}</p></blockquote>
<p>SCOMSettings.xml</p>
<blockquote><p>&lt;SCOMSettings ContentReadable=&#8221;true&#8221;&gt;<br />
&lt;General&gt;<br />
&lt;RootMS&gt;<em>SCOMSERVER</em>&lt;/RootMS&gt;<br />
&lt;ExportFolder&gt;<em>DRIVE</em>:\SVN\SCOM\UnsealedMPs&lt;/ExportFolder&gt;<br />
&lt;SVNControlledFolder&gt;&lt;<em>DRIVE</em>&gt;\SVN\SCOM\SVNControlledMPs&lt;/SVNControlledFolder&gt;<br />
&lt;/General&gt;<br />
&lt;Mail&gt;<br />
&lt;SMTPServer&gt;<em>MAILSERVER</em>&lt;/SMTPServer&gt;<br />
&lt;From&gt;<em>FROM</em>&lt;/From&gt;<br />
&lt;To&gt;<em>TO</em>&lt;/To&gt;<br />
&lt;/Mail&gt;<br />
&lt;/SCOMSettings&gt;</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.cupfighter.net/index.php/2009/07/system-center-operations-manager-version-control/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

