Creating FSRM quotas and notification reports via Powershell

For the file server project I also had to mirgrate Symantec Storage Exec quotas to Microsoft File Server Resource Manager quotas. While the raw quota transfer was done via a .vbs script, a nice Powershell script took care of the following new feature request:

Create FSRM quota reports and send them to the person responsible (to the email address specified for the owner of the shared folder AD object), with different parameters for each share, when quota usage reaches a specified threshold.

FSRM allows you to set a report's parameters on a global level. That often isn't exactly what you want, and was severely wrong in our case. For our purposes the "Large Files" report was optimal. We decided we wanted an owner of a share to recieve a tailored report of space consumption in their share, but FSRM only allows you to globally set a large file threshold and reports all files with a size above that level.

File shares at our organization differ wildly in space consumption and also on how large a "large file" really is, so my script takes the 100 largest files and sets the large file threshold to the average filesize of those larges 100. That gives every owner a good idea of which files hog their quota.

Usage: Scriptname.ps1 Servername DiskOnWhichSharesAre

It currently excludes hidden- and our home directory shares. Modify $SharesQuery to change that. $Threshold is the quota usage level to be reached before a report gets generated.

function get-ShareOwnerMail {
	Param ([string]$Share)
	
	$searcher.filter = "(&(objectClass=Volume)(uncname=$share))"
	$managerdn= $searcher.FindOne().properties.managedby
	$searcher.filter = "(&(objectClass=User)(distinguishedname=$managerdn))"
	return $searcher.findone().properties.mail
}

$root = [ADSI]""
$searcher = new-object directoryservices.directorysearcher($root)
$server = $args[0]
$drive = $args[1] + ":"
$Threshold = "75"
$UNCPrefix = "\5c\5c"
$UNCSeparator = "\5c"
$FileNamePostfix = "testcommand.txt"
$TemplateFile = get-content _TEMPLATECommandConfig.txt
$SharesQuery = {gwmi win32_share -computer $server | where {$_.name -notlike '*$' -and $_.name -notlike 'home?' -and $_.path -match $Drive}}
$ReportOptionsTemplate = "Arguments=reports generate /ondemand /report:largefiles /minsize:[MINSIZE]KB /scope:[SCOPE] /format:html /mailto:[SHAREOWNERMAIL]"

foreach ($share in &$sharesquery) 
{
	$name = $share.name
	$Scope = $share.path
	$ShareOwnerMail = get-shareownermail ($UNCPrefix+$server+$UNCSeparator+$name)
	$MinSize = [math]::round(((ls \\$server\$name -r | sort length -descending | select -first 100 | measure-object length -average).average)/1kb)
	write-host $Scope,$MinSize,$Shareownermail
	$ReportOptions= $ReportOptionsTemplate
	$ReportOptions= $ReportOptions.replace("[MINSIZE]",$MinSize).replace("[SCOPE]",$Scope).replace("[SHAREOWNERMAIL]",$ShareOwnerMail)	
	$outfile = $server + $name + $filenamepostfix
	$TemplateFile + $ReportOptions | out-file ($outfile) -encoding ASCII
	write-host dirquota quota add /path:$scope /modify-notification:$Threshold","C","$outfile /remote:$server 
	dirquota quota modify /path:$scope /delete-threshold:$Threshold /remote:$server
	dirquota quota modify /path:$scope /add-threshold:$Threshold /add-notification:$threshold","C","$outfile /remote:$server  | out-host
}

AttachmentSize
_TEMPLATECommandConfig.txt158 bytes