Powershell & DHCP Scopes

Really quick one this; I had a DHCP server with 136 scopes on it that I needed to disable and so the following script was born. It takes 1 argument – the hostname of the DHCP server in question; leave blank for localhost:

#DHCP Server-wide scope disabler
#Adam Beardwood 16/02/2010
#v1.0 - Initial Release
Disables all DHCP scopes on the specified server
DNS name or IP of server to work with
	[Parameter(Mandatory=$false,ParameterSetName="Server",ValueFromPipelineByPropertyName=$true,Position=0,Helpmessage="DNS name or IP of server to work with")]$Server = "localhost"
$Server = "\\$Server"
$scopes = netsh dhcp server $server show scope
foreach($scope in $scopes){
$regex = [regex]"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
$ip = $scope | foreach {$regex.Matches($_) | foreach {$_.Captures[0].Value}}
if($ip -ne $null){
& netsh dhcp server $server scope $ip[0] set state 0

Sophos/Utimaco Safeguard Auto-Sync Script

Those of you who have used Safeguard will know that for reasons known only to the Germans, Utimaco decided not to provide any way to automatically sync Safeguard with your AD domain(s) without resorting to a rather buggy API. They provide some example code for VBScript, but if you want to do it in Powershell instead, look no further:

#Safeguard Directory Synchronisation Tool
#Adam Beardwood 04/02/2010
#v1.0 - Initial Release
#Load Safeguard .NET Assembly for use
[void] [System.Reflection.Assembly]::LoadWithPartialName("Utimaco.SafeGuard.AdministrationConsole.Scripting")
#---Declare Variables---
#DateTime Stamp
$DTS = date -format yyyy-MM-dd--hh-mm
#Root DSN to bind connection to
$dsn = "DC=mydomain,DC=local"
#Location for Log File
$logFileName = "D:\Scripts\SGSync."+$DTS+".log"
#Sync Group Membership
$membership = 1
#Sync Account State
$accountState = 1
#Relocate Move Objects if they have been relocated to another sync'd OU
$takeCareOfMovedObjects = 1
if($args[0] -ne $null){$Debug = $True}else{$Debug = $False}
#---End Variables---
#---Define Functions---
#Function to send email alert on Sync completion
Function SendEmail ($Errs){
$smtpServer = "smtp.mydomain.local"
The Safeguard Enterprise Automated Sync process ran. The following errors occurred:
$(foreach($item in $Errs){$item;"`r"})
$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($logFileName)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "SGE AD Sync<_SGSync@mydomain.local>"
$msg.Subject = "SGE Sync Process"
if($Debug){write-host "Email sent, also," $Errs}
#Function to actually sync Safeguard
Function SGSync ($OU){
$adsStartContainer = $OU+","+$dsn
if($Debug){write-host "Syncing:" $adsStartContainer}
[ref] $Outcome = $ScriptingDirectory.SynchronizeDirectory($dsn, $adsStartContainer, 1, $logFileName, $membership, $accountState, $takeCareOfMovedObjects)
if($Debug){write-host "Start OU:" $Result}
$Result = $Scripting.GetLastError($Outcome)
if($Debug){write-host "GetLastError returns:" $Result}
#---End Functions---
#Create scripting objects, authenticate to directory and then initialise the sync process
if($Debug){write-host "Synchronization of Users & Computers ... Started"}
try{$Scripting = new-object Utimaco.SafeGuard.AdministrationConsole.Scripting.Base}
catch{write-host "An Error Occurred While Attempting To Load Safeguard Directory Synchronisation Libraries. Quitting...";exit 0}
if($Debug){write-host "Created Base Object"}
$ScriptingDirectory = $Scripting.CreateDirectoryClassInstance()
if($Debug){write-host "Created Directory Object"}
$Result = $Scripting.Initialize()
if($Debug){write-host "Init API:" $Result}
$Result = $Scripting.AuthenticateService()
if($Debug){write-host "Authenticate:" $Result}
$Result = $ScriptingDirectory.Initialize()
if($Debug){write-host "Init SGD:" $Result}
#---Sync the following OUs---
SGSync("OU=An OU")
SGSync("OU=Another OU")
#Free up resources
$Result = $ScriptingDirectory.FreeResources()
if($Debug){write-host "Finalize SGD:" $Result}
$Result = $Scripting.FreeResources()
if($Debug){write-host "Finalize API:" $Result}
#Get errors from the generated log file
$Errs = select-string -pattern "Failure" -path $logFileName
#Send email alert
if($Errs -ne $null){SendEmail $Errs}
if($Debug){write-host "Synchronization of Users & Computers...End"}

Obviously this has to be run on a machine which has the Safeguard .NET assemblies installed (Management Console or Server packages)

ISA Server & Powershell

I’ve recently been trying to find a way to work with ISA 2006 using powershell; it’s not as straightforward as I would have hoped as all the docs are for C and Vbscript and they’re not exactly full of information anyway. That said, a few people seem to have been managing so I dived in and came up with this; it’s a Powershell script to add IP address ranges (In my case, just single addresses) from a text file to an ISA Network object (for the purposes of blacklisting). Requires Powershell v2 and needs to be run on an ISA server. For the record, the ISA API is horrible.

Adds specified IP address ranges to a given Network in ISA
.PARAMETER network
Network Name to edit
Path to file containing list of IPs to add
	[Parameter(Mandatory=$true,ParameterSetName="path",ValueFromPipelineByPropertyName=$true,Position=1,Helpmessage="Path to file containing list of IPs to add")]$path
	[Parameter(Mandatory=$true,ParameterSetName="network",ValueFromPipelineByPropertyName=$true,Position=0,Helpmessage="Network Name to edit")]$network
#Create ISA COM Objects
$root = new-object -comObject "FPC.Root" -strict
#Get our array (well, there is only one in this case)
$server = $root.Arrays | Select-Object -first 1
#Get IPRangeSet for the required network
$ipranges = $server.NetworkConfiguration.Networks.item($network).IpRangeSet
$file = gc $path
foreach($ip in $file){
	$flag = 0
	foreach($iprange in $ipranges){
		if($iprange.ip_from -match $ip){$flag = 1}
	if($flag -ne 1){$ipranges.add($ip,$ip)}

Blog 2.0

Welcome to phase 2 of my attempt to maintain an up-to-date blog with useful stuff on it; phase 1 is still available via the link on your right, however, thanks to Google ending support for FTP publishing it’s back on Blogger and thus looks a bit rubbish(er).