Exchange 2013,2010 – Event logs gathering (Health Check part 2.)

I have mede a script, which connects to all Exchange servers in organization using remote powershell and gathers all event logs for you to central place. Then it analyses event logs based on previous article (https://wordpress.com/post/40179192/2178/) (database of event IDs must be stored as CSV file delimited by semicolon). The result is again XLSX file with two worksheets. One is event ID raw data and second is analyzed event IDs. If there is event ID not present in the database, script marks it with “NEW IN DB, must be found first” in the Action row. If you run the script with empy CSV for database, it will generate XLSX as well, but you have to find solution for every event.

The script utilizes Export-XLSX.ps1. Thanks guys for the great job! https://gallery.technet.microsoft.com/office/Export-XLSX-PowerShell-f2f0c035

Example of script:

# Event logs gathering
Write-Host "Event logs gathering ... " -ForegroundColor White
#Event log variables
$exservers = get-exchangeserver
$evtlogdaysback = 1
$experfwizserver = hostname
$experfwizfilepath = "\\$($experfwizserver)\c$\ExchangeHealthCheck"   #  zmeneno z c:...
$outpath = "\\$($experfwizserver)\c$\ExchangeHealthCheck"
$WellKnownEventLogDB = import-csv .\wellknownevents.csv -Delimiter ";"

############## evt log gathering
$evtlogout = @()
  foreach ($exsvr in $exservers){
                Write-Host "Processing Exchange server $($exsvr.fqdn) ...."
                
                $evtlogout +=Invoke-Command -computername $exsvr.fqdn -ScriptBlock {
                $dat = ((get-date).adddays(-$args[0]))
                Get-eventlog -LogName * | select log | foreach {get-eventlog -LogName $_.log -EntryType Error,warning | where {$_.TimeGenerated -gt $dat} | select eventID,MachineName,Category,CategoryNumber,EntryType,Message,Source,TimeGenerated,PSComputerName}
                } -ArgumentList $evtlogdaysback

       }
       $bck = $evtlogout
$evtlogout = $evtlogout
#EVTlog cleaning
$i = 0
$out = @()
foreach ($line in $evtlogout){
$melio = ""
$line.message = $line.message.replace("`r`n","--")
foreach ($meli in $line.message){$melio = "$($melio) " + $meli}
$line.message = $melio
$out +=$line
}
# Event logs grouping, counting and comparing with WellKnownEventLogs Flat File DB
$res = @()
$WellKnownEventLogDB = import-csv .\wellknownevents.csv -Delimiter ";"
$analysedevents = "" | select count,eventid,entrytype,source,Message,action,affectedservers
$groupedlogs = $out | group eventID,source | sort name
foreach ($evtgroup in $groupedlogs){
        $match = 0
        foreach ($dbline in $WellKnownEventLogDB){

            if($dbline.Eventid -match $evtgroup.name.split(",")[0]){
              if($dbline.Source -match $evtgroup.name.split(",")[1].trim()){
                            $analysedevents = "" | select count,eventid,entrytype,source,Message,action,affectedservers
                            $analysedevents.eventid = $dbline.Eventid                        
                            $analysedevents.entrytype = $dbline.EntryType
                            $analysedevents.source = $dbline.Source
                            $analysedevents.Message  = $dbline.Message
                            $analysedevents.action =  $dbline.action
                            $analysedevents.affectedservers = "$($evtgroup.group | select machinename | group machinename | select name)"
                            $analysedevents.count = $evtgroup.count
                            $res +=$analysedevents
                            $match = 1
                            }
                }
        }
 $match
       if ($match -eq 1){}else{
            $analysedevents = "" | select count,eventid,entrytype,source,message,action,affectedservers
            $analysedevents.eventid = $evtgroup.name.split(",")[0]                        
            $analysedevents.EntryType = $evtgroup.group[0].EntryType
            $analysedevents.source = $evtgroup.name.split(",")[1].trim()
            $analysedevents.message  = $evtgroup.group[0].message
            $analysedevents.action =  "NEW IN DB, must be found first"
            $analysedevents.affectedservers = "$($evtgroup.group | select machinename | group machinename | select name)"
            $analysedevents.count = $evtgroup.count
                $res +=$analysedevents
               }

}
$res | .\Export-xlsx -path "$($xlsout)\EventLogs.xlsx" -WorKsheetname "Analyzed EVENT logs" -Append
$EvtNotExchrelLOGS  = $out
$EvtNotExchrelLOGS | .\Export-xlsx -path "$($xlsout)\EventLogs.xlsx" -WorKsheetname "Event logs raw data" -Append






################################################################################################################################################################################################################################


################################
#   Ends HERE                  #
################################


 Download:

https://onedrive.live.com/redir?resid=3941F86AC9A4F457!9241&authkey=!AG73DJErvetxKsM&ithint=file%2czip

 

Script to run and collect all Exchange performance counters from your environment to server running the tool

Script runs the remote PowerShell session against all Exchange servers, copies the Experfwiz utility to each one and runs performance counters for the time defined by administrator and exports results to the folder, from which it was run.

1. Copy ExPerfWiz.ps1 from: https://experfwiz.codeplex.com/ to some server running Exchange Management Shell to c:\ExchangeHealthCheck
2. Run the script
3. Enter Organization Admin Credentials
4. will be asked to confirm to run perfmon on each server

perfwiz

#Author: Zbynek Salon

#Description: This is small script to collect performace counters from All servrers in your environment to single folder on the server running perfwiz.

#Variables experfwiz

$date = get-date

$UserCredential = Get-Credential

$experfwizstart = $date.AddHours(1)

$experfwizduration = "04:00:00"

$experfwizinterval = 5

$experfwizserver = hostname

$experfwizfilepath = "\\$($experfwizserver)\c$\ExchangeHealthCheck" # zmeneno z c:...

$experfwizmaxsize = 512

###################################################################################################################################################################################################

#Performance counters

$localhost = hostname

$script = get-content "\\$($localhost)\c$\ExchangeHealthCheck\experfwiz.ps1"

$exservers = get-exchangeserver

 foreach ($exsvr in $exservers){

 Write-Host "Processing Exchange server $($exsvr.fqdn) ...."

 Invoke-Command -computername $exsvr.fqdn -ScriptBlock {

 #copying script to EXBIN

 Write-Host "Copying PerfWiz to $($args[1])."

 Test-Path $args[1]

 $exinstall = $args[1]

 $x = $args[0] 

 $x | out-file "$($exinstall)Scripts\experfwiz.ps1"

 Start-Sleep 1

 Write-Host "Importing Exchange PS Session." 

 $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://$($args[8])/PowerShell/" -Authentication Kerberos -Credential $args[9] -AllowRedirection

 Import-PSSession $Session

 cd "$($exinstall)Scripts"

 Set-ExecutionPolicy Unrestricted -Confirm:$false

 .\experfwiz.ps1 -delete #-FilePath $args[5] -Server $args[6] -MaxSize $args[7]

 .\experfwiz.ps1 -Duration "$($args[3])" -interval "$($args[4])" -FilePath "$($args[5])" #-Server "$($args[6])" #-MaxSize $args[7]

 #running perfmon

 } -ArgumentList $script, $exinstall, $experfwizstart, $experfwizduration, $experfwizinterval, $experfwizfilepath, $experfwizserver, $experfwizmaxsize, $exsvr.fqdn, $usercredential

}

##################################################################################################################################################################################################

The script can be downloaded from my OneDrive:
OneDrive

Office 365 – Adding SMTP addresses while DirSync without ADFS/Hybrid

Background

There are limitations, when you deploy Office 365 without ADFS/Hybrid. In this article I would like to write about SMTP addresses.

  • This attribute is synchronized to Office 365
  • You cannot add SMTP addresses on the cloud side, so you have to use attribute editor or Powershell On-Premise instead
  • To use Powershell you need to import module for Server manager and one of the methods to add / remove or replace SMTP addresses is to use Set-ADUser cmdlet, where you add string values to multivalue property “ProxyAddresses”
  • More proxy addresses can be added at the time
get-aduser -identity "stokurev" | set-aduser -add @{'ProxyAddresses'=@("SMTP:anatolij.stokurev@domain.com","smtp:stokurev@domain.com")}

Example

As an example here is the script to double existing aliases with another domain suffix

#Purpose of this script is to double aliases of domain.suffix to domain.suffix2 as secondary SMTP addresses
#Author: Zbynek Salon
#importing needed module
Import-Module Servermanager
#gathering and adding aliases
$x = get-aduser -SearchBase "OU=SUFFIX2,OU=Office365,OU=People,DC=DOMAIN,DC=SUFFIX2" -filter * -pr * | select SAMAccountname,UserPrincipalName,proxyaddresses
foreach ($line in $x){
    foreach ($addr in $line.proxyaddresses){
                if ($addr -like "smtp:*"){
                $addr = $addr.replace("DOMAIN.SUFFIX","DOMAIN.SUFFIX2")
                $addr = $addr.replace("SMTP:","")
                $addr = $addr.replace("smtp:","")
                $addr
                get-aduser -identity "$($line.samaccountname)" | set-aduser -add @{'ProxyAddresses'=@("smtp:$($addr)")}

                }
                }
               
}
#check results
$y = get-aduser -SearchBase "OU=SUFFIX2,OU=Office365,OU=People,DC=DOMAIN,DC=SUFFIX2" -filter * -pr * | select SAMAccountname,UserPrincipalName,proxyaddresses
foreach ($line in $y){
$line.samaccountname
    foreach ($addr in $line.proxyaddresses){
                if ($addr -like "smtp:*"){
                $addr
                }
                }
               
}

Print server – enable auditing and log gathering script – Event ID: 307

I was asked by my friend to install print server to his environment (Windows Server 2008 R2 SP1), enable auditing of print jobs and create report on weekly basis.

  • To install print server there is very nice video: on youtube
  • After printers are installed and deployed we should enable audit of PrinterService event. logs. On the print server Open Server Manager -> Diagnostics -> Event Logs -> Applications and services Logs -> Microsoft -> Windows -> PrintService

server_manager

  • Expand PrintService event. logs -> Right click Operational
  • Make sure Disable Log is present (Otherwise click Enable Log)

Log Enabled

  • Print test pages
  • Run the following script and it will go through event. logs, collect event. ID 307 for last 168 hours and gather you CSV file with the most important info about printed documents (What, where, when and by whom was printed)
$dat = get-date
$name="$($dat.day)_$($dat.month)_$($dat.year)"
start-transcript c:\scripts\printaudit_logs\log_$name.log
#print audit script
$pserv = "PrintServerName"
$AuFileRaw = "c:\scripts\printaudit_logs\Audit.csv"
$AuFileLRD = "c:\scripts\printaudit_logs\last_run.csv"
################################# Test mode - uncomment
$dat | Out-File $AuFileLRD 
############################################################################################################################################
#read_event_log daily from current
$a = Get-WinEvent -ProviderName "Microsoft-Windows-PrintService" -ComputerName $pserv |  where {(($_.id -eq 307) -and ($_.timecreated -ge $dat.addhours(-168)))} | select Message,TimeCreated

#read event from file
#$a = Get-WinEvent -Path 'C:\Scripts\PrintAudit_logs\system log.evtx' |  where {(($_.id -eq 307))} | | select Message,TimeCreated

$lr = "DocName;user;IP;Printer;IP Port;size;pages;Date"
$lr  | Out-File $AuFileLRD -Append
foreach ($rec in $a) {
$r = $rec.message -replace " owned by ",";"
$r = $r -replace " was printed on ",";"
$r = $r -replace " on ",";"
$r = $r -replace " through port ",";"
$r = $r -replace "  Size in bytes: ",";"
$r = $r -replace ". Pages printed: ",";"
$r = $r -replace ". No user action is required.",""
$r
$out = "$($r);$($rec.timecreated)"
#saving to raw file
$out | Out-File $AuFileRaw -Append
$out | Out-File $AuFileLRD -Append
}

#saving to raw file
#generate reports
#sending mail
Stop-Transcript

Update: I made new version of the script gathering print reports for selected period. It is also faster, because I have added additional conditions to not include empty lines in reports. Here is the new version. Blue lines are subject to change to alter period, logs placement and print server name:

#Version 1.1
$dat = get-date
$name="$($dat.day)_$($dat.month)_$($dat.year)"
start-transcript c:\scripts\printaudit_logs\log_$name.log
#print audit script
$pserv = "OPHQMS01"
$AuFileRaw = "c:\scripts\printaudit_logs\Audit.csv"
$AuFileLRD = "c:\scripts\printaudit_logs\last_run.csv"
$AuFileRep = "c:\scripts\printaudit_logs\Audit_$name.html"
$smtpserver = "smtp.domain.local"
$adminrecip = "zbynek.salon@salonovi.cz"
$month = $dat.addmonths(-1) | select month
################################# Test mode - uncomment
#$dat | Out-File $AuFileLRD 
############################################################################################################################################
#read_event_log daily from current
$b = @()
$a = Get-WinEvent -ProviderName "Microsoft-Windows-PrintService" -ComputerName $pserv | select id,Message,TimeCreated
#$a = Get-WinEvent -Path 'C:\scripts12013-082013.evtx' | select id,Message,TimeCreated
foreach ($line in $a){
$b += $line |  where {(($line.id -eq 307) -and ($line.timecreated.month -eq $month.month))} | select Message,TimeCreated
}

#read event from file
$lastm = "_$($dat.addmonths(-1).month)_$($dat.year)"
#creating folder structure
Remove-Item -Recurse -Force "c:\scripts\printaudit_logs\stats$($lastm)"
new-item -ItemType Directory -path "c:\scripts\printaudit_logs\stats$($lastm)" -erroraction SilentlyContinue
new-item -ItemType Directory -path "c:\scripts\printaudit_logs\stats$($lastm)\uzivatelske" -erroraction SilentlyContinue
new-item -ItemType Directory -path "c:\scripts\printaudit_logs\stats$($lastm)\tiskarny" -erroraction SilentlyContinue

$lr = "Dokument;Uživatel;IP;Tiskárna;IPPort;Velikost;Stran;Datum"
$lr  | Out-File $AuFileLRD
$lr  | Out-File $AuFileRaw
foreach ($rec in $b) {
if ( $rec.message -notlike $null) {
	$r = $rec.message -replace " owned by ",";"
	$r = $r -replace " was printed on ",";"
	$r = $r -replace " on ",";"
	$r = $r -replace " through port ",";"
	$r = $r -replace "  Size in bytes: ",";"
	$r = $r -replace ". Pages printed: ",";"
	$r = $r -replace ". No user action is required.",""
	$out = "$($r);$($rec.timecreated)"
#saving to raw file
	$out | Out-File $AuFileRaw -Append
	$out | Out-File $AuFileLRD -Append
	}
}

#saving to raw file

#generate reports
$Rep = Import-Csv $AuFileLRD -Delimiter ";"
$psum = @()
$usum = @()
$printers = $rep | group tiskárna | select name
$users = $rep | group uživatel | select name

# user stats
foreach ($us in $users){
$uout = "c:\scripts\printaudit_logs\stats$($lastm)\uzivatelske\$($us.name)$($lastm).csv"
$x = @(); $x +=$Rep | where {$_.uživatel -like "$($us.name)"}
$usum += $x | group uživatel,tiskárna,stran | select name,count
$x | select * -excludeproperty uživatel,ip,velikost,ipport |  Export-Csv $uout -Encoding unicode -Delimiter ";"
}
# printer stats
foreach ($pr in $printers){
$prout = "c:\scripts\printaudit_logs\stats$($lastm)\tiskarny\$($pr.name)$($lastm).csv"
$x = @(); $x +=$Rep | where {$_.tiskárna -like "$($pr.name)"}
$psum += $x | group tiskárna,stran | select name,count
$x | select * -excludeproperty tiskárna,ip,velikost,ipport | Export-Csv $prout -Encoding unicode -Delimiter ";"
}
$psum =  $rep | group tiskárna | sort count -Descending | select name,count
$usum =  $rep | group uživatel,tiskárna | sort count -Descending | select name,count
#sending mail
$body = "Zdravím,

Statistiky za měsíc $($lastm) naleznete v \\ophqms01\printaudit_logs .

S pozdravem
Admin" send-mailmessage -From zbynek.salon@domain.local -To $adminrecip -Subject "Print audit" -Body $body -BodyAsHtml -Encoding ([System.Text.Encoding]::unicode) -smtpserver $smtpserver Stop-Transcript

IMAP pst file import problems – folders containing IMAP items (IPF.Imap) type are not displayed in Exchange 2010 / 2013 OWA

Problem description

I have been solving problem in my friends Exchange 2013 environment. After migration (from IMAP profile) some folders were not visible in his OWA while those were visible in Outlook.
After research I have found, that every folder is “Different in properties” as seen in result Picture below.

wrong properties

Hmm, what now? I dont wanna use MFCMapi, since my friend has many folders. EWS? OK, but how?

Solution

Theory

  • As far as I understand Exchange, there are several kind of permissions and properties and mailbox folder properties belong to MAPI and those can be edited via MFC Mapi (ExFolders) (http://mfcmapi.codeplex.com/) or via EWS Managed API (http://www.microsoft.com/en-us/download/details.aspx?id=30141)
  • Yes. Exchange Web Services Managed API allows you to write custom applications, but I am not a programmer. I have downloaded a script from (http://gsexdev.blogspot.cz/2012/02/ews-managed-api-and-powershell-how-to.html), which I want to say thanks for and made additions to it.
  • Behind the scenes I have found nice technet discussion about how to change folder class so, that it will be visible in OWA, because OWA doesnt show folders with IMAP items. The goal is to change IPF.Imap class to IPF.Note. After changing via EWS you will see the diference as in picture below and after refresh OWA will work as needed.

Correct properties

  • As administrator I am not keen in C# so I will use my domain. Powershell (3.0) as I do the script on Exchange 2013 server

Prerequisites

  • Before you even start to play with EWS, you need to install EWS Managed API fom the link: http://www.microsoft.com/en-us/download/details.aspx?id=30141 or newer version (Link is from Fall 2012)
  • After downloading install it to directory, from which you run the script. Note, that you will need to make reference for “Microsoft.Exchange.WebServices.dll” which is key component of EWS managed API. Example from my script is below:

$dllpath =“d:ExchangeScriptsEWSmanagedAPIMicrosoft.Exchange.WebServices.dll”  

  • Next step is to add your user name full access to mailbox, which will be checked and impersonate role, which will allow impersonation of mailbox under your user as you were owner of the mailbox. Commands are as follows:

New-ManagementRoleAssignment -Name Impersonation -User administrator -Role ApplicationImpersonation

Script

Script can be downloaded from Skydrive

 
$dllpath = "d:ExchangeScriptsEWSmanagedAPIMicrosoft.Exchange.WebServices.dll" #Define DLL Path

[void][Reflection.Assembly]::LoadFile($dllpath) #Load DLL

$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2) #Define EWS Service and version

$service.Url = New-Object System.Uri("https://email.domain.cz/EWS/Exchange.asmx") #Define uri for EWS VDir

$MBXID = "mailbox.identity" #Define mailboxID

foreach ($MailboxIdentity in $MBXID) {

Write-Host "Searching for $MailboxIdentity"

$MailboxName = (Get-Mailbox -Identity $MailboxIdentity).PrimarySmtpAddress.ToString()

$MailboxDName = (Get-Mailbox -Identity $MailboxIdentity).DisplayName

$ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId -ArgumentList ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress),$MailboxName #Define impersonation

$service.ImpersonatedUserId = $ImpersonatedUserId #Impersonate service under userID

$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root,$MailboxName) #MsgFolderRoot selection and creation of new root folder object

$f1 = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $MailboxName) #Binding folder under mailbox identity

$fold = get-mailboxfolderstatistics $MailboxIdentity #Getting complete list of selected mailbox

foreach ($mbxfolder in $fold){

#Define Folder View Really only want to return one object

$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(100) #page size for displayed folders

$fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep; #Search traversal selection Deep = recursively

#Define a Search folder that is going to do a search based on the DisplayName of the folder

$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::Displayname,$MBXFolder.name) #for each folder in mailbox define search

$findFolderResults = $service.FindFolders($folderid,$SfSearchFilter,$fvFolderView) #for each folder in mailbox define folder view (this is online task for store.exe) and perform search

if ($findFolderResults.TotalCount -eq 0){ "Folder Doesn't Exist" } #Info if folder still exist

else {"Folder Exist"

ForEach ($Folder in $findFolderResults.Folders) { #for each folder in folder results perform check of folder class

$folder.folderclass #Info about folder class

if ($Folder.folderclass -eq "IPF.Imap"){ #If folder class is target type, do change and update

$Folder.folderclass = "IPF.Note" #Folder class change in variable

Write-Host "Updating folder $folder.name to correct type IPF.Note. Folder will start to be visible in OWA"

$Folder.update() #Folder class update in mailbox via EWS

}

}

}

}

}

The script will generate some output to host:

converting via script

Reference

Mailbox quotas change based on Custom Attribute

  • Exchange 2010 / 2013 can be designed so, that multiple mailbox tiers can be placed within one database. In this case there is not easy way how to control mailbox limits for bigger companies. I wrote the script, which can help managing limits based on single value in Custom attribute 12.

How it works

  • Change custom attribute 12 for maiblox users to value Tier1, Tier2 ….Tier5
  • Plan to run the script on daily basis via task manager
  • Script will change the limits to correct values and check if the limits are still OK for existing mailboxes
  • If limits have changed for some reason. Script will set correct ones
  • For non existing value or deviated one: for example “Tier 1” the default tier will be set

What do you need to customize

  • Where to put report file (line 9)
  • Define tiers (Number for size, Unit for multiplier MB,GB etc)
  • You can specify unlimited value as well, unit value then is empty “”

Work left for service desk

  • Add tier info to CustomAttribute12 or leave it empty for default tier assignment
  • change CustomAttribute12 value once mailbox user requests change of mailbox limits

Script

 # Author: zbynek.salon@salonovi.cz
 # Version 3.0
 # Purpose: 1/ Changing limits based on tier value inside CustomAttribute12
 #
 #######################################################################################################################################################
 # Date and report definitions
 $dat = get-date | select day,month,year
 $date = "$($dat.day)_$($dat.month)_$($dat.year)"
 $file = "d:report_$date.txt"
 $report = "started at $($date) - Task 1/ Changing limits based on tier value inside CustomAttribute12"
 $report | out-file "$($file)" -width 2000000 -Append
 #######################################################################################################################################################
 # Tier definition W-Warning, S-ProhibitSend, R-ProhibitSendReceive, WU-Warning Unit, SU-Send Unit, RU-Receive Unit, TI - TierInfo
 $t = [PSCustomObject]@{
 T1 =[PSCustomObject]@{
 W="950"
 S="1024"
 R="1250"
 WU="MB"
 SU="MB"
 RU="MB"
 TI="Limit 1024MB"
 }
 T2 = [PSCustomObject]@{
 W="450"
 S="500"
 R="650"
 WU="MB"
 SU="MB"
 RU="MB"
 TI="Limit 500MB"
 }
 T3 = [PSCustomObject]@{
 W="130"
 S="150"
 R="200"
 WU="MB"
 SU="MB"
 RU="MB"
 TI="Limit 150MB"
 }
 T4 = [PSCustomObject]@{
 W="8192"
 S="10240"
 R="unlimited"
 WU="MB"
 SU="MB"
 RU=""
 TI="Business demand 8GB"
 }
 T5 = [PSCustomObject]@{
 W="2048"
 S="2548"
 R="3072"
 WU="MB"
 SU="MB"
 RU="MB"
 TI="Temporarily increased - for cleanup 2,5GB"
 }
 }
 #######################################################################################################################################################
 # Function
 function Limit ($mb,$ti,$rep){
 $res=0
 if ($mb.issuewarningquota.isunlimited -eq $true)
 {
 if ("unlimited" -ne $ti.w){$res=1}
 }
 else{
 if ($mb.issuewarningquota.value.toMB() -ne $ti.w){$res=1}
 }
 if ($mb.prohibitsendquota.isunlimited -eq $true)
 {
 if ("unlimited" -ne $ti.s){$res=1}
 }
 else{
 if ($mb.prohibitsendquota.value.toMB() -ne $ti.s){$res=1}
 }
 if ($mb.prohibitsendreceivequota.isunlimited -eq $true)
 {
 if ("unlimited" -ne $ti.r){$res=1}
 }
 else{
 if ($mb.prohibitsendreceivequota.value.toMB() -ne $ti.r){$res=1}
 }
 if ($res -eq 1){
 Write-Host "$($ti.TI)"
 $report = "$($mb.alias);$($mb.ExchangeGuid);$($mb.customattribute12);$($mb.issuewarningquota);$($mb.prohibitsendquota);$($mb.prohibitsendreceivequota);Will be set to correct limits"
 $report | out-file "$($rep)" -width 2000000 -Append
 set-mailbox "$($mb.exchangeguid)" -usedatabasequotadefaults $false -Prohibitsendquota "$($ti.s)$($ti.SU)" -prohibitsendreceivequota "$($ti.r)$($ti.RU)" -issuewarningquota "$($ti.w)$($ti.WU)"
 }
 else{
 Write-Host "$($ti.TI)"
 $report = "$($mb.alias);$($mb.ExchangeGuid);$($mb.customattribute12);$($mb.issuewarningquota);$($mb.prohibitsendquota);$($mb.prohibitsendreceivequota);Mailbox OK"
 $report | out-file "$($rep)" -width 2000000 -Append
 }
 }
########################################################################################################################################
 # Main program
 $a = $null
 $a = @()
 $a += get-mailbox -resultsize unlimited | select *quota*,customattribute12,alias,Exchangeguid
 foreach ($line in $a){
 if ($line.exchangeguid -ne $null){
 $tier=$null
 switch ($line.customattribute12) {
 "Tier1"{
 $tier = $t.t1
 Limit $line $tier $file
 }
 "Tier2"{
 $tier = $t.t2
 Limit $line $tier $file
 }
 "Tier3"{
 $tier = $t.t3
 Limit $line $tier $file
 }
 "Tier4"{
 $tier = $t.t4
 Limit $line $tier $file
 }
 "Tier5"{
 $tier = $t.t5
 Limit $line $tier $file
 }
 "$null"{
 $tier = $t.t3
 Limit $line $tier $file
 }
 default{
 $tier = $t.t3
 Limit $line $tier $file
 }
 }
 }
 }

How to backup Exchange 2013 mailbox database on Windows Server 2008 R2 SP1

It is possible to backup Exchange 2013 mailbox databases with Windows backup, however, there are some limitations in functionality. For normal LAB or small bussiness it is fine solution.

Exchange Backup limitations

  • Only Full backup is possible with log truncation (incremental backups do not flush logs)
  • Normal backup performance option does always full backup, but only differences are stored in the disk, while using file block mode.
  • After initial full backup every other backup of the same volume to the same target is incremental unless the following two conditions are fulfilled:
  • 14 incremental backups have occurred since the last full backup
  • More than 14 days have passed since the last full backup ( http://technet.microsoft.com/en-us/library/dd759145.aspx )

Configuring Windows backup

Installation

Windows Server Backup feature is not installed by default on W2k8 R2 SP1 server.

  • To gather status use the following Powershell command:
Get-windowsfeature | where {$_.name -like "*backup*"}
  • To install Windows Server Backup features run the following commands from Powershell. These commands will install needed features to run Exchange backup via command line tool Wbadmin.
Add-WindowsFeature "Backup-Features" Add-WindowsFeature "Backup-Tools"

  • In backup/restore of Exchange servers we will use Powershell commands. Run the following command to import WB command to Powershell session.
add-pssnapin windows.serverbackup
  • Add new disk for Exchange backups. In script there is used “Backup Disk” as volume name. (Depends on the HW you use, please use your HW guidance)

  • To succesfully configure Windows Server Backup we must first define backup policy:
$WBPolicyFull = New-WBPolicy         # Create new WB policy object
$WhatToBackup = New-WBFileSpec –FileSpec E:    # Define what to backup
Add-WBFileSpec –Policy $WBPolicyFull –FileSpec $WhatToBackup  # Adding what to backup to backup policy
$WBTarget = New-WBbackupTarget –NetworkPath "\Servernamesharenamepath"  # Selected backup disk will be set as target
Add-WBBackupTarget –Policy $WBPolicyFull -Target $WBTarget   # Adding target to WB policy
Set-WBVssBackupOptions -Policy $WBPolicyFull -VssFullBackup   # Set method to use WSS Full Backup
  • To check policy:
$WBPolicyFull
  • Status of mailbox database before initial full backup
Get-MailboxDatabase <identity> -Status

  • Policy configured in previous step might be started directly
Start-WBBackup -Policy $WBPolicyFull

  • Or scheduled
Set-WBSchedule –Policy $WBPolicyFull –Schedule 21:00
  • After initial full backup the mailbox database is changed

  • To list backup sets:
Get-WBBackupSet
  • To list job result:
Get-WBJob -previous 1

Example

add-pssnapin windows.serverbackup
$WBPolicyFull = New-WBPolicy
$WhatToBackup = New-WBFileSpec –FileSpec E:
Add-WBFileSpec –Policy $WBPolicyFull –FileSpec
$WhatToBackup $WBTarget = New-WBbackupTarget –Networkpath "\backend1g$Full"
Add-WBBackupTarget –Policy $WBPolicyFull -Target
$WBTarget Set-WBVssBackupOptions -Policy
$WBPolicyFull -VssFullBackup
Start-WBBackup -Policy $WBPolicyFull

Results