PowerShell Tip: Get string array from your list

Very easy procedure how to get string array from listed items from somewhere (e.g. txt file).

Well, run PS, declare a variable like $something=” paste your lines then close it by ” and convert it into the array $something=something.split(“`n”)

26- 5- 2015 22-31-55

26- 5- 2015 22-28-41

Of course there are a lot of other possibilities how to declare the same array e.g. $array = @(“10.10.10.26″,”10.10.10.35″,”10.10.10.44”), but anyway the paste option is useful thing ;).

Exchange 2013 SP1 – problem #1 – Powershell virtual directory malfunction – HTTP error (500)

This is known issue, but to remember myself for next versions: If you run EMS for Exchange 2013 SP1. Error comes out:500error

It has 3 possible issues. Here are solutions:

Root cause 1:

Exchange server is out of sync with time of DC. You should always have the following hierarchy of time sync in your domain: Reliable time source -> PDC -> Other DCs -> Servers and clients

  • Disable windows time sync from physical host if it is virtual machine
  • Enable time sync with domain by the following commands:
  • On PDC
net stop w32time 
w32tm /config /syncfromflags:manual /manualpeerlist:0.pool.ntp.org 
w32tm /config /reliable:yes 
net start w32time

On other DCs and Servers:

net stop w32time
w32tm /config /syncfromflags:domhier /reliable:no /update
net start w32time

Root cause 2:

Exchange server path to kerbauth.dll is wrong / Powershell virtual directory is misconfigured. I have re-created virtual directory for Powershell on affected server:

Get-PowerShellVirtualDirectory -Server <AffectedServer> | Remove-PowerShellVirtualDirectory
New-PowerShellVirtualDirectory -Server <AffectedServer> -Name PowerShell
Get-PowerShellVirtualDirectory -Server <AffectedServer> | Set-PowerShellVirtualDirectory -BasicAuthentication:$false
IISReset

After virtual directory re-creation I have checked its modules in IIS and made sure, that Kerberos module is native and the path to its DLL is correct:

modules

Root cause 3:

There is a missing Windows feature WinRM IIS extension.The full description is here: http://technet.microsoft.com/en-us/library/dd759166.aspx This was the case in my lab and I feel it is the side effect of in-place upgrade of OS from Windows server 2012 to Windows Server 2012 R2 on Exchange server (Yes I know it is not good idea, but how to learn non standard issues in other way). Here is simple solution: Install this windows feature:

Get-WindowsFeature *IIS* #to check if it is installed
Add-WindowsFeature Winrm-IIS-Ext # to install

winrmext

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
 }
 }
 }
 }

DNS monitoring via Powershell

There is a Microsoft service called ExRAP. (Exchange health check) and one of the errors in report, provided to you as a result of ExRAP is that internal DNS records are not checked automatically on all DNS servers. I have made a script, which will do DNS records monitoring for you and in case records differs from designed values, it will send e-mail to predefined e-mail address.
Prerequisites:
You must have rights to connect to DNS server and read DNS zones using WinRM.

How it works:

  • It uses powerful Powershell module called DNS Shell (downloadable here: http://dnsshell.codeplex.com/)
  • It connects to each DNS server in organization
  • It compares predefined (designed) values from CSV file with the values read from DNS servers (A and PTR) and if values of DNS records differs, it reports an error to e-mail message
  • Comparison is based on ODD / EVEN number of same records. If ODD record is found in field of read records, it stay that record on DNS server or CSV file is incorrect.

Preparation:

  • Implement DNSShell module to Powershell on server
    Extract DnsShell.zip to one of the paths shown by $Env:PSModulePath
  • Create CSV file with the following format (For each A record one line, for each PTR record one line)

“Name”;”RecordData”
“EXSERVER2″;”192.168.196.102”
“102.196.168.192.in-addr.arpa”;”EXSERVER2.yourdomain.com.”

  • Copy script to the same location as CSV file

# To make this work extract http://dnsshell.codeplex.com/ to C:Windowsystem32WindowsPowerShellv1.0Modules
# author: Zbynek.Salon@salonovi.cz
###################################################################################
$c = $null
$server =@()
$server = “DNS1″,”DNS2″,”DNS3”
foreach ($internalserver in $server){
#internal records check
import-module DNSShell
$tocomp = $null
$tocomp = import-csv .internal.csv -delimiter “;”
$data = @()
$data +=get-addnsrecord *exserver* | select name,recorddata
$data +=Get-DnsZone -Server $internalserver | where {$_.zonename -like “168.192*“} | get-dnsrecord | where {$_.recorddata -like “*exserver*“} | select name,recorddata
#$data | export-csv .tocompare.csv -delimiter “;”
$data +=$tocomp
$out = $data | sort name | group name,recorddata
$changed = @()
foreach ($rec in $out)
{
 $ev=$null
 $ev = [bool]!($rec.count%2)
 if ($ev -eq $false)
  {
  $changed +=”$($rec.name);”
  }
}
if ($changed -ne $null){
foreach ($chan in $changed){
$c +=”DNS server: $($internalserver)- Record: $($chan);<br />”}
}
}
if ($c -ne $null){send-mailmessage -From monitoring@yourdomain.com -To administrator@yourdomain.com,another.admin@yourdomain.com -Subject “Monitored DNS records changed – please check.” -Body “Hello,<br /> <br /> The following DNS records does not match with predefined values in’\SERVERNAMEd$ExchangeScriptsDNSrecordsMonitoringinternal.csv'<br />$(foreach($q in $c){$q;'<br />’})<br /> Please check accuracy. <br /> <br /> S pozdravem / Best regards, <br /> Zbynek” -BodyAsHtml -Encoding ([System.Text.Encoding]::unicode) -smtpserver SMTP.yourdomain.com
}

  • Green text in the script is subject to change
  • Do test run
  • In case of mismatch in DNSs records e-mail message is generated (Do not forget to use open relay connector and correct smtp server)

Hello,

The following DNS records does not match with predefined values in’\SERVERNAMEd$ExchangeScriptsDNSrecordsMonitoringinternal.csv’
DNS server: DNS1-Record: EXSERVER2, 192.168.196.111;;’
‘DNS server: DNS1-Record: EXSERVER2, 192.168.196.110;;’
‘DNS server: DNS2-Record: EXSERVER2, 192.168.196.111;;’
‘DNS server: DNS2-Record: EXSERVER2, 192.168.196.110;;’
‘DNS server: DNS3-Record: EXSERVER2, 192.168.196.111;;’
‘DNS server: DNS3-Record: EXSERVER2, 192.168.196.110;;’

Please check accuracy.

S pozdravem / Best regards,
Admin

  • Plan scheduled task to run the script as often as you want