<?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>Maartendamen&#039;s blog &#187; Powershell</title>
	<atom:link href="http://www.maartendamen.com/tag/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.maartendamen.com</link>
	<description>Blogging on various IT subjects</description>
	<lastBuildDate>Tue, 22 Nov 2011 21:27:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Exchange Custom Attribute editor with GUI, written in Powershell</title>
		<link>http://www.maartendamen.com/2011/03/exchange-custom-attribute-editor-gui-written-in-powershell/</link>
		<comments>http://www.maartendamen.com/2011/03/exchange-custom-attribute-editor-gui-written-in-powershell/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 13:13:24 +0000</pubDate>
		<dc:creator>Maarten</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[custom attributes]]></category>
		<category><![CDATA[exchange]]></category>
		<category><![CDATA[microsoft]]></category>

		<guid isPermaLink="false">http://www.maartendamen.com/?p=624</guid>
		<description><![CDATA[Microsoft Exchange extends the default Active Directory schema with some additional attributes, also known as custom attributes. These extra free fields are very handy, we use them for example for third party applications,employee identification numbers etc. Recently we migrated to Exchange 2010, nice but the Exchange Management console 2010 is not supported on 32bit versions [...]]]></description>
			<content:encoded><![CDATA[<p>Microsoft Exchange extends the default Active Directory schema with some additional attributes, also known as custom attributes.<br />
These extra free fields are very handy, we use them for example for third party applications,employee identification numbers etc.<br />
Recently we migrated to Exchange 2010, nice but the Exchange Management console 2010 is not supported on 32bit versions of Windows (we still use Windows XP 32bit). The only way to edit the custom attributes is through the Microsoft Exchange Management Console.<br />
So I had two options, either give support personnel access to the one of the Exchange servers or create some script to do it. I chose the latter.<br />
This Powershell script (with a nice GUI) allows you to edit custom attributes from any workstation (either Windows XP, Windows Vista or Windows 7 32bit or whatever runs Powershell :-) )<br />
Here&#8217;s an impression of the script&#8217;s GUI:</p>
<p><span id="more-624"></span></p>
<p><a href="http://www.maartendamen.com/wp-content/uploads/2011/03/exchange_custom.png"><img src="http://www.maartendamen.com/wp-content/uploads/2011/03/exchange_custom.png" alt="" title="exchange_custom" width="613" height="495" class="alignnone size-full wp-image-652" /></a></p>
<p>And here is the (very long) Powershell code:</p>
<pre class="brush: powershell; title: ; notranslate">
######################################################################
# Exchange Custom attribute editor 1.0
# Author: Maarten Damen
######################################################################

# Script configuration
$ldapstring = &quot;ou=Users, dc=TEST, dc=NL&quot; # LDAP string, pointing to the OU with users in it.
$username   = &quot;accountmanagement&quot; # Username with sufficient rights to edit custom attributes of users.
$password   = &quot;123456&quot; # Password of that particular user.

#----------------------------------------------
# Generated Form Function
#----------------------------------------------
function GenerateForm {

	#----------------------------------------------
	#region Import Assemblies
	#----------------------------------------------
	[void][reflection.assembly]::Load(&quot;System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&quot;)
	[void][reflection.assembly]::Load(&quot;System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot;)
	[void][reflection.assembly]::Load(&quot;mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&quot;)
	[void][reflection.assembly]::Load(&quot;System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&quot;)
	#endregion

	[System.Windows.Forms.Application]::EnableVisualStyles()
	$form1 = New-Object System.Windows.Forms.Form
	$btnSave = New-Object System.Windows.Forms.Button
	$label16 = New-Object System.Windows.Forms.Label
	$label15 = New-Object System.Windows.Forms.Label
	$label14 = New-Object System.Windows.Forms.Label
	$label13 = New-Object System.Windows.Forms.Label
	$label12 = New-Object System.Windows.Forms.Label
	$label11 = New-Object System.Windows.Forms.Label
	$label10 = New-Object System.Windows.Forms.Label
	$label9 = New-Object System.Windows.Forms.Label
	$label8 = New-Object System.Windows.Forms.Label
	$label7 = New-Object System.Windows.Forms.Label
	$label6 = New-Object System.Windows.Forms.Label
	$label5 = New-Object System.Windows.Forms.Label
	$label4 = New-Object System.Windows.Forms.Label
	$label3 = New-Object System.Windows.Forms.Label
	$custom15 = New-Object System.Windows.Forms.TextBox
	$custom14 = New-Object System.Windows.Forms.TextBox
	$custom13 = New-Object System.Windows.Forms.TextBox
	$custom12 = New-Object System.Windows.Forms.TextBox
	$custom11 = New-Object System.Windows.Forms.TextBox
	$custom10 = New-Object System.Windows.Forms.TextBox
	$custom9 = New-Object System.Windows.Forms.TextBox
	$custom8 = New-Object System.Windows.Forms.TextBox
	$custom7 = New-Object System.Windows.Forms.TextBox
	$custom6 = New-Object System.Windows.Forms.TextBox
	$custom5 = New-Object System.Windows.Forms.TextBox
	$custom4 = New-Object System.Windows.Forms.TextBox
	$custom3 = New-Object System.Windows.Forms.TextBox
	$custom2 = New-Object System.Windows.Forms.TextBox
	$custom1 = New-Object System.Windows.Forms.TextBox
	$label2 = New-Object System.Windows.Forms.Label
	$listbox1 = New-Object System.Windows.Forms.ListBox
	$label1 = New-Object System.Windows.Forms.Label
	$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState

	$FormEvent_Load={
			$root = New-Object System.DirectoryServices.DirectoryEntry &quot;LDAP://$ldapstring&quot;, $username, $password
			$searcher = New-Object DirectoryServices.DirectorySearcher
			$searcher.SearchRoot = $root
			$searcher.Filter = &quot;(objectClass=user)&quot;
			$results=$searcher.FindAll()

			foreach ($result in $results) {
				$listbox1.Items.Add($result.GetDirectoryEntry().cn.Value)
			}
	}

	$handler_listbox1_SelectedIndexChanged={
		# get current custom attributes for user
		$entry = New-Object System.DirectoryServices.DirectoryEntry (&quot;LDAP://CN={0}, $ldapstring&quot; -f $listbox1.Text), $username, $password

		for ($i = 1; $i -lt 16; $i++) {
			$textbox = Get-Variable &quot;custom$i&quot;
			$propertyvalue = &quot;extensionAttribute$i&quot;
			$textbox.Value.Text = $entry.$propertyvalue.Value
		}
	}

	$handler_btnSave_Click={
		# Save changes in AD
		$entry = New-Object System.DirectoryServices.DirectoryEntry (&quot;LDAP://CN={0}, $ldapstring&quot; -f $listbox1.Text), $username, $password

		for ($i = 1; $i -lt 16; $i++) {
			$textbox = Get-Variable &quot;custom$i&quot;
			if ($textbox.Value.Text -ne &quot;&quot;) {
				$entry.Put(&quot;extensionAttribute$i&quot;, &quot;{0}&quot; -f $textbox.Value.Text)
			} else {
				$entry.PutEx(1, &quot;extensionAttribute$i&quot;, $null)
			}
		}

		$entry.SetInfo()
	}

	$Form_StateCorrection_Load=
	{
		#Correct the initial state of the form to prevent the .Net maximized form issue
		$form1.WindowState = $InitialFormWindowState
	}

	#----------------------------------------------
	#region Generated Form Code
	#----------------------------------------------
	#
	# form1
	#
	$form1.Controls.Add($btnSave)
	$form1.Controls.Add($label16)
	$form1.Controls.Add($label15)
	$form1.Controls.Add($label14)
	$form1.Controls.Add($label13)
	$form1.Controls.Add($label12)
	$form1.Controls.Add($label11)
	$form1.Controls.Add($label10)
	$form1.Controls.Add($label9)
	$form1.Controls.Add($label8)
	$form1.Controls.Add($label7)
	$form1.Controls.Add($label6)
	$form1.Controls.Add($label5)
	$form1.Controls.Add($label4)
	$form1.Controls.Add($label3)
	$form1.Controls.Add($custom15)
	$form1.Controls.Add($custom14)
	$form1.Controls.Add($custom13)
	$form1.Controls.Add($custom12)
	$form1.Controls.Add($custom11)
	$form1.Controls.Add($custom10)
	$form1.Controls.Add($custom9)
	$form1.Controls.Add($custom8)
	$form1.Controls.Add($custom7)
	$form1.Controls.Add($custom6)
	$form1.Controls.Add($custom5)
	$form1.Controls.Add($custom4)
	$form1.Controls.Add($custom3)
	$form1.Controls.Add($custom2)
	$form1.Controls.Add($custom1)
	$form1.Controls.Add($label2)
	$form1.Controls.Add($listbox1)
	$form1.Controls.Add($label1)
	$form1.Text = &quot;Exchange custom attribute editor v1.0 © Maarten Damen&quot;
	$form1.Name = &quot;form1&quot;
	$form1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$form1.ClientSize = New-Object System.Drawing.Size(606,461)
	$form1.add_Load($FormEvent_Load)
	#
	# btnSave
	#
	$btnSave.TabIndex = 32
	$btnSave.Name = &quot;btnSave&quot;
	$btnSave.Size = New-Object System.Drawing.Size(120,23)
	$btnSave.UseVisualStyleBackColor = $True
	$btnSave.Text = &quot;Save changes&quot;
	$btnSave.Location = New-Object System.Drawing.Point(474,426)
	$btnSave.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$btnSave.add_Click($handler_btnSave_Click)
	#
	# label16
	#
	$label16.TabIndex = 31
	$label16.Size = New-Object System.Drawing.Size(115,19)
	$label16.Text = &quot;Custom Attribute 15&quot;
	$label16.Location = New-Object System.Drawing.Point(173,396)
	$label16.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label16.Name = &quot;label16&quot;
	#
	# label15
	#
	$label15.TabIndex = 30
	$label15.Size = New-Object System.Drawing.Size(115,19)
	$label15.Text = &quot;Custom Attribute 14&quot;
	$label15.Location = New-Object System.Drawing.Point(173,370)
	$label15.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label15.Name = &quot;label15&quot;
	#
	# label14
	#
	$label14.TabIndex = 29
	$label14.Size = New-Object System.Drawing.Size(115,19)
	$label14.Text = &quot;Custom Attribute 13&quot;
	$label14.Location = New-Object System.Drawing.Point(173,344)
	$label14.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label14.Name = &quot;label14&quot;
	#
	# label13
	#
	$label13.TabIndex = 28
	$label13.Size = New-Object System.Drawing.Size(115,19)
	$label13.Text = &quot;Custom Attribute 12&quot;
	$label13.Location = New-Object System.Drawing.Point(173,318)
	$label13.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label13.Name = &quot;label13&quot;
	#
	# label12
	#
	$label12.TabIndex = 27
	$label12.Size = New-Object System.Drawing.Size(115,19)
	$label12.Text = &quot;Custom Attribute 11&quot;
	$label12.Location = New-Object System.Drawing.Point(173,292)
	$label12.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label12.Name = &quot;label12&quot;
	#
	# label11
	#
	$label11.TabIndex = 26
	$label11.Size = New-Object System.Drawing.Size(115,19)
	$label11.Text = &quot;Custom Attribute 10&quot;
	$label11.Location = New-Object System.Drawing.Point(173,266)
	$label11.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label11.Name = &quot;label11&quot;
	#
	# label10
	#
	$label10.TabIndex = 25
	$label10.Size = New-Object System.Drawing.Size(115,19)
	$label10.Text = &quot;Custom Attribute 9&quot;
	$label10.Location = New-Object System.Drawing.Point(173,240)
	$label10.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label10.Name = &quot;label10&quot;
	#
	# label9
	#
	$label9.TabIndex = 24
	$label9.Size = New-Object System.Drawing.Size(115,19)
	$label9.Text = &quot;Custom Attribute 8&quot;
	$label9.Location = New-Object System.Drawing.Point(173,214)
	$label9.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label9.Name = &quot;label9&quot;
	#
	# label8
	#
	$label8.TabIndex = 23
	$label8.Size = New-Object System.Drawing.Size(115,19)
	$label8.Text = &quot;Custom Attribute 7&quot;
	$label8.Location = New-Object System.Drawing.Point(173,188)
	$label8.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label8.Name = &quot;label8&quot;
	#
	# label7
	#
	$label7.TabIndex = 22
	$label7.Size = New-Object System.Drawing.Size(115,19)
	$label7.Text = &quot;Custom Attribute 6&quot;
	$label7.Location = New-Object System.Drawing.Point(173,162)
	$label7.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label7.Name = &quot;label7&quot;
	#
	# label6
	#
	$label6.TabIndex = 21
	$label6.Size = New-Object System.Drawing.Size(115,19)
	$label6.Text = &quot;Custom Attribute 5&quot;
	$label6.Location = New-Object System.Drawing.Point(173,136)
	$label6.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label6.Name = &quot;label6&quot;
	#
	# label5
	#
	$label5.TabIndex = 20
	$label5.Size = New-Object System.Drawing.Size(115,19)
	$label5.Text = &quot;Custom Attribute 4&quot;
	$label5.Location = New-Object System.Drawing.Point(173,110)
	$label5.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label5.Name = &quot;label5&quot;
	#
	# label4
	#
	$label4.TabIndex = 19
	$label4.Size = New-Object System.Drawing.Size(115,19)
	$label4.Text = &quot;Custom Attribute 3&quot;
	$label4.Location = New-Object System.Drawing.Point(173,84)
	$label4.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label4.Name = &quot;label4&quot;
	#
	# label3
	#
	$label3.TabIndex = 18
	$label3.Size = New-Object System.Drawing.Size(115,19)
	$label3.Text = &quot;Custom Attribute 2&quot;
	$label3.Location = New-Object System.Drawing.Point(173,58)
	$label3.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label3.Name = &quot;label3&quot;
	#
	# custom15
	#
	$custom15.Size = New-Object System.Drawing.Size(300,20)
	$custom15.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom15.Name = &quot;custom15&quot;
	$custom15.Location = New-Object System.Drawing.Point(294,393)
	$custom15.TabIndex = 17
	#
	# custom14
	#
	$custom14.Size = New-Object System.Drawing.Size(300,20)
	$custom14.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom14.Name = &quot;custom14&quot;
	$custom14.Location = New-Object System.Drawing.Point(294,367)
	$custom14.TabIndex = 16
	#
	# custom13
	#
	$custom13.Size = New-Object System.Drawing.Size(300,20)
	$custom13.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom13.Name = &quot;custom13&quot;
	$custom13.Location = New-Object System.Drawing.Point(294,341)
	$custom13.TabIndex = 15
	#
	# custom12
	#
	$custom12.Size = New-Object System.Drawing.Size(300,20)
	$custom12.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom12.Name = &quot;custom12&quot;
	$custom12.Location = New-Object System.Drawing.Point(294,315)
	$custom12.TabIndex = 14
	#
	# custom11
	#
	$custom11.Size = New-Object System.Drawing.Size(300,20)
	$custom11.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom11.Name = &quot;custom11&quot;
	$custom11.Location = New-Object System.Drawing.Point(294,289)
	$custom11.TabIndex = 13
	#
	# custom10
	#
	$custom10.Size = New-Object System.Drawing.Size(300,20)
	$custom10.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom10.Name = &quot;custom10&quot;
	$custom10.Location = New-Object System.Drawing.Point(294,263)
	$custom10.TabIndex = 12
	#
	# custom9
	#
	$custom9.Size = New-Object System.Drawing.Size(300,20)
	$custom9.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom9.Name = &quot;custom9&quot;
	$custom9.Location = New-Object System.Drawing.Point(294,237)
	$custom9.TabIndex = 11
	#
	# custom8
	#
	$custom8.Size = New-Object System.Drawing.Size(300,20)
	$custom8.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom8.Name = &quot;custom8&quot;
	$custom8.Location = New-Object System.Drawing.Point(294,211)
	$custom8.TabIndex = 10
	#
	# custom7
	#
	$custom7.Size = New-Object System.Drawing.Size(300,20)
	$custom7.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom7.Name = &quot;custom7&quot;
	$custom7.Location = New-Object System.Drawing.Point(294,185)
	$custom7.TabIndex = 9
	#
	# custom6
	#
	$custom6.Size = New-Object System.Drawing.Size(300,20)
	$custom6.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom6.Name = &quot;custom6&quot;
	$custom6.Location = New-Object System.Drawing.Point(294,159)
	$custom6.TabIndex = 8
	#
	# custom5
	#
	$custom5.Size = New-Object System.Drawing.Size(300,20)
	$custom5.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom5.Name = &quot;custom5&quot;
	$custom5.Location = New-Object System.Drawing.Point(294,133)
	$custom5.TabIndex = 7
	#
	# custom4
	#
	$custom4.Size = New-Object System.Drawing.Size(300,20)
	$custom4.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom4.Name = &quot;custom4&quot;
	$custom4.Location = New-Object System.Drawing.Point(294,107)
	$custom4.TabIndex = 6
	#
	# custom3
	#
	$custom3.Size = New-Object System.Drawing.Size(300,20)
	$custom3.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom3.Name = &quot;custom3&quot;
	$custom3.Location = New-Object System.Drawing.Point(294,81)
	$custom3.TabIndex = 5
	#
	# custom2
	#
	$custom2.Size = New-Object System.Drawing.Size(300,20)
	$custom2.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom2.Name = &quot;custom2&quot;
	$custom2.Location = New-Object System.Drawing.Point(294,55)
	$custom2.TabIndex = 4
	#
	# custom1
	#
	$custom1.Size = New-Object System.Drawing.Size(300,20)
	$custom1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$custom1.Name = &quot;custom1&quot;
	$custom1.Location = New-Object System.Drawing.Point(294,29)
	$custom1.TabIndex = 3
	#
	# label2
	#
	$label2.TabIndex = 2
	$label2.Size = New-Object System.Drawing.Size(100,19)
	$label2.Text = &quot;Custom Attribute 1&quot;
	$label2.Location = New-Object System.Drawing.Point(173,32)
	$label2.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label2.Name = &quot;label2&quot;
	#
	# listbox1
	#
	$listbox1.FormattingEnabled = $True
	$listbox1.Size = New-Object System.Drawing.Size(155,420)
	$listbox1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$listbox1.Name = &quot;listbox1&quot;
	$listbox1.Location = New-Object System.Drawing.Point(12,29)
	$listbox1.Sorted = $True
	$listbox1.TabIndex = 0
	$listbox1.add_SelectedIndexChanged($handler_listbox1_SelectedIndexChanged)
	#
	# label1
	#
	$label1.TabIndex = 1
	$label1.Size = New-Object System.Drawing.Size(174,23)
	$label1.Text = &quot;Please select a user:&quot;
	$label1.Location = New-Object System.Drawing.Point(12,9)
	$label1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
	$label1.Name = &quot;label1&quot;
	#endregion Generated Form Code

	#----------------------------------------------

	#Save the initial state of the form
	$InitialFormWindowState = $form1.WindowState
	#Init the OnLoad event to correct the initial state of the form
	$form1.add_Load($Form_StateCorrection_Load)
	#Show the Form
	return $form1.ShowDialog()

} #End Function

#Call OnApplicationLoad to initialize
if(OnApplicationLoad -eq $true)
{
	#Create the form
	GenerateForm | Out-Null
	#Perform cleanup
	OnApplicationExit
}
</pre>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maartendamen.com/2011/03/exchange-custom-attribute-editor-gui-written-in-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Disable hibernation on multiple Windows 2008 servers using Windows Powershell</title>
		<link>http://www.maartendamen.com/2011/02/disable-hibernation-on-multiple-windows-2008-servers-using-windows-powershell/</link>
		<comments>http://www.maartendamen.com/2011/02/disable-hibernation-on-multiple-windows-2008-servers-using-windows-powershell/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 18:18:27 +0000</pubDate>
		<dc:creator>Maarten</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[hibernation]]></category>

		<guid isPermaLink="false">http://www.maartendamen.com/?p=613</guid>
		<description><![CDATA[By default hibernation is disabled on Windows 2008 server machines. However, a file called &#8220;hiberfil.sys&#8221; (equally sized to the amount of memory in the machine) is created in the root of the system volume. On a machine with 2GB of memory, this is not a big issue. However I discovered this on a VM with [...]]]></description>
			<content:encoded><![CDATA[<p>By default hibernation is disabled on Windows 2008 server machines. However, a file called &#8220;hiberfil.sys&#8221; (equally sized to the amount of memory in the machine) is created in the root of the system volume.<br />
On a machine with 2GB of memory, this is not a big issue. However I discovered this on a VM with 12GB of memory.. *auch*<br />
After some google&#8217;ing around I found out that there&#8217;s a way to get rid of this &#8220;hiberfil.sys&#8221;, the following Microsoft KB article gives you more information about this: <a href="http://support.microsoft.com/kb/920730/en-us">http://support.microsoft.com/kb/920730/en-us</a><br />
This command disables hibernation and also get&#8217;s rid of the hiberfil.sys file:<br />
<span id="more-613"></span></p>
<pre class="brush: plain; title: ; notranslate">
powercfg.exe /h off
</pre>
<p>But what if we wanted to repeat this task for let&#8217;s say 30-40 servers? Do it by hand? No way, Powershell to the rescue!<br />
Here&#8217;s the script I came up with, enjoy:</p>
<pre class="brush: powershell; title: ; notranslate">
# Ask for credentials used to do remote WMI.
$cred    	= Get-Credential DOMAIN\account

# Filter used for active directory query. Only 2008 server machines.
$strFilter 	= &quot;(&amp;(objectClass=computer)(operatingSystem=Windows *2008*))&quot;

$objDomain 	= New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = &quot;Subtree&quot;

$colResults = $objSearcher.FindAll()

# Loop through list of servers.
foreach ($objResult in $colresults)
{
	$objItem = $objResult.Properties
	$name = $objItem.name[0]

	Write-Host &quot;Disabling hibernation on: $name&quot;

	try {
		invoke-wmimethod -cred $cred -path win32_process -name create -argumentlist &quot;powercfg.exe /h off&quot; -ComputerName $name
	}
	catch {
		Write-Host &quot;Failed to disable hibernation on: $name, no permission or server down?&quot;
		break
	}
	finally {
		Write-Host &quot;Hibernation disabled on: $name&quot;
	}
}
</pre>
<p>Onwards!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maartendamen.com/2011/02/disable-hibernation-on-multiple-windows-2008-servers-using-windows-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mass creation of HP WSEM WiFi guest accounts using SSH and PowerShell</title>
		<link>http://www.maartendamen.com/2010/07/mass-creation-of-hp-wsem-wifi-guest-accounts-using-ssh-and-powershell/</link>
		<comments>http://www.maartendamen.com/2010/07/mass-creation-of-hp-wsem-wifi-guest-accounts-using-ssh-and-powershell/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 13:58:51 +0000</pubDate>
		<dc:creator>Maarten</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[hp]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[wireless]]></category>
		<category><![CDATA[wsem]]></category>

		<guid isPermaLink="false">http://www.maartendamen.com/?p=348</guid>
		<description><![CDATA[I was asked to create 365 (1 year) of WiFi (daily) guest access accounts, and export them to CSV. Of course I didn&#8217;t want to create them by hand.. this is where PowerShell came in. I used the following PowerShell script to create random WiFi guest accounts: Special thanks to Joel Bennett&#8217;s SharpSSH wrapper for [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked to create 365 (1 year) of WiFi (daily) guest access accounts, and export them to CSV.<br />
Of course I didn&#8217;t want to create them by hand.. this is where PowerShell came in. I used the following PowerShell script to create random WiFi guest accounts:</p>
<p><span id="more-348"></span></p>
<pre class="brush: powershell; title: ; notranslate">
# Number of days to generate, default = 365
$NumDays 		= 365
$AccessGroup 	= &quot;Gasten&quot;
$ExpiryTime 	= &quot;20:00&quot;
$StartTime 		= &quot;07:00&quot;
$OutputCSV		= &quot;C:\TEMP\wireless.csv&quot;

$SshHost 		= &quot;127.0.0.1&quot;
$SshUser		= &quot;someuser&quot;

$access_codes = @()

# Start SSH session
New-SshSession $SshUser $SshHost
Invoke-Ssh &quot;z&quot;
Invoke-Ssh &quot;conf t&quot;
Invoke-Ssh &quot;wireless F&quot;
Invoke-Ssh &quot;conf t&quot;
Invoke-Ssh &quot;radius-server local&quot;

$i = 0;
do {
	# WSEM format: mm/dd/yyyy hh:mm
	$date = (Get-Date).AddDays($i)
	$date2 = Get-Date $date -Format &quot;dd-MM-yyyy&quot;
	$date = Get-Date $date -format &quot;MM:dd:yyyy&quot;
	$pass = RandomPassword 4
	$user = RandomPassword 4
	$output = &quot;rad-user $user password 0 $pass group $AccessGroup guest expiry-time $ExpiryTime expiry-date $date start-time $StartTime start-date $date&quot;

	# add user through SSH
	Invoke-ssh $output

	$Response = New-Object PSObject
	Add-Member -InputObject $Response -MemberType NoteProperty -Name &quot;Datum&quot; -Value $date2
	Add-Member -InputObject $Response -MemberType NoteProperty -Name &quot;Gebruikersnaam&quot; -Value $user
	Add-Member -InputObject $Response -MemberType NoteProperty -Name &quot;Wachtwoord&quot; -Value $pass
	$access_codes += $Response

	$i++;
} while ( $i -le $NumDays )

# Save and disconnect SSH
Invoke-ssh &quot;write mem&quot;
Remove-SshSession

# Export to CSV
$access_codes | Export-Csv $OutputCSV

# Helper functions
function RandomPassword ([int]$intPasswordLength)
{
   $strNumbers = &quot;1234567890&quot;
   $strCapitalLetters = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;
   $strLowerLetters = &quot;abcdefghijklmnopqrstuvwxyz&quot;
   $rand = new-object random

   for ($a=1; $a -le $intPasswordLength; $a++)
      {
         if ($a -gt 3)
           {
      	      $b = $rand.next(0,3) + $a
      	      $b = $b % 3 + 1
      	   } else { $b = $a }
      	 switch ($b)
      	   {
      	      &quot;1&quot; {$b = &quot;$strNumbers&quot;}
      	      &quot;2&quot; {$b = &quot;$strCapitalLetters&quot;}
      	      &quot;3&quot; {$b = &quot;$strLowerLetters&quot;}
      	   }
         $charset = $($b)
         $number = $rand.next(0,$charset.Length)
         $RandomPassword += $charset[$number]
      }
   return $RandomPassword
}
</pre>
<p>Special thanks to Joel Bennett&#8217;s SharpSSH wrapper for PowerShell (located here: <a href="http://huddledmasses.org/scriptable-ssh-from-powershell/">http://huddledmasses.org/scriptable-ssh-from-powershell/</a>) which I used to automate the command line commands for the HP WSEM.<br />
This shows the great power of PowerShell for automating virtually anything! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.maartendamen.com/2010/07/mass-creation-of-hp-wsem-wifi-guest-accounts-using-ssh-and-powershell/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Change pagefile settings on multiple servers using Powershell</title>
		<link>http://www.maartendamen.com/2010/02/powershell-script-for-changing-pagefile-settings-on-multiple-servers/</link>
		<comments>http://www.maartendamen.com/2010/02/powershell-script-for-changing-pagefile-settings-on-multiple-servers/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 19:27:32 +0000</pubDate>
		<dc:creator>Maarten</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[pagefile]]></category>

		<guid isPermaLink="false">http://www.maartendamen.com/?p=157</guid>
		<description><![CDATA[Today I wanted to change the page file settings on some of our servers (about 80), doing that by hand would take ages. That&#8217;s why I came up with the following Powershell script, the script does the following: Loop through a list of Windows 2003 servers in our active directory, only Windows 2003 machines were [...]]]></description>
			<content:encoded><![CDATA[<p>Today I wanted to change the page file settings on some of our servers (about 80), doing that by hand would take ages.<br />
That&#8217;s why I came up with the following Powershell script, the script does the following:</p>
<ul>
<li>Loop through a list of Windows 2003 servers in our active directory, only Windows 2003 machines were needed. You can easily modify the search filter though.</li>
<li>Set pagefile size on those servers, minimum size and maximum size set to &#8220;0&#8243; means the pagefile settings will be set on &#8220;system managed&#8221;</li>
</ul>
<p>So, here&#8217;s the full source of the script:<br />
<span id="more-157"></span></p>
<pre class="brush: powershell; title: ; notranslate">
# Ask for credentials to do remote WMI.
$cred    	= Get-Credential DOMAIN\Administrator

# Filter used for active directory query. Only Windows 2003 is needed, Windows 2008 defaults to system managed pagefile size.
$strFilter 	= &quot;(&amp;(objectClass=computer)(operatingSystem=Windows Server 2003))&quot;

$objDomain 	= New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = &quot;Subtree&quot;

$colResults = $objSearcher.FindAll()

# Loop through list of servers.
foreach ($objResult in $colresults)
{
	$objItem = $objResult.Properties

	$name = $objItem.name[0]

	Write-Host &quot;Setting pagefile on server: $name&quot;

	try
	{
		$PageFile = Get-WmiObject Win32_PageFileSetting -Credential $cred -ComputerName $objItem.name
		$PageFile.InitialSize = 0
		$PageFile.MaximumSize = 0
		$PageFile.Put()
	}
	catch
	{
		Write-Host &quot;Failed to set pagefile on: $name, no permission or server down?&quot;
		break
	}
	finally
	{
		Write-Host &quot;Pagefile set on: $name&quot;
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.maartendamen.com/2010/02/powershell-script-for-changing-pagefile-settings-on-multiple-servers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SCOM alert notification subscription delay sending for x minutes and don&#8217;t sent if alert is auto-resolved within that time</title>
		<link>http://www.maartendamen.com/2009/12/scom-alert-notification-subscription-delay-sending-for-x-minutes-and-dont-sent-if-alert-is-auto-resolved-within-that-time/</link>
		<comments>http://www.maartendamen.com/2009/12/scom-alert-notification-subscription-delay-sending-for-x-minutes-and-dont-sent-if-alert-is-auto-resolved-within-that-time/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 10:52:24 +0000</pubDate>
		<dc:creator>Maarten</dc:creator>
				<category><![CDATA[SCOM]]></category>
		<category><![CDATA[alerts]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[notifications]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://www.maartendamen.com/?p=40</guid>
		<description><![CDATA[In my company we are using SCOM for monitoring our server environment. Off hours we also get notified about critical alerts using a SMS/GSM modem. Using default SCOM functionality we delay the sending of notifications by 5 minutes. This works fine for alerts with a &#8220;new&#8221; state. However if an alert is closed within the [...]]]></description>
			<content:encoded><![CDATA[<p>In my company we are using SCOM for monitoring our server environment.<br />
Off hours we also get notified about critical alerts using a SMS/GSM modem.<br />
Using default SCOM functionality we delay the sending of notifications by 5 minutes. This works fine for alerts with a &#8220;new&#8221; state.<br />
However if an alert is closed within the 5 minute period a &#8220;closed&#8221; notification is sent out.<br />
We do not want to see the closed alerts if an alert auto-resolved within the 5 minute time period.  But if a new alert that has aged 5 minutes and sent to our GSM, we definately want to see that closed alert if it auto/manual resolves into the closed state (to make sure someone actually did something about the alert)</p>
<p>Using default SCOM functionality, this is not possible. This is why we came up with the following idea (special thanks to my colleague Frank):</p>
<ul>
<li>Using two seperate subscriptions, one for &#8220;new&#8221; alerts and one for &#8220;closed&#8221; alerts.</li>
<li> On the new alert subscription set a channel with a powershell script to update custom field 1 when a SMS has been sent (this subscription has the 5 minute delay)</li>
<li>On the closed alert subscription set a condition to check custom field 1 to see wheter a SMS has been sent or not.</li>
</ul>
<p>This blog post describes how this can be done within SCOM.</p>
<p><span id="more-40"></span></p>
<p><strong>1. The Command Notification Channel<br />
</strong></p>
<p>First we have to create a &#8220;Command Notification Channel&#8221;. Go to the &#8220;Administration&#8221; section of the SCOM management console. Click on Notifications-&gt;Channels.<br />
Right click and select &#8220;New-&gt;Command&#8230;&#8221;.<br />
The following wizard appears:</p>
<p><img class="size-full wp-image-45 alignnone" style="margin: 10px 0px;" title="Command Notification Channel Wizard #1" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_cmdnot1.png" alt="Command Notification Channel Wizard #1" width="680" height="244" /></p>
<p>Give the channel a name, and click &#8220;Next &gt;&#8221;</p>
<p>Enter the following settings for the channel:</p>
<p><strong>Full path of the command file:</strong><br />
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe<br />
<strong>Command line parameters:<br />
</strong><em> </em>-Command &#8220;&amp; D:\Scripts\UpdateAlertCustomField.ps1 -alertid:&#8221;$Data/Context/DataItem/AlertId$&#8221;"<br />
<strong>Startup folder for the command line:</strong><br />
D:\Scripts</p>
<p>Change D:\Scripts to reflect your PowerShell script location. It should now look like this:</p>
<p><img class="size-full wp-image-46 alignnone" title="Command Notification Channel Wizard #2" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_cmdnot2.png" alt="Command Notification Channel Wizard #2" width="468" height="167" /></p>
<p>Save the changes by clicking &#8220;Finish&#8221;</p>
<p><strong>2. The used PowerShell script</strong></p>
<p>To modify alert &#8220;custom field 1&#8243;, I use a small PowerShell script. The text written into the field is &#8220;Notification sent out&#8221;<br />
The used script is displayed here, save this script as &#8220;UpdateAlertCustomField.ps1&#8243; in the directory specified in the command notification channel above.</p>
<pre class="brush: powershell; title: ; notranslate">
# Get alertid parameter
Param($alertid)
$alertid = $alertid.toString()

# Load SCOM snap-inn
add-pssnapin &quot;Microsoft.EnterpriseManagement.OperationsManager.Client&quot;;
$server = &quot;localhost&quot;

# Connect to SCOM
new-managementGroupConnection -ConnectionString:$server;
set-location &quot;OperationsManagerMonitoring::&quot;;

# Update alert custom field
$alert = Get-Alert -id $alertid
$alert.CustomField1 = &quot;Notification sent out&quot;
$alert.Update(&quot;Custom field 1 updated by UpdateAlertCustomField script&quot;)
</pre>
<p><strong>3. A subscriber for the command</strong></p>
<p>The next step is to create a subscriber which has the command notification channel created above assigned as channel.<br />
Go to the &#8220;Administration&#8221; section of the SCOM management console. Click on Notifications-&gt;Subscribers.<br />
Right click and click &#8220;New&#8230;&#8221;</p>
<p>In the &#8220;Notification Subscriber Wizard&#8221; give the new subscriber a name. In the next step of the wizard, specify your schedule as desired.<br />
On the &#8220;Addresses&#8221; step, click &#8220;Add&#8230;&#8221; to add a new address.</p>
<p><img class="alignnone size-full wp-image-72" title="scom_notsub_add" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_notsub_add.png" alt="scom_notsub_add" width="680" height="311" /></p>
<p>In the &#8220;Subscriber Address&#8221; wizard, specify a name for the new subscriber. This can be virtually anything as no e-mails/pages/SMS messages are sent anyway.<br />
Next, specify the &#8220;Command&#8221; channel type and select the Command channel we created earlier (Update custom field 1).</p>
<p><img class="alignnone size-full wp-image-73" title="scom_subaddr" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_subaddr.png" alt="scom_subaddr" width="677" height="351" /></p>
<p>Specify your schedule as desired, click &#8220;Finish&#8221; to end the wizard. Click &#8220;Finish&#8221; again to close the &#8220;Notification Subscriber Wizard&#8221;.<br />
You should now have a subscriber with the command channel as asigned channel.</p>
<p><strong>4. The subscription for new alerts</strong></p>
<p><strong></strong>Now that we have the command notification channel, powershell script and subscriber ready. We can create a new subscription for new alerts.<br />
Go to the &#8220;Administration&#8221; section of the SCOM management console. Click on Notifications-&gt;Subscriptions.</p>
<p>In the &#8220;Notification Subscription Wizard&#8221; specify a name for the new subscription. The next wizard step is the step to define criteria for the subscription.<br />
Specify atleast the &#8220;with specific resolution state&#8221; criteria, offcourse you can add your own other criteria here like you would normally do.</p>
<p><img class="alignnone size-full wp-image-74" title="scom_notsub_wi" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_notsub_wi.png" alt="scom_notsub_wi" width="489" height="365" /></p>
<p>On the next wizard page (Subscribers) add the command subscriber we created in step 3, as shown below.</p>
<p><img class="alignnone size-full wp-image-75" title="scom_subaddr_wi2" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_subaddr_wi2.png" alt="scom_subaddr_wi2" width="477" height="237" /></p>
<p>In the next wizard step (Channels) add the command channel we created in step 1 and specify the desired delay (5 minutes in this case). As shown below:</p>
<p><img class="alignnone size-full wp-image-76" title="scom_delay" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_delay.png" alt="scom_delay" width="476" height="474" /></p>
<p>Click &#8220;Next&#8221;, in the summary step make sure &#8220;Enable this notification subscription&#8221; is checked and click &#8220;Finish&#8221;.<br />
You should now have an subscription ready for new SCOM alerts.</p>
<p><strong>5. Subscription for closed alerts</strong></p>
<p>You can create the subscription channel like you would normally do. The only important step is to get the criteria right. We have to include custom field 1.<br />
This is how the closed subscription criteria look:</p>
<p><img class="alignnone size-full wp-image-79" title="scom_notcustom" src="http://www.maartendamen.com/wp-content/uploads/2009/12/scom_notcustom.png" alt="scom_notcustom" width="483" height="393" /></p>
<p><span style="text-decoration: underline;"><strong>NOTE: there is currently a bug in SCOM R2 when using custom fields in a subscription criteria!</strong></span></p>
<p>For more information about thihs bug visit the following URL:</p>
<p><a href="http://social.technet.microsoft.com/Forums/en/operationsmanagergeneral/thread/260be16a-0f45-4904-8093-7c1caa5ed546">http://social.technet.microsoft.com/Forums/en/operationsmanagergeneral/thread/260be16a-0f45-4904-8093-7c1caa5ed546</a></p>
<p><span style="text-decoration: underline;">You have to update the xml file each time you change something in either of the notifications!</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.maartendamen.com/2009/12/scom-alert-notification-subscription-delay-sending-for-x-minutes-and-dont-sent-if-alert-is-auto-resolved-within-that-time/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>vSphere snapshot overview script (with e-mail report)</title>
		<link>http://www.maartendamen.com/2009/11/vsphere-snapshot-overview-script-with-e-mail-report/</link>
		<comments>http://www.maartendamen.com/2009/11/vsphere-snapshot-overview-script-with-e-mail-report/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 11:33:48 +0000</pubDate>
		<dc:creator>Maarten</dc:creator>
				<category><![CDATA[VMware vSphere]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[vmware]]></category>
		<category><![CDATA[vsphere]]></category>

		<guid isPermaLink="false">http://www.maartendamen.com/?p=28</guid>
		<description><![CDATA[I was looking for a way to e-mail an overview of all exisiting snapshots (on virtual machines) in our virtual environment. VMware provides an excellent powershell cmdlet pack (known as PowerCLI), you can download the latest version (as of today) here: http://blogs.vmware.com/vipowershell/2009/11/powercli-40-u1-is-out.html I used PowerCLI to write a script that does the following: Loop through [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking for a way to e-mail an overview of all exisiting snapshots (on virtual machines) in our virtual environment.<br />
VMware provides an excellent powershell cmdlet pack (known as PowerCLI), you can download the latest version (as of today) here: <a href="http://blogs.vmware.com/vipowershell/2009/11/powercli-40-u1-is-out.html">http://blogs.vmware.com/vipowershell/2009/11/powercli-40-u1-is-out.html</a></p>
<p>I used PowerCLI to write a script that does the following:</p>
<ul>
<li>Loop through all virtual machines to check if there a snapshots created for a specific virtual machine;</li>
<li>sum up all of the snapshots for a machine containing snapshots;</li>
<li>e-mail a report of the above.</li>
</ul>
<p>Here is the script:<br />
<span id="more-28"></span></p>
<pre class="brush: powershell; title: ; notranslate">
Add-PSSnapin -Name &quot;VMware.VimAutomation.Core&quot;

$VIServer = &quot;yourvirtualcenterserver.test.local&quot;
$VIUsername = &quot;DOMAIN\username&quot;
$VIPassword = &quot;password&quot;

Connect-VIServer -Server $VIServer -User $VIUsername -Password $VIPassword

$AllVirtualMachines = Get-VM

$SmtpClient = new-object system.net.mail.smtpClient
$MailMessage = New-Object system.net.mail.mailmessage 

$SmtpClient.Host = &quot;smtpserver.test.local&quot;
$MailMessage.from = &quot;notification@smtpserver.test.local&quot;
$MailMessage.To.add(&quot;address1@test.local&quot;)
$MailMessage.To.add(&quot;address2@test.local&quot;)
$MailMessage.Headers.Add(&quot;message-id&quot;, &quot;&lt;3BD50098E401463AA228377848493927-1&gt;&quot;)
$MailMessage.IsBodyHtml = 1

$MailMessage.Subject = &quot;VMware snapshot overview&quot;
$MailMessage.Body += &quot;&lt;FONT FACE='Arial, Helvetica, Geneva'&gt;&lt;h2&gt;VMware snapshot overview:&lt;/h2&gt;&lt;br&gt;&quot;

foreach ($VirtualMachine in $AllVirtualMachines)
{
	$AllSnapshots=Get-Snapshot -VM $VirtualMachine

	if ($AllSnapshots.count -gt 0)
	{
		$MailMessage.Body += &quot;&lt;b&gt;&quot; + $VirtualMachine + &quot;&lt;/b&gt;&lt;br&gt;&quot;
		foreach ($Snapshot in $AllSnapshots)
		{
			If ($Snapshot.ID -like &quot;VirtualMachineSnapshot-*&quot;)
			{
				$MailMessage.Body += $Snapshot.Created, $Snapshot.Name, $Snapshot.Description + &quot;&lt;br&gt;&quot;
			}
		}
		$MailMessage.Body += &quot;&lt;br&gt;&quot;
	}
}
$MailMessage.Body += &quot;&lt;/font&gt;&quot;
$SmtpClient.Send($MailMessage)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.maartendamen.com/2009/11/vsphere-snapshot-overview-script-with-e-mail-report/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

