Thursday, June 17, 2010

Updating a Extended property based on Group Membership Powershell GUI

Group membership has long been used in directory services to provide a way of giving access to different objects, distribution lists and a variety of other useful things to solve everyday problems in both active directory and Exchange Infrastructures. There are a number of things that you can’t do with Groups in Exchange which can be slightly limiting if you’re trying to solve certain problems in an easy and flexible manner. Exchange provides a whole bunch of extended properties in Active directory that can be used for various things one of the more useful of this is being able to apply a specific proxyaddress based on a specific value set in a extended property via a recipient policy. It can also be useful in Transport Agents and Transport Rules and a number of different application uses.

For example in most mail systems you will have logical grouping of users into distribution lists maybe loosely based on department function etc. If for example your sales department want to use a specific sub domain for a specific promotion they are running let’s call it @worldcup.youdomain.com and you want this to apply to everybody in the sales department (who are in for example a sales distribution list) then this is the script that could help you out.

What this script does is first provides a search mechanism to find a group based on its name using ADSI. Once the group is found you can then view its membership and show any current extended properties that are set. There is an export button so you can export any of the current settings for users that are show in the grid. To use this script you need to select the group you want to affect in the left hand grid select the property you want to set from the combo box and put the value in you want set for all user in the group and hit update.The script will then go through and set the property using ADSI on every member of the group. The script does a nested group query so will affect every member of the group and any members of nested groupd.

The show member’s query will show you all the users that it will affect.

I’ve put a download of this script here the script itself looks like.

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$form = new-object System.Windows.Forms.form

$repeathashGroup = @{ }
$repeathashUser = @{ }

function Get-member($GroupName){
$Grouppath = "LDAP://" + $GroupName
$groupObj = [ADSI]$Grouppath
foreach($member in $groupObj.Member){
$userPath = "LDAP://" + $member
$UserObj = [ADSI]$userPath
if($UserObj.groupType.Value -eq $null){
if($repeathashUser.ContainsKey($UserObj.distinguishedName.ToString()) -eq $false){
$repeathashUser.add($UserObj.distinguishedName.ToString(),1)
$grTable.Rows.Add($UserObj.DisplayName.ToString(),$UserObj.extensionAttribute1.Value,`
$UserObj.extensionAttribute2.Value,$UserObj.extensionAttribute3.Value,$UserObj.extensionAttribute4.Value,$UserObj.extensionAttribute5.Value,`
$UserObj.extensionAttribute6.Value,$UserObj.extensionAttribute7.Value,$UserObj.extensionAttribute8.Value,$UserObj.extensionAttribute9.Value,`
$UserObj.extensionAttribute10.Value,$UserObj.extensionAttribute11.Value,`
$UserObj.extensionAttribute12.Value,$UserObj.extensionAttribute13.Value,$UserObj.extensionAttribute14.Value,$UserObj.extensionAttribute15.Value)
}

}
else{
if($repeathashGroup.ContainsKey($UserObj.distinguishedName.ToString()) -eq $false){
$repeathashGroup.add($UserObj.distinguishedName.ToString(),1)
Get-member($UserObj.distinguishedName)
}
}
}
$dgDataGrid2.DataSource = $grTable
}

function Update-member($GroupName){
#Warn first
$buttons=[system.windows.forms.messageboxbuttons]::yesno
$return = ""
$return = [system.windows.forms.messagebox]::Show("This will set the selected Extended Properties for all members of the group and nested Groups do you want to proceed","",$buttons)
if ($return -eq [Windows.Forms.DialogResult]::Yes){
$Grouppath = "LDAP://" + $GroupName
$groupObj = [ADSI]$Grouppath
foreach($member in $groupObj.Member){
$userPath = "LDAP://" + $member
$UserObj = [ADSI]$userPath
if($UserObj.groupType.Value -eq $null){
if($repeathashUser.ContainsKey($UserObj.distinguishedName.ToString()) -eq $false){
$propname = $exPropDrop.SelectedItem.ToString()
$repeathashUser.add($UserObj.distinguishedName.ToString(),1)
$UserObj.$propname = $uvtext.Text
$UserObj.SetInfo()
}

}
else{
if($repeathashGroup.ContainsKey($UserObj.distinguishedName.ToString()) -eq $false){
$repeathashGroup.add($UserObj.distinguishedName.ToString(),1)
Update-member($UserObj.distinguishedName)
}
}
}
}
else{
[system.windows.forms.messagebox]::Show("Update Aborted")
}
$grTable.Clear()
$repeathashUser.clear()
$repeathashGroup.clear()
Get-member($msTable.DefaultView[$dgDataGrid.CurrentCell.RowIndex][1])

}

function ExportGrid(){
$exFileName = new-object System.Windows.Forms.saveFileDialog
$exFileName.DefaultExt = "csv"
$exFileName.Filter = "csv files (*.csv)|*.csv"
$exFileName.InitialDirectory = "c:\temp"
$exFileName.ShowHelp = $true
$exFileName.ShowDialog()
if ($exFileName.FileName -ne ""){
$logfile = new-object IO.StreamWriter($exFileName.FileName,$true)
$logfile.WriteLine("MemberName,extensionAttribute1,extensionAttribute2,extensionAttribute3,extensionAttribute4,extensionAttribute5,extensionAttribute6,extensionAttribute7,extensionAttribute8,extensionAttribute9,extensionAttribute10,extensionAttribute11,extensionAttribute12,extensionAttribute13,extensionAttribute14,extensionAttribute15")
foreach($row in $grTable.Rows){
$logfile.WriteLine("`"" + $row[0].ToString() + "`"," + $row[1].ToString() + "," + $row[2].ToString() + "," + $row[3].ToString() + "," + $row[4].ToString()+ "," + $row[5].ToString() + "," + $row[6].ToString() + "," + $row[7].ToString() + "," + $row[8].ToString()`
+ "," + $row[9].ToString() + "," + $row[10].ToString() + "," + $row[11].ToString() + "," + $row[12].ToString() + "," + $row[13].ToString() + "," + $row[14].ToString() + "," + $row[15].ToString())
}
$logfile.Close()
}

}

function SearchfoGroup(){
$msTable.clear()
$root = [ADSI]'LDAP://RootDSE'
if ($rbSearchDWide.Checked -eq $true){
$dfDefaultRootPath = "LDAP://" + $root.DefaultNamingContext.tostring()
}
else{
$dfDefaultRootPath = "LDAP://" + $ouOUNameDrop.SelectedItem.ToString()
}
$dfRoot = [ADSI]$dfDefaultRootPath
$gfGALQueryFilter = "(&(objectClass=group)(displayName=" + $pnProxyAddress.Text + "*))"
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($dfRoot)
if($ouOUCheckBox.Checked -eq $false -band $rbSearchDWide.Checked -eq $false){$dfsearcher.SearchScope = "OneLevel"}
$dfsearcher.Filter = $gfGALQueryFilter
$srSearchResult = $dfsearcher.FindAll()
foreach ($emResult in $srSearchResult) {
$unUserobject = New-Object System.DirectoryServices.directoryentry
$unUserobject = $emResult.GetDirectoryEntry()
$msTable.Rows.Add($unUserobject.DisplayName.ToString(),$unUserobject.distinguishedName.ToString())

}
$dgDataGrid.DataSource = $msTable

}

$msTable = New-Object System.Data.DataTable
$msTable.TableName = "GroupName"
$msTable.Columns.Add("GroupName")
$msTable.Columns.Add("DistinguishedName")

$grTable = New-Object System.Data.DataTable
$grTable.TableName = "Members"
$grTable.Columns.Add("MemberName")
$grTable.Columns.Add("extensionAttribute1")
$grTable.Columns.Add("extensionAttribute2")
$grTable.Columns.Add("extensionAttribute3")
$grTable.Columns.Add("extensionAttribute4")
$grTable.Columns.Add("extensionAttribute5")
$grTable.Columns.Add("extensionAttribute6")
$grTable.Columns.Add("extensionAttribute7")
$grTable.Columns.Add("extensionAttribute8")
$grTable.Columns.Add("extensionAttribute9")
$grTable.Columns.Add("extensionAttribute10")
$grTable.Columns.Add("extensionAttribute11")
$grTable.Columns.Add("extensionAttribute12")
$grTable.Columns.Add("extensionAttribute13")
$grTable.Columns.Add("extensionAttribute14")
$grTable.Columns.Add("extensionAttribute15")



# Add RadioButtons
$rbSearchDWide = new-object System.Windows.Forms.RadioButton
$rbSearchDWide.Location = new-object System.Drawing.Size(20,20)
$rbSearchDWide.size = new-object System.Drawing.Size(150,17)
$rbSearchDWide.Checked = $true
$rbSearchDWide.Text = "Search Domain Wide"
$rbSearchDWide.Add_Click({if ($rbSearchDWide.Checked -eq $true){$ouOUNameDrop.Enabled = $false}})
$form.Controls.Add($rbSearchDWide)

$rbSearchOUWide = new-object System.Windows.Forms.RadioButton
$rbSearchOUWide.Location = new-object System.Drawing.Size(20,60)
$rbSearchOUWide.size = new-object System.Drawing.Size(150,17)
$rbSearchOUWide.Checked = $false
$rbSearchOUWide.Add_Click({if ($rbSearchDWide.Checked -eq $false){$ouOUNameDrop.Enabled = $true}})
$rbSearchOUWide.Text = "Search within OU"
$form.Controls.Add($rbSearchOUWide)


$OulableBox = new-object System.Windows.Forms.Label
$OulableBox.Location = new-object System.Drawing.Size(220,60)
$OulableBox.size = new-object System.Drawing.Size(120,20)
$OulableBox.Text = "Select OU Name : "
$form.controls.Add($OulableBox)

# Add OU Drop Down
$ouOUNameDrop = new-object System.Windows.Forms.ComboBox
$ouOUNameDrop.Location = new-object System.Drawing.Size(360,60)
$ouOUNameDrop.Size = new-object System.Drawing.Size(350,30)
$ouOUNameDrop.Enabled = $false
$root = [ADSI]'LDAP://RootDSE'
$dfDefaultRootPath = "LDAP://" + $root.DefaultNamingContext.tostring()
$dfRoot = [ADSI]$dfDefaultRootPath
$gfGALQueryFilter = "(objectClass=organizationalUnit)"
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($dfRoot)
$dfsearcher.Filter = $gfGALQueryFilter
$srSearchResult = $dfsearcher.FindAll()
foreach ($emResult in $srSearchResult) {
$OUobject = New-Object System.DirectoryServices.directoryentry
$OUobject = $emResult.GetDirectoryEntry()
$ouOUNameDrop.Items.Add($OUobject.distinguishedName.ToString())
}
$form.Controls.Add($ouOUNameDrop)

# Add Prop Drop Down
$exPropDrop = new-object System.Windows.Forms.ComboBox
$exPropDrop.Location = new-object System.Drawing.Size(240,580)
$exPropDrop.Size = new-object System.Drawing.Size(150,30)
$exPropDrop.Items.Add("extensionAttribute1")
$exPropDrop.Items.Add("extensionAttribute2")
$exPropDrop.Items.Add("extensionAttribute3")
$exPropDrop.Items.Add("extensionAttribute4")
$exPropDrop.Items.Add("extensionAttribute5")
$exPropDrop.Items.Add("extensionAttribute6")
$exPropDrop.Items.Add("extensionAttribute7")
$exPropDrop.Items.Add("extensionAttribute8")
$exPropDrop.Items.Add("extensionAttribute9")
$exPropDrop.Items.Add("extensionAttribute10")
$exPropDrop.Items.Add("extensionAttribute11")
$exPropDrop.Items.Add("extensionAttribute12")
$exPropDrop.Items.Add("extensionAttribute13")
$exPropDrop.Items.Add("extensionAttribute14")
$exPropDrop.Items.Add("extensionAttribute15")
$form.Controls.Add($exPropDrop)

$exlableBox = new-object System.Windows.Forms.Label
$exlableBox.Location = new-object System.Drawing.Size(20,580)
$exlableBox.size = new-object System.Drawing.Size(240,20)
$exlableBox.Text = "Extended Property to Set/Update : "
$form.controls.Add($exlableBox)

$exlableBox2 = new-object System.Windows.Forms.Label
$exlableBox2.Location = new-object System.Drawing.Size(20,610)
$exlableBox2.size = new-object System.Drawing.Size(150,20)
$exlableBox2.Text = "Value : "
$form.controls.Add($exlableBox2)


$uvtext = new-object System.Windows.Forms.TextBox
$uvtext.Location = new-object System.Drawing.Size(240,610)
$uvtext.size = new-object System.Drawing.Size(300,20)
$form.controls.Add($uvtext)


$ProxyAddresslableBox = new-object System.Windows.Forms.Label
$ProxyAddresslableBox.Location = new-object System.Drawing.Size(20,100)
$ProxyAddresslableBox.size = new-object System.Drawing.Size(320,20)
$ProxyAddresslableBox.Text = "Group to Search for"
$form.controls.Add($ProxyAddresslableBox)

$ouOUCheckBox = new-object System.Windows.Forms.CheckBox
$ouOUCheckBox.Location = new-object System.Drawing.Size(750,60)
$ouOUCheckBox.Size = new-object System.Drawing.Size(200,20)
$ouOUCheckBox.Checked = $true
$ouOUCheckBox.Text = "Search in Sub OU's"
$form.Controls.Add($ouOUCheckBox)


# Add ProxyDomain Text Box
$pnProxyAddress = new-object System.Windows.Forms.TextBox
$pnProxyAddress.Location = new-object System.Drawing.Size(350,100)
$pnProxyAddress.size = new-object System.Drawing.Size(300,20)
$form.controls.Add($pnProxyAddress)


$exButton1 = new-object System.Windows.Forms.Button
$exButton1.Location = new-object System.Drawing.Size(700,100)
$exButton1.Size = new-object System.Drawing.Size(125,20)
$exButton1.Text = "Search"
$exButton1.Add_Click({SearchfoGroup})
$form.Controls.Add($exButton1)

$exButton3 = new-object System.Windows.Forms.Button
$exButton3.Location = new-object System.Drawing.Size(320,150)
$exButton3.Size = new-object System.Drawing.Size(105,20)
$exButton3.Text = "Show Members"
$exButton3.Add_Click({$grTable.clear()
$repeathashUser.clear()
$repeathashGroup.clear()
Get-member($msTable.DefaultView[$dgDataGrid.CurrentCell.RowIndex][1])
})
$form.Controls.Add($exButton3)

# Add Update Button

$exButton2 = new-object System.Windows.Forms.Button
$exButton2.Location = new-object System.Drawing.Size(10,640)
$exButton2.Size = new-object System.Drawing.Size(125,20)
$exButton2.Text = "Set/Update Value"
$exButton2.Add_Click({
$repeathashUser.clear()
$repeathashGroup.clear()
update-member($msTable.DefaultView[$dgDataGrid.CurrentCell.RowIndex][1])
})
$form.Controls.Add($exButton2)


# Add Export Grid Button

$exButton4 = new-object System.Windows.Forms.Button
$exButton4.Location = new-object System.Drawing.Size(700,550)
$exButton4.Size = new-object System.Drawing.Size(125,20)
$exButton4.Text = "Export Grid"
$exButton4.Add_Click({ExportGrid})
$form.Controls.Add($exButton4)

# Add DataGrid View

$dgDataGrid = new-object System.windows.forms.DataGridView
$dgDataGrid.Location = new-object System.Drawing.Size(10,145)
$dgDataGrid.size = new-object System.Drawing.Size(300,400)
$dgDataGrid.AutoSizeRowsMode = "AllHeaders"
$form.Controls.Add($dgDataGrid)

# Add DataGrid View

$dgDataGrid2 = new-object System.windows.forms.DataGridView
$dgDataGrid2.Location = new-object System.Drawing.Size(440,145)
$dgDataGrid2.size = new-object System.Drawing.Size(400,400)
$dgDataGrid2.AutoSizeRowsMode = "AllHeaders"
$form.Controls.Add($dgDataGrid2)


$form.Text = "Group Extended Propery Update GUI"
$form.size = new-object System.Drawing.Size(1200,800)
$form.autoscroll = $true
$form.Add_Shown({$form.Activate()})
$form.ShowDialog()

Wednesday, June 09, 2010

Enumerting the members of a nested group with ADSI and powershell

Its often useful with scripts and applications to be able to use Group membership to control what users are affected by a particular application or script. Enumerating nested group members in powershell seems to be a bit of art and there are few different approaches none of which i particular liked so i came up with my own. The following approach uses two hash tables to ensure that if a user is in multiple groups they only get enumerated once and also any circular group nesting are taken care of as well seems to work well for me so i thought I'd share it.

In the case of this script he $groupName is the DistiguishedName of the Group you want to enumerate the members of.

$repeathashGroup = @{ }
$repeathashUser = @{ }

function Get-member($GroupName){
$Grouppath = "LDAP://" + $GroupName
$groupObj = [ADSI]$Grouppath
foreach($member in $groupObj.Member){
$userPath = "LDAP://" + $member
$UserObj = [ADSI]$userPath
if($UserObj.groupType.Value -eq $null){
if($repeathashUser.ContainsKey($UserObj.distinguishedName.ToString()) -eq $false){
$repeathashUser.add($UserObj.distinguishedName.ToString(),1)
$UserObj.distinguishedName.ToString()

}

}
else{
if($repeathashGroup.ContainsKey($UserObj.distinguishedName.ToString()) -eq $false){
$repeathashGroup.add($UserObj.distinguishedName.ToString(),1)
Get-member($UserObj.distinguishedName)
}
}
}
}

Friday, June 04, 2010

Exchange proxyaddress display and removal powershell gui for Exchange 2003,2007,2010

ProxyAddresses are something in Exchange environments that can be a challenge to maintain over a long period of time and also during migrations or consolidations something that you need to deal with. If your lucky then just modifying your recipient policies may work the magic that you need if not and you have a large number of users that you need to modify you need to look at creating a script or doing a lot of mouse work.

The first challenge if your going to write a script to do this is because your going to be deleting information just doing a one-liner or simple script may mean you will end up removing more information than you want. So one way to tackle this is using a simple GUI script that will allow mutiple selects to at least control what and which accounts you are going to affect. The good thing about createing a simple Gui is that it can also be used to do some analysis first. So the script i've created allows you to search based on the proxy address domain you want to look at and also limit what branch of your domain you want to query eg the whole domain, OU or subtree OU query. It also has the ability to export the search results.

A few other things about this script is that it uses ADSI so should work against any version of Exchange. It uses Putex so it should only affect one entry in the proxyaddresses array (hopefully the one your targeting to delete) which is hopefully a little safer then some approachs simular scrisst take of rewriting the whole proxyaddresses object which if it goes wrong can get ugly.

The ldap query the script uses does a wildcard smtp* + the domain you want to search so it will match a full or partial match. There is also some code to stop you deleting any proxyaddresses that may be the primary email address which should be avoided.

To use the script you need to put the domain you want to search for in the format @proxyaddress.com and then click search. This should find any accounts with that paricular proxy addresses. To delete specific proxy address you need to select the row fully and click the delete button. The script is latched by default so will prompt on every deletetion there is a checkbox to disable this (but do so with great care).

Note this script if for demostration purposes only and has had no real testing so is only sutible for test enviroments. I've put a download of the script here

The script itself looks like

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$form = new-object System.Windows.Forms.form

function SearchforProxy(){
if ($pnProxyAddress.Text -match "@"){
$msTable.clear()
$root = [ADSI]'LDAP://RootDSE'
if ($rbSearchDWide.Checked -eq $true){
$dfDefaultRootPath = "LDAP://" + $root.DefaultNamingContext.tostring()
}
else{
$dfDefaultRootPath = "LDAP://" + $ouOUNameDrop.SelectedItem.ToString()
}
$dfRoot = [ADSI]$dfDefaultRootPath
$gfGALQueryFilter = "(&(&(&(&(!mailnickname=systemmailbox*)(objectCategory=person)(objectClass=user)(proxyAddresses=smtp:*" + $pnProxyAddress.Text + ")))))"
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($dfRoot)
if($ouOUCheckBox.Checked -eq $false -band $rbSearchDWide.Checked -eq $false){$dfsearcher.SearchScope = "OneLevel"}
$dfsearcher.Filter = $gfGALQueryFilter
$srSearchResult = $dfsearcher.FindAll()
foreach ($emResult in $srSearchResult) {
$unUserobject = New-Object System.DirectoryServices.directoryentry
$unUserobject = $emResult.GetDirectoryEntry()
$address = ""
$userName = ""
$mail = ""
$prxfound = ""
foreach($prxaddress in $unUserobject.ProxyAddresses){
$sstring = "*" + $pnProxyAddress.Text
if ($prxaddress -like $sstring){
if($prxfound -eq ""){$prxfound = $prxaddress}
else{$prxfound = $prxfound + ";" + $prxaddress}

}
if ($address -eq ""){$address = $prxaddress}
else{$address = $address + ";" + $prxaddress}
}
if ($unUserobject.Mail -ne $null){$mail = $unUserobject.Mail.ToString()}
$msTable.Rows.Add($unUserobject.SamaccountName.ToString(),$mail,$prxfound,$unUserobject.psbase.Parent.Name.ToString(),$address,$unUserobject.distinguishedName.ToString())

}
$dgDataGrid.DataSource = $msTable
}
else{
$msgstring = "Address format incorrect it must contain @ sign"
$a = new-object -comobject wscript.shell
$b = $a.popup($msgstring,0,"Warning",1)

}
}

function ExportGrid(){
$exFileName = new-object System.Windows.Forms.saveFileDialog
$exFileName.DefaultExt = "csv"
$exFileName.Filter = "csv files (*.csv)|*.csv"
$exFileName.InitialDirectory = "c:\temp"
$exFileName.ShowHelp = $true
$exFileName.ShowDialog()
if ($exFileName.FileName -ne ""){
$logfile = new-object IO.StreamWriter($exFileName.FileName,$true)
$logfile.WriteLine("UserName,Primary-EmailAddress,ProxyAddres-Found,OU,ProxyAddresses,distinguishedName")
foreach($row in $msTable.Rows){
$logfile.WriteLine("`"" + $row[0].ToString() + "`"," + $row[1].ToString() + "," + $row[2].ToString() + "," + $row[3].ToString() + "," + $row[4].ToString()+ $row[5].ToString())
}
$logfile.Close()
}

}

function DeletedSelected(){
if ($dgDataGrid.SelectedRows.Count -eq 0){
$msgstring = "Now Rows Selected"
$a = new-object -comobject wscript.shell
$b = $a.popup($msgstring,0,"Warning",1)
}
else{
$buttons=[system.windows.forms.messageboxbuttons]::yesno
$return = ""
$return = [system.windows.forms.messagebox]::Show("This will remove the Selected Proxy Addresses Click Yes to Procced","",$buttons)
if ($return -eq [Windows.Forms.DialogResult]::Yes){
$lcLoopCount = 0
while ($lcLoopCount -le ($dgDataGrid.SelectedRows.Count-1)) {

$UserDN = "LDAP://" + $dgDataGrid.SelectedRows[$lcLoopCount].Cells[5].Value
$userObject = [ADSI]$UserDN
$sstring = "*" + $pnProxyAddress.Text
foreach($prxaddress in $userObject.ProxyAddresses){
if ($prxaddress -like $sstring){
if($prxaddress -cmatch "SMTP:") {
$Message = "Not Deleteing " + $prxaddress + " as this is the primary SMTP address"
[system.windows.forms.messagebox]::Show($Message)
}
else{
$Message = "Deleteing the following proxy Address's`r`n`r`n" + $prxaddress + "`r`n`r`nFrom " + $userObject.DisplayName.ToString()
$mreturn = ""
if ($cmfCheckBox.Checked -eq $true){
$mreturn = [system.windows.forms.messagebox]::Show($Message,"",$buttons)
if ($mreturn -eq [Windows.Forms.DialogResult]::Yes){
$userObject.PutEx(4, 'proxyAddresses', @("$prxaddress"))
$userObject.setinfo()
}
}
else{
$userObject.PutEx(4, 'proxyAddresses', @("$prxaddress"))
$userObject.setinfo()
}
}
}
}
$lcLoopCount += 1
}
}
else {[system.windows.forms.messagebox]::Show("Not proceeding with delete") }
SearchforProxy

}


}

$msTable = New-Object System.Data.DataTable
$msTable.TableName = "ProxyAddress"
$msTable.Columns.Add("UserName")
$msTable.Columns.Add("Primary-EmailAddress")
$msTable.Columns.Add("ProxyAddress-Found")
$msTable.Columns.Add("OU")
$msTable.Columns.Add("ProxyAddresses")
$msTable.Columns.Add("distinguishedName")


# Add RadioButtons
$rbSearchDWide = new-object System.Windows.Forms.RadioButton
$rbSearchDWide.Location = new-object System.Drawing.Size(20,20)
$rbSearchDWide.size = new-object System.Drawing.Size(150,17)
$rbSearchDWide.Checked = $true
$rbSearchDWide.Text = "Search Domain Wide"
$rbSearchDWide.Add_Click({if ($rbSearchDWide.Checked -eq $true){$ouOUNameDrop.Enabled = $false}})
$form.Controls.Add($rbSearchDWide)

$rbSearchOUWide = new-object System.Windows.Forms.RadioButton
$rbSearchOUWide.Location = new-object System.Drawing.Size(20,60)
$rbSearchOUWide.size = new-object System.Drawing.Size(150,17)
$rbSearchOUWide.Checked = $false
$rbSearchOUWide.Add_Click({if ($rbSearchDWide.Checked -eq $false){$ouOUNameDrop.Enabled = $true}})
$rbSearchOUWide.Text = "Search within OU"
$form.Controls.Add($rbSearchOUWide)


$OulableBox = new-object System.Windows.Forms.Label
$OulableBox.Location = new-object System.Drawing.Size(220,60)
$OulableBox.size = new-object System.Drawing.Size(120,20)
$OulableBox.Text = "Select OU Name : "
$form.controls.Add($OulableBox)

# Add OU Drop Down
$ouOUNameDrop = new-object System.Windows.Forms.ComboBox
$ouOUNameDrop.Location = new-object System.Drawing.Size(360,60)
$ouOUNameDrop.Size = new-object System.Drawing.Size(350,30)
$ouOUNameDrop.Enabled = $false
$root = [ADSI]'LDAP://RootDSE'
$dfDefaultRootPath = "LDAP://" + $root.DefaultNamingContext.tostring()
$dfRoot = [ADSI]$dfDefaultRootPath
$gfGALQueryFilter = "(objectClass=organizationalUnit)"
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($dfRoot)
$dfsearcher.Filter = $gfGALQueryFilter
$srSearchResult = $dfsearcher.FindAll()
foreach ($emResult in $srSearchResult) {
$OUobject = New-Object System.DirectoryServices.directoryentry
$OUobject = $emResult.GetDirectoryEntry()
$ouOUNameDrop.Items.Add($OUobject.distinguishedName.ToString())
}
$form.Controls.Add($ouOUNameDrop)

$ProxyAddresslableBox = new-object System.Windows.Forms.Label
$ProxyAddresslableBox.Location = new-object System.Drawing.Size(20,100)
$ProxyAddresslableBox.size = new-object System.Drawing.Size(320,20)
$ProxyAddresslableBox.Text = "Proxy Address to Search (eg @proxydomain.com)"
$form.controls.Add($ProxyAddresslableBox)

$ouOUCheckBox = new-object System.Windows.Forms.CheckBox
$ouOUCheckBox.Location = new-object System.Drawing.Size(750,60)
$ouOUCheckBox.Size = new-object System.Drawing.Size(200,20)
$ouOUCheckBox.Checked = $true
$ouOUCheckBox.Text = "Search in Sub OU's"
$form.Controls.Add($ouOUCheckBox)


# Add ProxyDomain Text Box
$pnProxyAddress = new-object System.Windows.Forms.TextBox
$pnProxyAddress.Location = new-object System.Drawing.Size(350,100)
$pnProxyAddress.size = new-object System.Drawing.Size(300,20)
$form.controls.Add($pnProxyAddress)

$exButton1 = new-object System.Windows.Forms.Button
$exButton1.Location = new-object System.Drawing.Size(700,100)
$exButton1.Size = new-object System.Drawing.Size(125,20)
$exButton1.Text = "Search"
$exButton1.Add_Click({SearchforProxy})
$form.Controls.Add($exButton1)

# Add Export Grid Button

$exButton2 = new-object System.Windows.Forms.Button
$exButton2.Location = new-object System.Drawing.Size(10,760)
$exButton2.Size = new-object System.Drawing.Size(125,20)
$exButton2.Text = "Export Grid"
$exButton2.Add_Click({ExportGrid})
$form.Controls.Add($exButton2)

# Add Export Grid Button

$exButton3 = new-object System.Windows.Forms.Button
$exButton3.Location = new-object System.Drawing.Size(250,760)
$exButton3.Size = new-object System.Drawing.Size(300,20)
$exButton3.Text = "Deleted Select Proxy Addresses"
$exButton3.Add_Click({DeletedSelected})
$form.Controls.Add($exButton3)

$cmfCheckBox = new-object System.Windows.Forms.CheckBox
$cmfCheckBox.Location = new-object System.Drawing.Size(600,760)
$cmfCheckBox.Size = new-object System.Drawing.Size(200,20)
$cmfCheckBox.Checked = $true
$cmfCheckBox.Text = "Confirm Each removal"
$form.Controls.Add($cmfCheckBox)


# Add DataGrid View

$dgDataGrid = new-object System.windows.forms.DataGridView
$dgDataGrid.Location = new-object System.Drawing.Size(10,145)
$dgDataGrid.size = new-object System.Drawing.Size(1000,600)
$dgDataGrid.AutoSizeRowsMode = "AllHeaders"
$form.Controls.Add($dgDataGrid)

$form.Text = "Proxy Address Search and Remove Form"
$form.size = new-object System.Drawing.Size(1200,750)
$form.autoscroll = $true
$form.Add_Shown({$form.Activate()})
$form.ShowDialog()