exchange

Das Skript generiert eine html-Seite mit der Übersicht aller Termine für alle Exchange Accounts. So kann übersichtlich gelistet werden, wer heute wo, wann und wie beschäftigt ist.

Als Grundlage habe ich das super Skript von Glen Scales benutzt.

fbboard

Dieses hatte leider noch Probleme die Kalendereinträge richtig auf die Zeiten zu zuordnen. Außerdem habe ich die Zeitspanne bei einem Tag von 8:00 Uhr bis 20:00 Uhr erweitert und die Termine werden verkürzt in den einzelnen Zellen angezeigt. Der komplette Terminname wird angezeigt, wenn man mit dem Cursor über die Zelle fährt. Desweiteren habe ich den Start des Skripts mit einem Parameter versehen, so dass die Termine für bestimmte Tage in der Vergangenheit oder auch in der Zukunft generiert werden können.

Bitte beachtet das die Exchange Web Services installiert sein müssen und in Zeile 56 der richtige Exchange-Server eingetragen wird: $casserverName = “Exchange-Server”.

Hier das Skript:

function cleanDescription([string] $url)
{
	$url = $url.Replace("title=", "")
	$url = $url.Replace("`"","")
	$url = $url.Substring(0,6)

    return $url
}

if ($Args.count -lt 1) {

    'No Parameter!'
    'Usage:'
    './fb.ps1 days in the future (e.g. 0 - Today; 1 - Tomorrow; -1 - Yesterday)'
    ''
	'Today:'
	'./fb.ps1 0'
    }
else{
[int]$days = $args[0]

$casserverName = "Exchange-Server"
$dllpath = "C:Program FilesMicrosoftExchangeWeb Services1.0Microsoft.Exchange.WebServices.dll"
[void][Reflection.Assembly]::LoadFile($dllpath)
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)

$uri=[system.URI] ("https://" + $casserverName + "/ews/exchange.asmx")
$service.Url = $uri

$mbHash = @{ }

$tmValHash = @{ }
$tidx = 0
for($vsStartTime=[DateTime]::Parse([DateTime]::Now.ToString("yyyy-MM-dd 0:00")).AddDays($days);$vsStartTime -lt [DateTime]::Parse([DateTime]::Now.ToString("yyyy-MM-dd 0:00")).AddDays($days+1);$vsStartTime = $vsStartTime.AddMinutes(30)){
	$tmValHash.add($vsStartTime.ToString("HH:mm"),$tidx)
	$tidx++
}

get-mailbox -ResultSize unlimited | foreach-object{
	if ($mbHash.ContainsKey($_.WindowsEmailAddress.ToString()) -eq $false){
		$mbHash.Add($_.WindowsEmailAddress.ToString(),$_.DisplayName)
	}
}
$Attendeesbatch = [activator]::createinstance(([type]'System.Collections.Generic.List`1').makegenerictype([Microsoft.Exchange.WebServices.Data.AttendeeInfo]))

$StartTime = [DateTime]::Parse([DateTime]::Now.ToString("yyyy-MM-dd 0:00")).AddDays($days)
$EndTime = $StartTime.AddDays(1)

$displayStartTime =  [DateTime]::Parse([DateTime]::Now.ToString("yyyy-MM-dd 08:00")).AddDays($days)
$displayEndTime = [DateTime]::Parse([DateTime]::Now.ToString("yyyy-MM-dd 20:30")).AddDays($days)

$drDuration = new-object Microsoft.Exchange.WebServices.Data.TimeWindow($StartTime,$EndTime)
$AvailabilityOptions = new-object Microsoft.Exchange.WebServices.Data.AvailabilityOptions
$AvailabilityOptions.RequestedFreeBusyView = [Microsoft.Exchange.WebServices.Data.FreeBusyViewType]::DetailedMerged

$batchsize = 100
$bcount = 0
$bresult = @()
if ($mbHash.Count -ne 0){
	$mbHash.GetEnumerator() | Sort Value | foreach-object {
		if ($bcount -ne $batchsize){
			$Attendee1 = new-object Microsoft.Exchange.WebServices.Data.AttendeeInfo($_.Key)
			$Attendeesbatch.add($Attendee1)
			$bcount++
		}
		else{
			$availresponse = $service.GetUserAvailability($Attendeesbatch,$drDuration,[Microsoft.Exchange.WebServices.Data.AvailabilityData]::FreeBusy,$AvailabilityOptions)
			foreach($avail in $availresponse.AttendeesAvailability.OverallResult){$bresult += $avail}
			$Attendeesbatch = [activator]::createinstance(([type]'System.Collections.Generic.List`1').makegenerictype([Microsoft.Exchange.WebServices.Data.AttendeeInfo]))
			$bcount = 0
			$Attendee1 = new-object Microsoft.Exchange.WebServices.Data.AttendeeInfo($_.Key)
			$Attendeesbatch.add($Attendee1)
			$bcount++
		}
	}
}
$availresponse = $service.GetUserAvailability($Attendeesbatch,$drDuration,[Microsoft.Exchange.WebServices.Data.AvailabilityData]::FreeBusy,$AvailabilityOptions)
$usrIdx = 0
$frow = $true
foreach($res in $availresponse.AttendeesAvailability){
      if ($frow -eq $true){
	  	$fbBoard = $fbBoard + "<table><tr><td align=`"center`"><b>"+$StartTime.ToString("dd-MM-yyyy")+"</b></td><td align=`"right`" style=`"width=50;`"><b>Free:</b></td><td bgcolor=`"#41A317`" align=`"center`" style=`"width=50;`" ></td>" + "`r`n"
		$fbBoard = $fbBoard + "<td align=`"center`" style=`"width=50;`"><b>Tentative:</b></td><td bgcolor=`"#828383`" align=`"center`" style=`"width=50;`" ></td>" + "`r`n"
		$fbBoard = $fbBoard + "<td align=`"center`" style=`"width=50;`"><b>Busy:</b></td><td bgcolor=`"#153E7E`" align=`"center`" style=`"width=50;`" ></td>" + "`r`n"
		$fbBoard = $fbBoard + "<td align=`"center`" style=`"width=50;`"><b>OOF:</b></td><td bgcolor=`"#4E387E`" align=`"center`" style=`"width=50;`" ></td>" + "`r`n"
		$fbBoard = $fbBoard + "</tr>"
		$fbBoard = $fbBoard + "<tr bgcolor=`"#95aedc`">" +"`r`n"
		$fbBoard = $fbBoard + "<td align=`"center`" style=`"width=200;`" ><b>User</b></td>" +"`r`n"
		for($stime = $displayStartTime;$stime -lt $displayEndTime;$stime = $stime.AddMinutes(30)){
			$fbBoard = $fbBoard + "<td align=`"center`" style=`"width=50;`" ><b>" + $stime.ToString("HH:mm") + "</b></td>" +"`r`n"
		}
		$fbBoard = $fbBoard + "</tr>" + "`r`n"
		$frow = $false
	}
	for($stime = $displayStartTime;$stime -lt $displayEndTime;$stime = $stime.AddMinutes(30)){

		if ($stime -eq $displayStartTime){
			$fbBoard = $fbBoard + "<td bgcolor=`"#CFECEC`"><b>" + $mbHash[$Attendeesbatch[$usrIdx].SmtpAddress] + "</b></td>"  + "`r`n"
			$c = 0
		}

		$title = "title="
		$description = ""
		if ($res.MergedFreeBusyStatus[$tmValHash[$stime.ToString("HH:mm")]] -ne $null){
			$gdet = $false
			$FbValu = $res.MergedFreeBusyStatus[$tmValHash[$stime.ToString("HH:mm")]]
			switch($FbValu.ToString()){
				"Free" {$bgColour = "bgcolor=`"#41A317`""}
				"Tentative" {$bgColour = "bgcolor=`"#828383`""
					     $gdet = $true

					}
				"Busy" {$bgColour = "bgcolor=`"#153E7E`""
					     $gdet = $true

					}
				"OOF" {$bgColour = "bgcolor=`"#4E387E`""
					     $gdet = $true

					}
				"NoData" {$bgColour = "bgcolor=`"#98AFC7`""}
				"N/A" {$bgColour = "bgcolor=`"#98AFC7`""}
			}
			if ($gdet -eq $true){
				if ($res.CalendarEvents.Count -ne 0){
					if($c -lt $res.CalendarEvents.Count){
					#for($ci=0;$ci -lt $res.CalendarEvents.Count;$ci++){
						[int]$start = $res.CalendarEvents[$c].StartTime.ToString("HHmm")
						[int]$end = $res.CalendarEvents[$c].EndTime.ToString("HHmm")
						if($end -ge 0)
						{
							$end = 2000
						}
						[int]$time = $stime.ToString("HHmm")
						#Write-Host $start $time $end
						if ($time -ge $start-25 -band $time -le $end){
							$c += 1
							if($res.CalendarEvents[$c-1].Details.IsPrivate -eq $False){
								$subject = ""
								$location = ""
								#Write-Host $c
								#Write-Host $mbHash[$Attendeesbatch[$usrIdx].SmtpAddress]
								#Write-Host $res.CalendarEvents[$c-1].StartTime.ToString("HH:mm")

								#Write-Host $time
								#Write-Host $res.CalendarEvents[$c-1].EndTime.ToString("HH:mm")
								#Write-Host $res.CalendarEvents[$c-1].Details.Subject
								if ($res.CalendarEvents[$c-1].Details.Subject -ne $null){

									$subject = $res.CalendarEvents[$c-1].Details.Subject.ToString()
								}
								if ($res.CalendarEvents[$c-1].Details.Location -ne $null){
									$location = $res.CalendarEvents[$c-1].Details.Location.ToString()
								}
								$title = $title + "`"" + $subject + "`r`n" + "Wo: " + $location + "`" "
							}else{
								$title = $title + "Privat"
							}
						}
					}

				}
			}

		}
		else{
			$bgColour = "bgcolor=`"#98AFC7`""
		}
		if($title -ne "title="){

			$description = cleanDescription($title)
			$fbBoard = $fbBoard + "<td " + $bgColour + " " + $title + "><font color=#FFFFFF>"+$description+"</font></td>"  + "`r`n"
		}
		else{
			$fbBoard = $fbBoard + "<td " + $bgColour + "></td>"  + "`r`n"
		}

	}
	$fbBoard = $fbBoard + "</tr>"  + "`r`n"
	$usrIdx++
}
$fbBoard = $fbBoard + "</table>"  + "  "
$fbBoard | out-file "c:fbboardfbboard$days.htm"
}

Wenn dir dieser Artikel gefallen hat, kannst du ihn mit einem Klick auf die folgenden Buttons weiterempfehlen. Möchtest du in Zukunft keine neuen Beiträge mehr verpassen? Dann abonniere doch den RSS Feed dieses Blogs. Vielen Dank!

psMan stelle sich vor: Ein Fileserver mit diversen Gruppenberechtigungen am Dateisystem soll durch neue Sicherheitsgruppen, analog der alten Gruppen, erweitert werden.

Beispiel:

Die Sicherheitsgruppe G_Test hat in dem Ordner Fileserver:DatenTemp Vollzugriff. Nun soll Gruppe N_Test dieselben Berechtigungen auf diesen Ordner erhalten.

Und da kommt Powershell wie gerufen. Mit folgendem Skript wird abgefragt, ab welchem Ordner + (Unterordner) überprüft werden soll. Danach wird automatisch nach den angegebenen Gruppen gesucht und diese duch die neue Domäne ersetzt. Auch die Vererbung wird geprüft und ggf. übertragen. Es funktioniert nur, wenn die Gruppen gleich heißen, kann aber schnell abgeändert werden.

#ChangeACL.ps1

#The possible values for Rights are
# ListDirectory, ReadData, WriteData
# CreateFiles, CreateDirectories, AppendData
# ReadExtendedAttributes, WriteExtendedAttributes, Traverse
# ExecuteFile, DeleteSubdirectoriesAndFiles, ReadAttributes
# WriteAttributes, Write, Delete
# ReadPermissions, Read, ReadAndExecute
# Modify, ChangePermissions, TakeOwnership
# Synchronize, FullControl

$StartingDir=Read-Host "What directory do you want to start at?"

foreach ($file in $(Get-ChildItem $StartingDir -recurse | where {$_.PsIsContainer})) {
  " "
  "Objekt: " + $file.FullName

  $name = Get-Acl $file.FullName | ForEach-Object { $_.Access  } | Group-Object IdentityReference | % {$_.Name}
  $rights = Get-Acl $file.FullName | % {$_.Access} | % {$_.FileSystemRights}
  $IsInherited = Get-Acl $file.FullName | % {$_.Access} | % {$_.InheritanceFlags}

  for($i=0;$i -lt $name.count ;$i++)
  {
        "User: " + $name[$i]
        "Rights: " + $rights[$i]

        #Insert your groups which will be replaced
        if($name[$i] -eq "domain_ATest" -or $name[$i] -eq "domain_ATest2")
        {
                $name[$i] = $name[$i].Substring(13)
                $name[$i] = "domain_B"+$name[$i] #type in the new domainname
                $acl = Get-Acl $file.FullName

                $permission = $name[$i],$rights[$i],$IsInherited[$i],"None","Allow"
                $rule=new-object System.Security.AccessControl.FileSystemAccessRule $permission

                $acl.SetAccessRule($rule)
                $acl | Set-Acl $file.FullName

        }
  }

 }

Wenn dir dieser Artikel gefallen hat, kannst du ihn mit einem Klick auf die folgenden Buttons weiterempfehlen. Möchtest du in Zukunft keine neuen Beiträge mehr verpassen? Dann abonniere doch den RSS Feed dieses Blogs. Vielen Dank!

Sumby-Full

Vielen ist es bekannt, dass die Exchange Server Konsole nur wenig Informationen über Postfächer ausgibt, zumindest, wenn man mehrere Postfächer vergleichen möchte. Powershell kann da schon mehr Infos gleichzeitig ausgeben, wobei hier die Übersichtlichkeit leidet.

Mit Hilfe des Exchange Dev Blogs von Glen Scales habe ich eine neue GUI erstellt, welche sehr viele Infos über die Mailboxen auf einem oder mehreren Exchange-Servern darstellt. Z.B.: Kann nach Postfachgröße (Anzahl der Elemente oder der Speicherbelegung) sortiert werden. Eine Auflistung der Unterordner in einem Postfach ist auch möglich.

Einen Auszug von Filtern zeigt der folgende Screenshot:

sumby-filters

Außerdem kann zwischen verbundenen und nicht-verbundenen Postfächern geschaltet werden:

sumby-disconnected

Das Skript muss auf einem Exchange-Server ausgeführt werden. Getestet wurde es auf einem deutschen Exchange-Server 2010. Das Skript muss daher in diesen Ordner kopiert werden: C:Program FilesMicrosoftExchange ServerV14Scripts

Außerdem muss der ausführende Account Zugriffsberechtigungen auf den restlichen Postfächern besitzen.

Das Skript ist hier zum Download verfügbar.


Wenn dir dieser Artikel gefallen hat, kannst du ihn mit einem Klick auf die folgenden Buttons weiterempfehlen. Möchtest du in Zukunft keine neuen Beiträge mehr verpassen? Dann abonniere doch den RSS Feed dieses Blogs. Vielen Dank!