Save Hashed Password in RDP file

23 01 2009

Over on the main EverydayNerd.com website, I’ve posted an article about saving a hashed password in an .RDP file.  Hope you find it helpful!

http://everydaynerd.com/microsoft/save-password-in-rdp-file





Script to Find Whitespace on all Exchange 2007 Servers

23 01 2009

As an Exchange Admin, I’m sure you have had the need to find out how much whitespace is in each of your Exchange databases.  This can be a real pain to do, crawling through the Event Log, looking for Event ID 1221.  This script will query all Exchange 2007 Mailbox servers, crawl through the Event logs, and return the Whitespace for every Database you have.  This information can also be exported to a SQL database, if you un-comment the appropriate lines.

Hope this makes your job easier!

*** Special thanks to my co-worker Stephen M for writing this script, and suggesting that I post it to ExchangeStyle.EverydayNerd.com – Thanks!

# Script: Get-WhiteSpace.ps1 will return the Whitespace on every Mailbox Server in an Exchange 2007 Environment
# Author: EverydayNerd.com
# Contact: Nerd [at] everydaynerd.com

# Uncomment to write to a database

#$db = “Enter Server Name Here”
#$catalog = “Enter Database Catalog Here”
#$conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=$db; Initial Catalog=$catalog; Integrated Security=SSPI")
#$conn.Open()

$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-1))
$servers = Get-ExchangeServer | Where{$_.ServerRole -eq 'None' -or $_.ServerRole -like '*Mailbox*'} | sort name
foreach ($server in $servers){
Write-Host $server
Get-WmiObject -computer $server -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'") |
ForEach-Object{
$time = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated).ToString()
$date = $time.split("' '")
$writedate = $date[0]
$mbnamearray = $_.message.split("' '")
$store = $mbnamearray[2]
$store = $store -replace '"', ''
$size = [math]::round(($mbnamearray[4]/1024),4)
$search = $server.ToString() + "\" + $store.ToString()

$test = Get-ExchangeServer $server
If ($server.ServerRole -eq 'None'){
$root =[ADSI]'LDAP://RootDSE'
$cfConfigRootpath = "
LDAP://" + $root.ConfigurationNamingContext.tostring()
$configRoot = [ADSI]$cfConfigRootpath
$searcher = New-Object DirectoryServices.DirectorySearcher($configRoot)
$searcher.Filter = '(&(objectCategory=msExchExchangeServer)(cn=' + $Server + '))'
$searchres = $searcher.FindOne()
$snServerEntry = New-Object System.DirectoryServices.directoryentry
$snServerEntry = $searchres.GetDirectoryEntry()


$adsiServer = [ADSI]('LDAP://' + $snServerEntry.DistinguishedName)
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($adsiServer)
$dfsearcher.Filter = "
(objectCategory=msExchPrivateMDB)"
$srSearchResults = $dfsearcher.FindAll()
foreach ($srSearchResult in $srSearchResults){
$msMailStore = $srSearchResult.GetDirectoryEntry()
$srnamearray = $_.message.split("
'\'")
$srstore = $mbnamearray[2]
$srstore = $srstore -replace '
"',''
If ($srstore.ToString() -like $store.ToString()){
$EDBFile = $msMailStore.msExchEDBFile
$EDBFilePath = "
\\" + $server.ToString() + "\" + $EDBFile.ToString()
$EDBFilePath = $EDBFilePath -replace ':', '$'
$EDBFileSize = Get-Item $EDBFilePath.ToString() | select Length
}
}
}
Else{
$EDBFile = Get-MailboxDatabase -Identity $search | select EDBFilePath
$EDBFile = $EDBFile -replace '@{EdbFilePath=', ''
$EDBFile = $EDBFile -replace '}', ''
$EDBFile = $EDBFile -replace ':', '$'
$EDBFilePath = "
\\" + $server.ToString() + "\" + $EDBFile.ToString()
$EDBFileSize = Get-Item $EDBFilePath.ToString() | select Length
}

$EDBFileSize = $EDBFileSize -replace '@{Length=', ''
$EDBFileSize = $EDBFileSize -replace '}', ''
$EDBFileSize = [math]::round(((($EDBFileSize/1024)/1024)/1024),2)

# Uncomment to write to a database
#$cmd = $conn.CreateCommand()
#$cmd.CommandText ="
INSERT EventLog1221 VALUES ('$writedate', '$server', '$store', '$size', '$EDBFileSize')"
#$cmd.ExecuteNonQuery()

Write-Host $writedate $server $store $size $EDBFileSize
}
}
# Uncomment to write to a database
#$conn.Close()





Auto Grow DPM Protection Groups by Percentage Thresholds

20 01 2009

Managing many DPM servers can turn into quite a time consuming activity, especially when it comes to allocating more disk space to Data Sources.  The Ctrl-P DPM blog has a real simple auto-grow script on their site, but I personally have had issues with it, as have many others on the Net.  It is also rather lacking in “bells and whistles” but for an everyday DPM admin, it sure would make life easier.  In my quest for ways to make my job easier, I found this absolutely AWESOME script that Owen Clashing wrote on his blog.

#This DPM powershell script helps automate the growing of replica and shadow copy volumes which need to be grown.
param([string] $DPMServerName, [string] $Mode, [int] $ReplicaThreshold, [int] $ReplicaGrowBy, [int] $RecoveryPointThreshold, [int] $RecoveryPointGrowBy)

###### Define variables for default values
$DefaultDPMServerName = $env:COMPUTERNAME # Assumes that the current computer is the DPM server
$DefaultMode = "A"
$DefaultReplicaThreshold = 90
$DefaultReplicaGrowBy = 5
$DefaultShadowCopyThreshold = 90
$DefaultShadowCopyGrowBy = 5
######

function Usage()
{
write-host
write-host "Usage::"
write-host "AutoGrowByPercentWithDefaults.ps1"
write-host "AutoGrowByPercentWithDefaults.ps1 -DPMServerName [DPMServername] -Mode [A|C]"
write-host
write-host "Run 'AutoGrowByPercentWithDefaults.ps1 -detailed' for detailed help"
write-host
write-host
}

if(("-?","-help") -contains $args[0])
{
Usage
exit 0
}

if(("-detailed") -contains $args[0])
{
write-host
write-host "Detailed Help : Use this script to automatically grow the replica and recovery point volume sizes"
write-host "Parameters:"
write-host "-DPMServerName [DPMServername] :: The name of the DPM server that is being targetted"
write-host "-Mode [A|C] :: A - Audit only (make no disk allocation changes); C - Change disk allocations"
write-host "-ReplicaThreshold [Replica Threshold %] :: Percentage usage above which disk space allocation for the replica volume will be triggered"
write-host "-ReplicaGrowBy [Replica Grow By %] :: Percentage by which to grow the replica volume"
write-host "-RecoveryPointThreshold [Recovery Point Threshold %] :: Percentage usage above which disk space allocation for the recovery point volume will be triggered"
write-host "-RecoveryPointGrowBy [Recovery Point Grow By %] :: Percentage by which to grow the recovery point volume"
write-host "Current default values:"
write-host "-DPMServerName $DefaultDPMServerName"
write-host "-Mode $DefaultMode"
write-host "-ReplicaThreshold $DefaultReplicaThreshold"
write-host "-ReplicaGrowBy $DefaultReplicaGrowBy"
write-host "-RecoveryPointThreshold $DefaultShadowCopyThreshold"
write-host "-RecoveryPointGrowBy $DefaultShadowCopyGrowBy"
write-host
exit 0
}

if(!$DPMServerName)
{
$DPMServerName = $DefaultDPMServerName
}

if(!$Mode)
{
$Mode = $DefaultMode
}
else
{
if (($Mode -ne "A") -or ($Mode -ne "C"))
{
Usage
exit 0
}
}

if(!$ReplicaThreshold)
{
$ReplicaThreshold = $DefaultReplicaThreshold
}

if(!$ReplicaGrowBy)
{
$ReplicaGrowBy = $DefaultReplicaGrowBy
}

# Note the inconsistency in the naming - Object model name Shadow Copy, GUI name Recovery Point
# We use the GUI names in naming the parameters to keep it familiar for the casual user.
if(!$RecoveryPointThreshold)
{
$ShadowCopyThreshold = $DefaultShadowCopyThreshold
}
else
{
$ShadowCopyThreshold = $RecoveryPointThreshold
}


if(!$RecoveryPointGrowBy)
{
$ShadowCopyGrowBy = $DefaultShadowCopyGrowBy
}
else
{
$ShadowCopyThreshold = $RecoveryPointGrowBy
}


switch ($Mode)
{
"A"
{
$ChangeHighlightColor = "Green"
write-host "In audit mode - No changes will be made to the disk allocations" -foregroundcolor $ChangeHighlightColor
}
"C"
{
$ChangeHighlightColor = "Red"
write-host "In change mode - Changes will be made to the disk allocations" -foregroundcolor $ChangeHighlightColor
}
}



$dpmserver = Connect-DPMServer $DPMServerName

if(!$dpmserver)
{
write-error "Unable to connect to $dpmservername"
exit 1
}

$PGList = @(Get-ProtectionGroup $DPMServerName)

foreach($PG in $PGList)
{
# Use a modifiable protection group only if we are in change mode
# A non-modifiable protection group object is significantly faster
if ($Mode -eq "C")
{
$MPG = Get-ModifiableProtectionGroup $PG
}
else
{
$MPG = $PG
}

$dslist=@(get-datasource $MPG)
foreach ($ds in $dslist)
{
$ReplicaUsedPercent = ($ds.ReplicaUsedSpace/$ds.ReplicaSize)
$ShadowCopyUsedPercent = ($ds.ShadowCopyUsedSpace/$ds.ShadowCopyAreaSize)
"------------------------------------------------------------------------"
#"Protection Group: $PG.Name"
"$ds"

# $ds.ReplicaSize = -1 when there is no replica component to the backup
# Only process if there is replica disk space allocated
if ($ds.ReplicaSize -ne -1)
{
"Replica Used % : {0:P2}" -f $ReplicaUsedPercent

if($ReplicaUsedPercent -gt $ReplicaThreshold/100)
{
$ReplicaGrowByActual = ($ReplicaGrowBy/100)*$ds.ReplicaSize
$NewReplicaSize = $ds.ReplicaSize + $ReplicaGrowByActual
"Replica Grow % : {0:P2}" -f $($ReplicaGrowBy/100)
write-host $("Replica Grow Actual (GB) : {0:N2}" -f $($ReplicaGrowByActual/1GB)) -foregroundcolor $ChangeHighlightColor
"Replica New Total (GB) : {0:N2}" -f $($NewReplicaSize/1GB)

if ($Mode -eq "C")
{
Set-DatasourceDiskAllocation -Manual -Datasource $ds -ProtectionGroup $MPG -ReplicaArea $NewReplicaSize
}
}
else
{
"Replica Grow % : 0.00 %"
"Replica Grow Actual (GB) : 0.00"
"Replica New Total (GB) : {0:N2}" -f $(($ds.ReplicaSize)/1GB)
}
}
else
{
"No disk space allocated for replica"
}

# $ds.ShadowCopyAreaSize = -1 when there is no shadow copy component to the backup
# Only process if there is shadow copy disk space allocated
if ($ds.ShadowCopyAreaSize -ne -1)
{
"Recovery Point Used % : {0:P2}" -f $ShadowCopyUsedPercent

if($ShadowCopyUsedPercent -gt $ShadowCopyThreshold/100)
{
$ShadowCopyGrowByActual = ($ShadowCopyGrowBy/100)*$ds.ShadowCopyAreaSize
$NewShadowCopySize = $ds.ShadowCopyAreaSize + $ShadowCopyGrowByActual
"Recovery Point Grow % : {0:P2}" -f $($ShadowCopyGrowBy/100)
write-host $("Recovery Point Grow Actual (GB): {0:N2}" -f $($ShadowCopyGrowByActual/1GB)) -foregroundcolor $ChangeHighlightColor
"Recovery Point New Total (GB) : {0:N2}" -f $($NewShadowCopySize/1GB)

if ($Mode -eq "C")
{
Set-DatasourceDiskAllocation -Manual -Datasource $ds -ProtectionGroup $MPG -ShadowCopyArea $NewShadowCopySize
}
}
else
{
"Recovery Point Grow % : 0.00 %"
"Recovery Point Grow Actual (GB): 0.00"
"Recovery Point New Total (GB) : {0:N2}" -f $($ds.ShadowCopyAreaSize/1GB)
}
}
else
{
"No disk space allocated for recovery point"
}
}

# Update the protection group if we are in change mode
if ($Mode -eq "C")
{
Set-ProtectionGroup $MPG
}
}

Disconnect-DPMServer $DPMServerName

"------------------------------------------------------------------------"

I LOVE the –MODE switch, allowing me to run the script, and see the results, without actually changing any disk allocations.  I’ve added this script to the DPM servers that I manage, and have the task scheduler run it twice a day.  No more failed jobs due to lack of disk space!  Yeah!





Script – Create Recovery Points

16 01 2009

In the environment that I work, DPM protects the Exchange 2007 servers.  I have only one Exchange server in each protection group.  Each Exchange server has between 10-20 Storage Groups (or Data Sources).  If I want to initiate a backup on the entire server, it is a pain to select each storage group, click Create Recovery Point, and select either Full or Incremental, then click Close. 

The script below does all that for me.  It connects to the DPM server, lists the Protection Groups, asks if you want to run an Express Full, or Incremental backup, then initiates the jobs for each Data Source in the Protection Group (each Storage Group on the Exchange Server).

# DPM 2007 Powershell Script
# Script to initiate a Recovery Point for each Data Source in a Protection Group
# Initial Script from Technet, but Modified to give more choices
# Edited by Dan Burgess
# nerd@EverydayNerd.com

param([string] $dpmname, [string] $pgname, [string] $backupoption)
# Clear the screen
cls
#Get name of Localhost
$CompStat = Get-WmiObject win32_computersystem
$Localhst = $CompStat.Name

# Notify that connected to Localhost
write-host ""
write-host "Script: Create-RecoveryPoint" -foregroundcolor Blue -backgroundcolor white
write-host ""
write-host ""
Write-host "Connected to Localhost: $Localhst" -foregroundcolor Blue -backgroundcolor white
write-host ""
write-host ""

# Set DPM Servername
$dpmname = read-host "DPM Server Name (Enter for $Localhst):"
if ($dpmname -eq "")
{
$dpmname = $Localhst
write-host "Using Localhost $dpmname " -foregroundcolor green
write-host ""
write-host ""
}

# List Protection Groups on DPM server
$pglist = get-protectiongroup -DPMServerName $dpmname
write-host "Protection Groups on $dpmname :" -foregroundcolor green
write-output $pglist
write-host ""
write-host ""

#Enter name of Protection Group you wish to create Recovery Point
$pgname = read-host "Enter Protection Group Name:"
write-host ""
write-host ""

#List choices for JobChoice1 Variable
write-host "1: Express Full"
write-host "2: Incremental"
write-host ""

$JobChoice1 = read-host "Enter Backup type - 1 or 2 [Default is 1: Express Full]:"

switch ($JobChoice1)
{
1 { $backupoption = 'ExpressFull' }
2 { $backupoption = 'Incremental' }
default { $backupoption = 'ExpressFull' }
}
write-host ""
Write-host "You selected $backupoption" -foregroundcolor Blue -backgroundcolor white
write-host ""

trap{"Error in execution... $_";break}

if($clipg -eq $abc)
{
write-host ""
Throw "No ProtectionGroup found"
write-host ""
}
else
{
write-host ""
write-host "Getting DataSource from Protection Group $pgname..." -foregroundcolor green
write-host ""

# Create variable of each Datasource from Protection Group
$backupds = @(Get-Datasource $clipg)

# Run the Job for each DataSource in Protection Group
foreach ($ds in $backupds)
{
write-host ""
write-host "Creating Recovery point for $ds..." -foregroundcolor Blue -backgroundcolor white
write-host ""

$job = New-RecoveryPoint -Datasource $ds -Disk -BackupType $backupoption
$jobtype = $job.jobtype
Write-host "$jobtype Job has been triggerred..." -foregroundcolor green
}
}
}

I’ve been playing around with this script for a while, and there is more that I want to do to it, but I figured I’d share it, and hope it helps someone out.  I’d love some input on how to make the script better!

One thing I’d really like to do, but have not been able to figure it out yet, is have a status update at the end, updating every 10 seconds showing the Server name, PGname, Status, and HasCompleted – until True.  Just a thought… would save me from having to RDP into all the DPM servers…





Powershell Script to list all Cluster Active Nodes

9 01 2009

If you have a medium to large infrastructure, it is helpful to know what node of your Exchange Clusters is the active node.  This can be done manually, but it is much easier if done with the following script:

 

$Clusters = Get-MailboxServer | Where-Object { $_.RedundantMachines } | Select Name
 
 foreach ($cluster in $clusters) {
    Get-ClusteredMailboxServerStatus -identity $Cluster.name | Select OperationalMachines,State 
 
    }








Design a site like this with WordPress.com
Get started