#Powershell Service Uptime

So i wanted to see how long a couple of BlackBerry servers had been up, but I wanted to know how long the services has been running.  So i knocked this up.  Its dead simple to change for other services!

$Servers = "BES01", "BES02"
$Matrix = @()
ForEach($Server in $Servers){
  Write-Host $Server -Foregroundcolor Green
  $SVC = Get-Service -ComputerName $Server | Where {$_.Name -like "Black*"}
  Foreach($item in $SVC){
    $tmpMatrix="" | Select Server, Service, State, Uptime
    Write-Host "-" $Item.Name
    $tmpMatrix.Server = $Server
    $tmpMatrix.Service = $item.Name
    $s = gwmi win32_service -ComputerName $Server -filter "name = ‘$($item.Name)’"
    $tmpMatrix.State = $s.State
    If ($s.State -eq "Running"){
      $tmpUpTime = "{0}" -f ((get-date) – ([wmi]”).ConvertToDateTime((gwmi Win32_Process  -ComputerName $Server -filter "ProcessID = ‘$($s.ProcessId)’").CreationDate))
      $tmpMatrix.Uptime = $tmpUpTime
    }
    $Matrix += $tmpMatrix
  }
}
  $Matrix

Get-DatabaseDistribution.ps1

#msexchange #powershell

How cr@p am I? I totally forgot about this baby.  So this is rough and ready Disappointed smile not had a chance to sort the help out at the beginning, but I’m sure you will get the idea.  Basically run this with one of the switches ByMailboxSize or ByMailboxCount and it will look at your exchange 2010 mailboxes and try and load balance the users.  It doesn’t actually DO anything, what it will do is generate a CSV that you use as input for Move-RequestFromCSV that is here: http://flaphead.dns2go.com/?p=2945

Let me know what you think.  In the test I have done so far ByMailboxCount is shweet, ByMailboxSize isn’t perfect.  Enjoy

PARAM([String]$Database="", [String]$BatchName, [Switch]$ByMailboxCount, [Switch]$ByMailboxSize, [String]$SizePercentage=2, [String]$ExportCSV="$pwdmiguserlist.csv")

#http://stackoverflow.com/questions/5863772/powershell-round-down-to-nearest-whole-number
function round( $value, [MidpointRounding]$mode = ‘AwayFromZero’ ) {   [Math]::Round( $value, $mode ) }

#$DB=@();Get-MailboxDatabase * | ForEach{$db += $_.name}

$xPsCheck = Get-PSSnapin | Select Name | Where {$_.Name -Like "*Exchange*"}
If ($xPsCheck -eq $Null) {Add-PsSnapin Microsoft.Exchange.Management.PowerShell.e2010}

Write-Host "Database:……."$Database
Write-Host "ByMailboxCount:."$ByMailboxCount
Write-Host "ByMailboxSize:.."$ByMailboxSize
Write-Host "SizePercentage:."$SizePercentage
Write-Host "ExportCSV:……"$ExportCSV
Write-Host ""

If ($Database -ne ""){
  $tmpDatabaseArray = $database.split(" ")
  $i=0
  $DatabaseHashTable = @{}
  ForEach($item in $tmpDatabaseArray){; $DatabaseHashTable.Add($i,$item); $i++}
}

$tmpDatabaseArray

$MailboxArray=@()
ForEach($item in $tmpDatabaseArray){
  Write-Host "`nChecking Database" $item -Foregroundcolor Green
  $position=$host.ui.rawui.cursorposition
  $tmpMailbox = Get-Mailbox -Database $item -ResultSize unlimited
  $mbxcnt   = 0
  $mbxItems = 0
  $mbxSize  = 0
  ForEach($xMailbox in $tmpMailbox){
    $tmpUser = $xmailbox.PrimarySmtpAddress.toString()
    $host.ui.rawui.cursorposition=$position;
    Write-Host "-" $tmpuser "                                                                          "
    $tmpMailboxArray = "" | Select DisplayName, Email, ServerName, Database, Items, Size, Target, Status 
    $tmpMailboxArray.DisplayName = $xMailbox.DisplayName
    $tmpMailboxArray.Email       = $tmpUser
    $tmpMailboxArray.ServerName  = $xMailbox.ServerName
    $tmpMailboxArray.Database    = $xMailbox.Database
    $tmpMailboxArray.Target      = $xMailbox.Database
    $tmpMailboxStatistics        = Get-Mailbox $tmpUser | Get-MailboxStatistics
    $tmpMailboxArray.Items       = $tmpMailboxStatistics.ItemCount
    $tmpMailboxArray.Size        = $tmpMailboxStatistics.TotalItemSize.Value.ToMB()
    $MailboxArray += $tmpMailboxArray
    $mbxcnt ++
    $mbxItems += $tmpMailboxArray.Items
    $mbxSize  += $tmpMailboxArray.Size
  }
  $host.ui.rawui.cursorposition=$position;
  Write-Host "-> Complete! " -NoNewLIne
  Write-Host $mbxcnt -NoNewLine -ForegroundColor Yellow
  Write-Host " Mailboxes Found with " -NoNewline
  Write-Host $mbxItems -NoNewLine -ForegroundColor Yellow
  Write-host " Items and " -NoNewLine
  Write-Host $mbxSize -ForegroundColor Yellow -NoNewLine
  Write-Host "MB            "
}

#Okay lets count the number of databases
$DatabaseCount = $tmpdatabasearray.count
$MailboxCount  = $MailboxArray.count
$MailboxSize   = ($MailboxArray | Measure-Object Size -sum).Sum
$MailboxesPerDatabase = round ($MailboxCount / $DatabaseCount )
$MBPerDatabase = round ($MailboxSize / $DatabaseCount )

Write-Host "Database Count:……………."$DatabaseCount
Write-Host "Mailbox Count:…………….."$MailboxCount
Write-Host "Ideal Mailboxes Per Database:.."$MailboxesPerDatabase
Write-Host "Total Size:……………….."$MailboxSize
Write-Host "Ideal MB Per Database:………"$MBPerDatabase
$MBPerDatabase = round ($MBPerDatabase + (($MBPerDatabase /100)*$SizePercentage))
Write-Host "`nMB Per Database (+"$SizePercentage"%) = "$MBPerDatabase

#Group MailboxArray by Database
$DatabaseCountArray = $MailboxArray | Group Database
$DatabaseMatrix = @()
ForEach($Item in $DatabaseCountArray){
  $tmpDatabaseMatrix = "" | Select Name, Count, Difference1, Difference2, MB , Difference3, Difference4
  $tmpDatabaseMatrix.Name        = $Item.Name
  $tmpDatabaseMatrix.Count       = $Item.Count
  $tmpDatabaseMatrix.Difference1 = $MailboxesPerDatabase – $Item.Count
  $tmpDatabaseMatrix.Difference2 = $Item.Count – $MailboxesPerDatabase
  $tmpDatabaseMatrix.MB    &#160
;     = ($Item.Group | Measure-Object Size -Sum).Sum
  $tmpDatabaseMatrix.Difference3 = $MBPerDatabase – $tmpDatabaseMatrix.MB
  $tmpDatabaseMatrix.Difference4 = $tmpDatabaseMatrix.MB – $MBPerDatabase

  $DatabaseMatrix += $tmpDatabaseMatrix
}
$DatabaseMatrix | ft

If ($ByMailboxSize){
  Write-Host "`nBY MAILBOX SIZE" -Foregroundcolor Red
  Write-Host "—————"
  Write-Host "`nFinding databases with excess mailboxes"
  $Database2MoveOff = $DatabaseMatrix | Where {$_.Difference4 -ge 0}
  ForEach($db in $Database2MoveOff){
    Write-Host $db.Name -Foregroundcolor Blue
    $tmpExcess = $MailboxArray | where {$_.Database -eq $db.Name} | Sort Size -Descending
    $targetMB=0
    ForEach($yUser in $MailboxArray | where {$_.Database -eq $db.Name} | Sort Size -Descending){
      $tmpMB = $yUser.Size
      If ($tmpMB + $targetMB -gt $MBPerDatabase){
        $yUser.Target = ""
      } ELSE {
        $yuser.Status = "Keep"
        $targetMB += $tmpMB
      } #If ($tmpMB + $targetMB -gt $MBPerDatabase)
    } #ForEach $yUser
  } #ForEach $db

  Write-Host "`nAssigning excess mailboxes"
  ForEach($item in $DatabaseMatrix | Where {$_.Difference3 -gt 0}){
    $Mailboxes2Move =  $DatabaseMatrix | Where {$_.Target -eq ""}  
    $targetMB=$item.MB
    ForEach($yUser in $MailboxArray | where {$_.Target -eq ""} | Sort Size -Descending){
      $tmpMB = $yUser.Size
      If ($tmpMB + $targetMB -gt $MBPerDatabase){
        $yUser.Target = ""
      } ELSE {
        $yuser.Target = $item.Name
        $yuser.Status = "Move"
        $targetMB += $tmpMB
      } #If ($tmpMB + $targetMB -gt $MBPerDatabase)
    } #ForEach $yUser
  } #ForEach $item

  Write-Host "`nSUMMARY" -Foregroundcolor Green
  Write-Host "Ideal MB Per Database:………"$MBPerDatabase
  $MailboxArray | Group Target | %{
    New-Object psobject -Property @{
        Item = $_.Name
        Sum = ($_.Group | Measure-Object Size -Sum).Sum
    }
  }
} #If ($ByMailboxSize)

If ($ByMailboxCount){
  Write-Host "`nBY MAILBOX COUNT" -Foregroundcolor Red
  Write-Host "—————-"
  Write-Host "Check to see if the Excess Mailboxes = Required " -NoNewLine
  $tmpcheck = ($DatabaseMatrix | Measure-Object Difference1 -Sum).sum
  Write-Host $tmpcheck -ForegroundColor Green

  Write-Host "`nFinding databases with excess mailboxes"
  $Database2MoveOff = $DatabaseMatrix | Where {$_.Difference2 -ge 0}
  $ExcessTotal = 0
  ForEach($db in $Database2MoveOff){
    Write-Host $db.Name -Foregroundcolor Blue
    Write-Host "Removing"$db.Difference2 "users`n"
    $ExcessTotal += $db.Difference2
    $MailboxArray | Where {$_.Database.Name -eq $db.name} | Select -First $db.Difference2 | ForEach{$_.Target = "";$_.Status = "Move"}
  }

  Write-Host "Total Excess Mailbox " $ExcessTotal
  $i=0
  ForEach($item in $DatabaseMatrix | Where {$_.Difference1 -gt 0}){
    $Mailboxes2Add = $item.Difference1
    $MailboxArray | Where {$_.Target -eq ""} | Select -First $Mailboxes2Add | ForEach{$_.Target = $item.Name}
  }

  Write-Host "`nSUMMARY" -Foregroundcolor Green
  $MailboxArray | Group Target
}#ByMailboxCount

#Foreach($line in $MailboxArray){Write-Host $line.Email"`t"$line.database}

Write-Host "`nMove Mailboxes"
$outCSV = @()
$ExcessMailboxes = $MailboxArray | where {$_.Status -eq "Move"}

ForEach($item in $ExcessMailboxes){
  $tmpOutCsv                = "" | Select email, TargetDatabase
  $tmpOutCSV.email          = $item.email
  $tmpOutCsv.TargetDatabase = $Item.Target
  $outCSV += $tmpOutCSV
}

ForEach($line in $outCSV){
  $position=$host.ui.rawui.cursorposition
  Write-Host $line.email
  $position.x = 50
  $host.ui.rawui.cursorposition=$position;
  Write-host $line.target
}
$outCSV | Export-csv $ExportCSV -NoTypeInformation

Get-LyncServer v1.3

#Powershell, #Lync

Wow feedback .. thanks mike for the observation on the vertical text.  Have updated it to do it a different way, so let me know what you think.

You can download it here or cut and paste below

<#
  .NOTES
  NAME: Get-LyncServer.ps1
  AUTHOR: Paul Flaherty
  Last Edit: "v1.3 [28 February 2012]

  v1.0 08 Feb 2012 : A script it born
  v1.1 20 Feb 2012 : Change Services to *RTC* instead of RTC*
  v1.2 21 Feb 2012 : Added Lync Server version
  v1.3 28 Feb 2012 : Updated HTML TH style

  .LINK
  blogs.flaphead.com

  .SYNOPSIS
  This Script gets connectes to a Lync Server and enumerates a list
  of all OCS/Lync Servers and gathers additional information.
.DESCRIPTION
  This script will connect to a Lync Server using the /OcsPowershell URI.
  Once connected it will use Get-CsComputer to get a list of OCS/Lync related servers.
  Then it uses Get-CsService to get a list of Lync Services and the Lync related
  windows services.

  The script then creates a matrix of the data an output a CSV file and HTML web Page
.OUTPUTS
  Get-LyncServer.html
  Get-LyncServer.csv
.EXAMPLE
  Get-LyncServer.ps1
  This will prompt you for Credentials and search the AD for a lync server to use
.EXAMPLE
  Get-LyncServer.ps1 -LyncServer myLyncServer01
  This will prompt you for Credentials and use the specified lync server.
  it will also add the default ad domain to the server name is missing
.EXAMPLE
  Get-LyncServer.ps1 -CredentialsFile .creds.txt
  This will search the AD for a lync server to use and use the current user account and
  credentials store in the CredentialsFile as the password
.EXAMPLE
  Get-LyncServer.ps1 -CredentialsFile .creds.txt -LyncServer myLyncServer01
  This will use the specified lync server and use the current user account and
  credentials store in the CredentialsFile as the password
  .PARAMETER LyncServer
  Netbios or FQDN of a lync server to use.
  If the Netbios name is used, the AD Domain DNS name will be appended
  .PARAMETER CredentialsFile
  Credentials Password file for the current logged on user.
  To Create the credentials file run:
  $creds = Get-Credential
  $creds.Password  | ConvertFrom-SecureString | Set-Content creds.txt

#>
##########################################################################################
PARAM([String]$LyncServer="", [String]$CredentialsFile="")

$AppName                = "Get-LyncServer.ps1"
$AppVer                 = "v1.3 [28 February 2012]"
$errorPref              = $errorActionPreference
$errorActionPreference  = "SilentlyContinue"
$ServerName             = hostname
$Today                  = Get-Date
$Global:CurrentUser     = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Global:CurrentUserName = $Global:CurrentUser.Name
$xUser                  = $Global:CurrentUserName
$currentdom             = [System.DirectoryServices.ActiveDirectory.Domain]::getcurrentdomain()
$Forest                 = $currentdom.Forest.ToString()
$ForestDomain           = $Forest
$xHTMLoutFolder         = "E:PsMon.LyncHTML"

##########################################################################################
#Display script name and version
#########################################################################################
Write-host " " $AppName -NoNewLine -foregroundcolor Green
Write-Host ": " $AppVer -foregroundcolor Green
Write-host "`n Run on $ServerName at $Today by $xUser" -foregroundcolor Yellow
Write-Host "|——————————————————————-|`n"
##########################################################################################
#Load the Lync bits & bobs
#########################################################################################
If($CredentialsFile -eq "") {
  $creds = Get-Credential -Credential $xUser
}ELSE{
  Write-Host "Using Credentials for " -NoNewLine
  Write-Host $xUser -NoNewLine -ForeGroundColor Yellow
  Write-Host " and password from " -NoNewLine
  Write-Host $CredentialsFile -ForeGroundColor Yellow

  $password = Get-Content $CredentialsFile | ConvertTo-SecureString
  $creds = New-Object System.Management.Automation.PsCredential $xUser,$password
} #$CredentialsFile

If($LyncServer -eq ""){
  Write-Host "Looking in RTCHSUniversalServices for a Lync Server"
  $Forest              = $Forest.Replace(".", ",DC=")
  $Forest              = "DC=" + $Forest
  $Dom                 = "LDAP://"
  $Dom                += $Forest
  $Root                = New-Object DirectoryServices.DirectoryEntry $Dom
  $Filter              = "(&(ObjectCategory=group)(name=*RTCHSUniversalServices*))"
  $selector            =
New-Object DirectoryServices.DirectorySearcher $Filter
  $selector.PageSize   = 1000
  $selector.SearchRoot = $root
  $objs                = $selector.findall()
  $tmpGroup            = $objs | Select Path -First 1
  $Group               = [ADSI]$tmpGroup.Path
  $GrpMembers          = $Group.Member
  $grpCnt              = $GrpMembers.Count
  Write-Host "Found Group.  It has " -NoNewLine
  Write-Host  $GrpCnt -NoNewLine -ForeGroundColor Green
  Write-Host " Members"

  $LyncServerList = @()
  ForEach($tmpMember in $GrpMembers){
    $tmpADSI = "LDAP://" + $tmpMember
    $tmpA    = [ADSI]$tmpADSI
    If($tmpA.objectClass -contains "computer"){$LyncServerList += $tmpA.Name}
  }

  $LyncServerList = $LyncServerList | Sort
  $tmpNumber = Get-Random -Minimum 0 -Maximum $LyncServerList.Count
  $LyncServer = $LyncServerList[$tmpNumber]
  $LyncServer = $LyncServer + "." + $ForestDomain
  $LyncConnectionURI = "
https://" + $LyncServer + "/OcsPowershell" 

 

}ELSE{
  IF($LyncServer.Contains(".") -eq $False){$LyncServer = $LyncServer + "." + $ForestDomain}
  $LyncConnectionURI = "
https://" + $LyncServer + "/OcsPowershell"
}

Write-Host "`nConnecting to:"$LyncConnectionURI
$s=New-PSSession -ConnectionURI $LyncConnectionURI -Credential $creds
If ($s -eq $Null){
  Write-Host "Error connecting to Lync" -Foregroundcolor Red
  Write-Host "Exiting" -Foregroundcolor Yellow
  Exit
}
Import-PSSession $s

$arrObjects = @()
$LyncRoleLabels = @()
$LyncRoleLabels += "Computer", "Pool", "Site", "ProductVersion", "DeploymentType", "OS", "RAM","UpToDate"

Write-Host "`nGetting Lync Servers`t" -NoNewLine
$LyncServers  = Get-CsComputer | Sort Identity
Write-host $LyncServers.Count"`n" -ForeGroundColor Green

Write-Host "Get-CsService`t" -NoNewLine
$LyncService  = Get-CsService
Write-Host $LyncService.count "Services found" -ForeGroundColor Green

Write-Host "`nGetting Windows Services"
$LyncWindowsServices = @()
ForEach($item in $LyncServers){
  $n = $item.Identity
  Write-Host $n"`t" -NoNewLine
  $tmpLWS = @()
  $tmpLWS = Get-Service *RTC* -ComputerName $n #| select @{Expression={($_.DisplayName).Replace(" ","")};Label="DisplayName"}, Status
  Write-Host $tmpLWS.count -ForeGroundColor Green
  $LyncWindowsServices += $tmpLWS

 
}
Write-host "Total Services Found"$LyncWindowsServices.count

$LyncWindowsServicesByServer = $LyncWindowsServices | Group MachineName

#Get Available Roles
Write-host "`nGetting Lync Server Roles"

$LyncRoles = $LyncService | group Role | sort name
ForEach($tmpRole in $LyncRoles){$LyncRoleLabels += $tmpRole.Name}
$LyncServiceByPool = $LyncService | Group PoolFqdn | Sort Name

#Get Available Services
$grpLyncWindowsServices = $LyncWindowsServices | Group DisplayName
$grpLyncWindowsServices | ForEach{$n = $_.name; $LyncRoleLabels += $n}

Write-Host "`nMatrix Label Count" $LyncRoleLabels.count
Write-Debug $LyncRoleLabels

Write-Host "`nBuilding Matrix"
ForEach($tmpServer in $LyncServers){
  $tmpLyncServerId = $tmpServer.Identity
  Write-Host $tmpLyncServerId
  $objSite = Get-CsPool -Identity $tmpServer.pool | Select-Object Site
  $objReplication = $Null
  $objReplication = Get-CsManagementStoreReplicationStatus -ReplicaFqdn $tmpLyncServerId | Select-Object UpToDate
  $strReplication = $objSite.site -replace("Site:","")
  $tmpOS          = Get-WmiObject win32_operatingsystem -ComputerName $tmpLyncServerId

  $key="SOFTWAREMicrosoftReal-Time Communications"
  $type = [Microsoft.Win32.RegistryHive]::LocalMachine
  $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $tmpLyncServerId)
  $regKey = $regKey.OpenSubKey($key, $True)
  $tmpLabel = $regKey.GetValueNames()
  $tmpVC = "" | Select $tmpLabel
  ForEach($vc in $regKey.GetValueNames()){$tmpVC.$vc = $regkey.GetValue($vc)}

  $tmpLyncServer = "" | Select $LyncRoleLabels
  $tmpLyncServer.Computer = $tmpLyncServerId
  $tmpLyncServer.Pool     = $tmpServer.Pool
  $tmpLyncServer.Site     = $strReplication
  $tmpLyncServer.UpToDate = $objReplication.UpToDate
  $tmpLyncServer.OS       = $tmpOS.Caption + " " + $tmpOS.CSDVersion
  $tmpLyncServer.RAM      = "!AR!" + $tmpOS.FreePhysicalMemory
  $tmpLyncServer.ProductVersion = $tmpVC.ProductVersion
  $tmpLyncServer.DeploymentType = $tmpVC.DeploymentType

  $tmpLSbP = $LyncServiceByPool | Where {$_
.Name -eq $tmpLyncServerId}
  ForEach($item in $tmpLSbP){
    $tmpG = $item.Group
    ForEach($itemG in $tmpG){
      $xRole = $itemG.Role
      $tmpLyncServer.$xRole = $True
    }
  }

  $tmpWinSvc = $LyncWindowsServicesByServer | Where {$_.Name -eq $tmpLyncServerId}
  ForEach($item in $tmpWinSvc){
    $tmpG = $item.Group
    Write-Host $tmpG.count  
    ForEach($itemG in $tmpG){
      $xSvc = $itemG.DisplayName
      Write-Host $xSvc
      $tmpLyncServer.$xSvc = "svc"
    }
  }

  $arrObjects += $tmpLyncServer
}

$HtmlHeader = "
<Style>
  TABLE{border-width: 1px;
        padding: 1px;
        border-style: solid;
        border-color: black;
        border-collapse: collapse;}
  TD{border-width: 1px;
     padding: 1px;
     border-style: solid;
     border-color: black;}
  TH{font-family:’Arial’;
     font-size:12px;
     border-width: 1px;
     padding: 1px;
     border-style: solid;
     border-color: black;
     background-color:peachpuff;
     white-space: nowrap;
     writing-mode:tb-rl;
     filter: flipv fliph;
     Text-align:left}
  TR{font-family:’Arial’;
     font-size:10px}
  P{font-family:’Arial’;}
</Style>
<TITLE>LYNC SERVERS</TITLE>"

$z="<B><FONT size=’2′ face=’VERDANA’>Lync Servers</B></FONT><BR><FONT size=’1′ face=’VERDANA’>Last updated: $today</FONT></font><HR size=6 color=Green>"
$xHTML = $arrObjects | ConvertTo-Html -head $HtmlHeader -Title "Lync Server Info" -body $z

$txtYELLOW = @()
$txtAR     = @()
$i=0; $xHTML | foreach{IF ($_ -like "*<td>True*"){ $txtYellow += $i}; $i++}
$txtYELLOW | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<td>True","<td bgcolor=ORANGE>True")}

$txtYELLOW = @()
$i=0; $xHTML | foreach{IF ($_ -like "*<td>svc*"){ $txtYellow += $i}; $i++}
$txtYELLOW | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<td>svc","<td bgcolor=ORANGE>svc")}

$i=0; $xHTML | foreach{IF ($_ -like "*>!AR!*"){ $txtAR += $i;}; $i++}
$txtAR | ForEach{$xHTML[$_] = $xHTML[$_].Replace(">!AR!"," align=right>")}

$xEnd = get-Date
$xHTML += "
<HR size=6 color=Green>
<FONT size=’1′ face=’VERDANA’>Script Completed: $xEnd</FONT>
</FONT><BR></BODY>
</HTML>
"

$arrObjects | ForEach{$_.RAM = $_.RAM.Replace("!AR!","")}
$xHTML      | out-file $xHTMLoutFolderGet-LyncServer.html
$arrObjects | Export-csv Get-LyncServer.csv -NoTypeInformation

Get-PSSession | ForEach{Remove-PSSession -id $_.id}
$errorActionPreference = $errorPref
#End
##########################################################################################

Get-LyncServer v1.2

#Powershell, #Lync

Okay so made some updates to include Lync/OCS version, Lync Type, OS and Memory.  Also change the services from RTC* to *RTC*

Downloadable from here or cut and paste below .. enjoy

<#
  .NOTES
  NAME: Get-LyncServer.ps1
  AUTHOR: Paul Flaherty
  Last Edit: "v1.2 [21 February 2012]
  .LINK
  blogs.flaphead.com
  .SYNOPSIS
  This Script gets connectes to a Lync Server and enumerates a list
  of all OCS/Lync Servers and gathers additional information.
 .DESCRIPTION
  This script will connect to a Lync Server using the /OcsPowershell URI.
  Once connected it will use Get-CsComputer to get a list of OCS/Lync related servers.
  Then it uses Get-CsService to get a list of Lync Services and the Lync related
  windows services.

  The script then creates a matrix of the data an output a CSV file and HTML web Page
 .OUTPUTS
  Get-LyncServer.html
  Get-LyncServer.csv
 .EXAMPLE
  Get-LyncServer.ps1
  This will prompt you for Credentials and search the AD for a lync server to use
 .EXAMPLE
  Get-LyncServer.ps1 -LyncServer myLyncServer01
  This will prompt you for Credentials and use the specified lync server.
  it will also add the default ad domain to the server name is missing
 .EXAMPLE
  Get-LyncServer.ps1 -CredentialsFile .creds.txt
  This will search the AD for a lync server to use and use the current user account and
  credentials store in the CredentialsFile as the password
 .EXAMPLE
  Get-LyncServer.ps1 -CredentialsFile .creds.txt -LyncServer myLyncServer01
  This will use the specified lync server and use the current user account and
  credentials store in the CredentialsFile as the password
  .PARAMETER LyncServer
  Netbios or FQDN of a lync server to use.
  If the Netbios name is used, the AD Domain DNS name will be appended
  .PARAMETER CredentialsFile
  Credentials Password file for the current logged on user.
  To Create the credentials file run:
  $creds = Get-Credential
  $creds.Password  | ConvertFrom-SecureString | Set-Content creds.txt

#>

PARAM([String]$LyncServer="", [String]$CredentialsFile="")
##########################################################################################
$AppName = "Get-LyncServer.ps1"
$AppVer  = "v1.0 [13 February 2012]"
#v1.0 08 Feb 2012 : A script it born
#v1.1 20 Feb 2012 : Change Services to *RTC* instead of RTC*
#v1.2 21 Feb 2012 : Added Lync Server version
#
# This script gets a list of Lync Servers
#
#Written By Paul Flaherty
#blogs.flaphead.com
##########################################################################################
$errorPref = $errorActionPreference
$errorActionPreference = "SilentlyContinue"

$ServerName             = hostname
$Today                  = Get-Date
$Global:CurrentUser     = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Global:CurrentUserName	= $Global:CurrentUser.Name
$xUser                  = $Global:CurrentUserName
$currentdom             = [System.DirectoryServices.ActiveDirectory.Domain]::getcurrentdomain()
$Forest                 = $currentdom.Forest.ToString()
$ForestDomain           = $Forest

$xHTMLoutFolder         = "E:PsMon.LyncHTML"

##########################################################################################
#Display script name and version
#########################################################################################
Write-host " " $AppName -NoNewLine -foregroundcolor Green
Write-Host ": " $AppVer -foregroundcolor Green
Write-host "`n Run on $ServerName at $Today by $xUser" -foregroundcolor Yellow
Write-Host "|-------------------------------------------------------------------|`n"
##########################################################################################
#Load the Lync bits & bobs
#########################################################################################
If($CredentialsFile -eq "") {
  $creds = Get-Credential -Credential $xUser
}ELSE{
  Write-Host "Using Credentials for " -NoNewLine
  Write-Host $xUser -NoNewLine -ForeGroundColor Yellow
  Write-Host " and password from " -NoNewLine
  Write-Host $CredentialsFile -ForeGroundColor Yellow

  $password = Get-Content $CredentialsFile | ConvertTo-SecureString
  $creds = New-Object System.Management.Automation.PsCredential $xUser,$password
} #$CredentialsFile

If($LyncServer -eq ""){
  Write-Host "Looking in RTCHSUniversalServices for a Lync Server"
  $Forest              = $Forest.Replace(".", ",DC=")
  $Forest              = "DC=" + $Forest
  $Dom                 = "LDAP://"
  $Dom                += $Forest
  $Root                = New-Object DirectoryServices.DirectoryEntry $Dom
  $Filter              = "(&(ObjectCategory=group)(name=*RTCHSUniversalServices*))"
  $selector            = New-Object DirectoryServices.DirectorySearcher $Filter
  $selector.PageSize   = 1000
  $selector.SearchRoot = $root
  $objs                = $selector.findall()
  $tmpGroup            = $objs | Select Path -First 1
  $Group               = [ADSI]$tmpGroup.Path
  $GrpMembers          = $Group.Member
  $grpCnt              = $GrpMembers.Count
  Write-Host "Found Group.  It has " -NoNewLine
  Write-Host  $GrpCnt -NoNewLine -ForeGroundColor Green
  Write-Host " Members"

  $LyncServerList = @()
  ForEach($tmpMember in $GrpMembers){
    $tmpADSI = "LDAP://" + $tmpMember
    $tmpA    = [ADSI]$tmpADSI
    If($tmpA.objectClass -contains "computer"){$LyncServerList += $tmpA.Name}
  }

  $LyncServerList = $LyncServerList | Sort
  $tmpNumber = Get-Random -Minimum 0 -Maximum $LyncServerList.Count
  $LyncServer = $LyncServerList[$tmpNumber]
  $LyncServer = $LyncServer + "." + $ForestDomain
  $LyncConnectionURI = "https://" + $LyncServer + "/OcsPowershell"



}ELSE{
  IF($LyncServer.Contains(".") -eq $False){$LyncServer = $LyncServer + "." + $ForestDomain}
  $LyncConnectionURI = "https://" + $LyncServer + "/OcsPowershell"
}

Write-Host "`nConnecting to:"$LyncConnectionURI
$s=New-PSSession -ConnectionURI $LyncConnectionURI -Credential $creds
If ($s -eq $Null){
  Write-Host "Error connecting to Lync" -Foregroundcolor Red
  Write-Host "Exiting" -Foregroundcolor Yellow
  Exit
}
Import-PSSession $s

$arrObjects = @()
$LyncRoleLabels = @()
$LyncRoleLabels += "Computer", "Pool", "Site", "ProductVersion", "DeploymentType", "OS", "RAM","UpToDate"

Write-Host "`nGetting Lync Servers`t" -NoNewLine
$LyncServers  = Get-CsComputer | Sort Identity
Write-host $LyncServers.Count"`n" -ForeGroundColor Green

Write-Host "Get-CsService`t" -NoNewLine
$LyncService  = Get-CsService
Write-Host $LyncService.count "Services found" -ForeGroundColor Green

Write-Host "`nGetting Windows Services"
$LyncWindowsServices = @()
ForEach($item in $LyncServers){
  $n = $item.Identity
  Write-Host $n"`t" -NoNewLine
  $tmpLWS = @()
  $tmpLWS = Get-Service *RTC* -ComputerName $n #| select @{Expression={($_.DisplayName).Replace(" ","")};Label="DisplayName"}, Status
  Write-Host $tmpLWS.count -ForeGroundColor Green
  $LyncWindowsServices += $tmpLWS


}
Write-host "Total Services Found"$LyncWindowsServices.count

$LyncWindowsServicesByServer = $LyncWindowsServices | Group MachineName

#Get Available Roles
Write-host "`nGetting Lync Server Roles"

$LyncRoles = $LyncService | group Role | sort name
ForEach($tmpRole in $LyncRoles){$LyncRoleLabels += $tmpRole.Name}
$LyncServiceByPool = $LyncService | Group PoolFqdn | Sort Name

#Get Available Services
$grpLyncWindowsServices = $LyncWindowsServices | Group DisplayName
$grpLyncWindowsServices | ForEach{$n = $_.name; $LyncRoleLabels += $n}

Write-Host "`nMatrix Label Count" $LyncRoleLabels.count
Write-Debug $LyncRoleLabels

Write-Host "`nBuilding Matrix"
ForEach($tmpServer in $LyncServers){
  $tmpLyncServerId = $tmpServer.Identity
  Write-Host $tmpLyncServerId
  $objSite = Get-CsPool -Identity $tmpServer.pool | Select-Object Site
  $objReplication = $Null
  $objReplication = Get-CsManagementStoreReplicationStatus -ReplicaFqdn $tmpLyncServerId | Select-Object UpToDate
  $strReplication = $objSite.site -replace("Site:","")
  $tmpOS          = Get-WmiObject win32_operatingsystem -ComputerName $tmpLyncServerId

  $key="SOFTWAREMicrosoftReal-Time Communications"
  $type = [Microsoft.Win32.RegistryHive]::LocalMachine
  $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $tmpLyncServerId)
  $regKey = $regKey.OpenSubKey($key, $True)
  $tmpLabel = $regKey.GetValueNames()
  $tmpVC = "" | Select $tmpLabel
  ForEach($vc in $regKey.GetValueNames()){$tmpVC.$vc = $regkey.GetValue($vc)}


  $tmpLyncServer = "" | Select $LyncRoleLabels
  $tmpLyncServer.Computer = $tmpLyncServerId
  $tmpLyncServer.Pool     = $tmpServer.Pool
  $tmpLyncServer.Site     = $strReplication
  $tmpLyncServer.UpToDate = $objReplication.UpToDate
  $tmpLyncServer.OS       = $tmpOS.Caption + " " + $tmpOS.CSDVersion
  $tmpLyncServer.RAM      = "!AR!" + $tmpOS.FreePhysicalMemory
  $tmpLyncServer.ProductVersion = $tmpVC.ProductVersion
  $tmpLyncServer.DeploymentType = $tmpVC.DeploymentType

  $tmpLSbP = $LyncServiceByPool | Where {$_.Name -eq $tmpLyncServerId}
  ForEach($item in $tmpLSbP){
    $tmpG = $item.Group
    ForEach($itemG in $tmpG){
      $xRole = $itemG.Role
      $tmpLyncServer.$xRole = $True
    }
  }

  $tmpWinSvc = $LyncWindowsServicesByServer | Where {$_.Name -eq $tmpLyncServerId}
  ForEach($item in $tmpWinSvc){
    $tmpG = $item.Group
    Write-Host $tmpG.count
    ForEach($itemG in $tmpG){
      $xSvc = $itemG.DisplayName
      Write-Host $xSvc
      $tmpLyncServer.$xSvc = $True
    }
  }

  $arrObjects += $tmpLyncServer
}


$HtmlHeader = "
<Style>
  TABLE{border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
  TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}
  TH{font-family:'Arial';font-size:12px;border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;layout-flow:vertical-ideographic;Text-align:left}
  TR{font-family:'Arial';font-size:10px}
  P{font-family:'Arial';}
</Style>
<TITLE>LYNC SERVERS</TITLE>"

$z="<B><FONT size='2' face='VERDANA'>Lync Servers</B></FONT><BR><FONT size='1' face='VERDANA'>Last updated: $today</FONT></font><HR size=6 color=Green>"
$xHTML = $arrObjects | ConvertTo-Html -head $HtmlHeader -Title "Lync Server Info" -body $z

$txtYELLOW = @()
$txtAR     = @()
$i=0; $xHTML | foreach{IF ($_ -like "*<td>True*"){ $txtYellow += $i}; $i++}
$txtYELLOW | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<td>True","<td bgcolor=ORANGE>True")}

$i=0; $xHTML | foreach{IF ($_ -like "*>!AR!*"){ $txtAR += $i;}; $i++}
$txtAR | ForEach{$xHTML[$_] = $xHTML[$_].Replace(">!AR!"," align=right>")}


$xEnd = get-Date
$xHTML += "
<HR size=6 color=Green>
<FONT size='1' face='VERDANA'>Script Completed: $xEnd</FONT>
</FONT><BR></BODY>
</HTML>
"

$xHTML      | out-file $xHTMLoutFolderGet-LyncServer.html
$arrObjects | Export-csv Get-LyncServer.csv -NoTypeInformation

Get-PSSession | ForEach{Remove-PSSession -id $_.id}
$errorActionPreference = $errorPref
#End
##########################################################################################

Get-LyncServer v1

#Powershell, #Lync

So I just love Exchange 2010 and PowerShell, and a cmdlet that rocks is Get-ExchangeServer which is a cmdlet that get the attributes of some or all the servers in the Exchange organization.

Lync however doesn’t have a similar cmdlet and that annoyed the hell out of me.  All I want is a list of Lync Servers and what they do .. simple you would think! Think again Disappointed smile

So I knocked this up.  It has some help text too that will help with the usage.  You can run get-help ./get-lyncserver –full

The basic output is a HTML summary matrix and a csv file that I use as input to other scripts.  Essentially I run this script once a day and then the other scripts when needed.

Oh another thing, the connectionuri needs credentials .. help explains how to set them or you get a prompt.

Let me know what you think!  this is v1 to enjoy

You can download the script from here or copy and paste from here:

<#
  .NOTES
  NAME: Get-LyncServer.ps1
  AUTHOR: Paul Flaherty
  Last Edit: "v1.0 [13 February 2012]
  .LINK
  blogs.flaphead.com
  .SYNOPSIS
  This Script gets connects to a Lync Server and enumerates a list
  of all OCS/Lync Servers and gathers additional information.
 .DESCRIPTION
  This script will connect to a Lync Server using the /OcsPowershell URI.
  Once connected it will use Get-CsComputer to get a list of OCS/Lync related servers.
  Then it uses Get-CsService to get a list of Lync Services and the Lync related
  windows services.

  The script then creates a matrix of the data an output a CSV file and HTML web Page
 .OUTPUTS
  Get-LyncServer.html
  Get-LyncServer.csv
 .EXAMPLE
  Get-LyncServer.ps1
  This will prompt you for Credentials and search the AD for a lync server to use
 .EXAMPLE
  Get-LyncServer.ps1 -LyncServer myLyncServer01
  This will prompt you for Credentials and use the specified lync server.
  it will also add the default ad domain to the server name is missing
 .EXAMPLE
  Get-LyncServer.ps1 -CredentialsFile .creds.txt
  This will search the AD for a lync server to use and use the current user account and
  credentials store in the CredentialsFile as the password
 .EXAMPLE
  Get-LyncServer.ps1 -CredentialsFile .creds.txt -LyncServer myLyncServer01
  This will use the specified lync server and use the current user account and
  credentials store in the CredentialsFile as the password
  .PARAMETER LyncServer
  Netbios or FQDN of a lync server to use.
  If the Netbios name is used, the AD Domain DNS name will be appended
  .PARAMETER CredentialsFile
  Credentials Password file for the current logged on user.
  To Create the credentials file run:
  $creds = Get-Credential
  $creds.Password  | ConvertFrom-SecureString | Set-Content creds.txt

#>

PARAM([String]$LyncServer="", [String]$CredentialsFile="")
##########################################################################################
$AppName = "Get-LyncServer.ps1"
$AppVer  = "v1.0 [13 February 2012]"
#v1.0 08 Feb 2012 : A script it born
#
# This script gets a list of Lync Servers
#
#Written By Paul Flaherty
#blogs.flaphead.com
##########################################################################################
$errorPref = $errorActionPreference
$errorActionPreference = "SilentlyContinue"

$ServerName             = hostname
$Today                  = Get-Date
$Global:CurrentUser     = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Global:CurrentUserName	= $Global:CurrentUser.Name
$xUser                  = $Global:CurrentUserName
$currentdom             = [System.DirectoryServices.ActiveDirectory.Domain]::getcurrentdomain()
$Forest                 = $currentdom.Forest.ToString()
$ForestDomain           = $Forest

$xHTMLoutFolder         = $pwd

##########################################################################################
#Display script name and version
#########################################################################################
Write-host " " $AppName -NoNewLine -foregroundcolor Green
Write-Host ": " $AppVer -foregroundcolor Green
Write-host "`n Run on $ServerName at $Today by $xUser" -foregroundcolor Yellow
Write-Host "|-------------------------------------------------------------------|`n"
##########################################################################################
#Load the Lync bits & bobs
#########################################################################################
If($CredentialsFile -eq "") {
  $creds = Get-Credential -Credential $xUser
}ELSE{
  Write-Host "Using Credentials for " -NoNewLine
  Write-Host $xUser -NoNewLine -ForeGroundColor Yellow
  Write-Host " and password from " -NoNewLine
  Write-Host $CredentialsFile -ForeGroundColor Yellow

  $password = Get-Content $CredentialsFile | ConvertTo-SecureString
  $creds = New-Object System.Management.Automation.PsCredential $xUser,$password
} #$CredentialsFile

If($LyncServer -eq ""){
  Write-Host "Looking in RTCHSUniversalServices for a Lync Server"
  $Forest              = $Forest.Replace(".", ",DC=")
  $Forest              = "DC=" + $Forest
  $Dom                 = "LDAP://"
  $Dom                += $Forest
  $Root                = New-Object DirectoryServices.DirectoryEntry $Dom
  $Filter              = "(&(ObjectCategory=group)(name=*RTCHSUniversalServices*))"
  $selector            = New-Object DirectoryServices.DirectorySearcher $Filter
  $selector.PageSize   = 1000
  $selector.SearchRoot = $root
  $objs                = $selector.findall()
  $tmpGroup            = $objs | Select Path -First 1
  $Group               = [ADSI]$tmpGroup.Path
  $GrpMembers          = $Group.Member
  $grpCnt              = $GrpMembers.Count
  Write-Host "Found Group.  It has " -NoNewLine
  Write-Host  $GrpCnt -NoNewLine -ForeGroundColor Green
  Write-Host " Members"

  $LyncServerList = @()
  ForEach($tmpMember in $GrpMembers){
    $tmpADSI = "LDAP://" + $tmpMember
    $tmpA    = [ADSI]$tmpADSI
    If($tmpA.objectClass -contains "computer"){$LyncServerList += $tmpA.Name}
  }

  $LyncServerList = $LyncServerList | Sort
  $tmpNumber = Get-Random -Minimum 0 -Maximum $LyncServerList.Count
  $LyncServer = $LyncServerList[$tmpNumber]
  $LyncServer = $LyncServer + "." + $ForestDomain
  $LyncConnectionURI = "https://" + $LyncServer + "/OcsPowershell"



}ELSE{
  IF($LyncServer.Contains(".") -eq $False){$LyncServer = $LyncServer + "." + $ForestDomain}
  $LyncConnectionURI = "https://" + $LyncServer + "/OcsPowershell"
}

Write-Host "`nConnecting to:"$LyncConnectionURI
$s=New-PSSession -ConnectionURI $LyncConnectionURI -Credential $creds
If ($s -eq $Null){
  Write-Host "Error connecting to Lync" -Foregroundcolor Red
  Write-Host "Exiting" -Foregroundcolor Yellow
  Exit
}
Import-PSSession $s

$arrObjects = @()
$LyncRoleLabels = @()
$LyncRoleLabels += "Computer", "Pool", "Site", "UpToDate"

Write-Host "`nGetting Lync Servers`t" -NoNewLine
$LyncServers  = Get-CsComputer | Sort Identity
Write-host $LyncServers.Count"`n" -ForeGroundColor Green

Write-Host "Get-CsService`t" -NoNewLine
$LyncService  = Get-CsService
Write-Host $LyncService.count "Services found" -ForeGroundColor Green

Write-Host "`nGetting Windows Services"
$LyncWindowsServices = @()
ForEach($item in $LyncServers){
  $n = $item.Identity
  Write-Host $n"`t" -NoNewLine
  $tmpLWS = @()
  $tmpLWS = Get-Service RTC* -ComputerName $n #| select @{Expression={($_.DisplayName).Replace(" ","")};Label="DisplayName"}, Status
  Write-Host $tmpLWS.count -ForeGroundColor Green
  $LyncWindowsServices += $tmpLWS
}
Write-host "Total Services Found"$LyncWindowsServices.count

$LyncWindowsServicesByServer = $LyncWindowsServices | Group MachineName

#Get Available Roles
Write-host "`nGetting Lync Server Roles"

$LyncRoles = $LyncService | group Role | sort name
ForEach($tmpRole in $LyncRoles){$LyncRoleLabels += $tmpRole.Name}
$LyncServiceByPool = $LyncService | Group PoolFqdn | Sort Name

#Get Available Services
$grpLyncWindowsServices = $LyncWindowsServices | Group DisplayName
$grpLyncWindowsServices | ForEach{$n = $_.name; $LyncRoleLabels += $n}

Write-Host "`nMatrix Label Count" $LyncRoleLabels.count
Write-Debug $LyncRoleLabels

Write-Host "`nBuilding Matrix"
ForEach($tmpServer in $LyncServers){
  $tmpLyncServerId = $tmpServer.Identity
  Write-Host $tmpLyncServerId
  $objSite = Get-CsPool -Identity $tmpServer.pool | Select-Object Site
  $objReplication = $Null
  $objReplication = Get-CsManagementStoreReplicationStatus -ReplicaFqdn $tmpLyncServerId | Select-Object UpToDate
  $strReplication = $objSite.site -replace("Site:","")

  $tmpLyncServer = "" | Select $LyncRoleLabels
  $tmpLyncServer.Computer = $tmpLyncServerId
  $tmpLyncServer.Pool     = $tmpServer.Pool
  $tmpLyncServer.Site     = $strReplication
  $tmpLyncServer.UpToDate = $objReplication.UpToDate

  $tmpLSbP = $LyncServiceByPool | Where {$_.Name -eq $tmpLyncServerId}
  ForEach($item in $tmpLSbP){
    $tmpG = $item.Group
    ForEach($itemG in $tmpG){
      $xRole = $itemG.Role
      $tmpLyncServer.$xRole = $True
    }
  }

  $tmpWinSvc = $LyncWindowsServicesByServer | Where {$_.Name -eq $tmpLyncServerId}
  ForEach($item in $tmpWinSvc){
    $tmpG = $item.Group
    Write-Host $tmpG.count
    ForEach($itemG in $tmpG){
      $xSvc = $itemG.DisplayName
      Write-Host $xSvc
      $tmpLyncServer.$xSvc = $True
    }
  }

  $arrObjects += $tmpLyncServer
}


$HtmlHeader = "
<Style>
  TABLE{border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
  TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}
  TH{font-family:'Arial';font-size:12px;border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;layout-flow:vertical-ideographic;Text-align:left}
  TR{font-family:'Arial';font-size:10px}
  P{font-family:'Arial';}
</Style>
<TITLE>LYNC SERVERS</TITLE>"

$z="<B><FONT size='2' face='VERDANA'>Lync Servers</B></FONT><BR><FONT size='1' face='VERDANA'>Last updated: $today</FONT></font><HR size=6 color=Green>"
$xHTML = $arrObjects | ConvertTo-Html -head $HtmlHeader -Title "Lync Server Info" -body $z

$txtYELLOW = @()
$i=0; $xHTML | foreach{IF ($_ -like "*<td>True*"){ $txtYellow += $i}; $i++}
$txtYELLOW | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<td>True","<td bgcolor=ORANGE>True")}


$xEnd = get-Date
$xHTML += "
<HR size=6 color=Green>
<FONT size='1' face='VERDANA'>Script Completed: $xEnd</FONT>
</FONT><BR></BODY>
</HTML>
"

$xHTML      | out-file $xHTMLoutFolderGet-LyncServer.html
$arrObjects | Export-csv Get-LyncServer.csv -NoTypeInformation

Get-PSSession | ForEach{Remove-PSSession -id $_.id}
$errorActionPreference = $errorPref
#End
##########################################################################################

Dump-RBAC.ps1

#Exchange #Exchange2010 #Powershell

So I have been meaning to post this for a while, so here it is.  I have a need to dump out the RBAC permissions for Exchange 2010 so I could see who had what.  So here is is.  The output is a HTML file.  You will need to create a folder called C:ps for it save it to.

Enjoy .. feedback welcome Winking smile

 

$Error.Clear()
#########################################################################################
$AppName = "Dump-RBAC.ps1"
$AppVer  = "v1.0 [4th Feburary 20111]"
#
#v1.0  05 Aug 2011 : A Script is born

#This script exports relevant RBAC information and generate a webpage
##########################################################################################

##########################################################################################
#Load the Exchange 2010 bits & bobs
#########################################################################################
$xPsCheck = Get-PSSnapin | Select Name | Where {$_.Name -Like "*Exchange*"}
If ($xPsCheck -eq $Null) {Add-PsSnapin Microsoft.Exchange.Management.PowerShell.e2010}

##########################################################################################
#Display script name and version
#########################################################################################
Write-host " " $AppName -NoNewLine -foregroundcolor Green
Write-Host ": " $AppVer -foregroundcolor Green
Write-host "`n Run on $ServerName at $Today by $xUser" -foregroundcolor Yellow
Write-Host "|——————————————————————-|`n"
Write-host "Log Folder: $DateFolder"

$RBACArray      = @()
$RBACCmd        = @()
$RoleGroupArray = @()

$tmpCols = Get-ManagementRoleAssignment
$tmpCols | group RoleAssigneeName | sort name | Select Name | ForEach{$feName = $_.Name; $feName = $feName.Replace(" ","");$xHTML += "<td>" + $fename + "</td>"}

$x=@();$x+="RoleName"; $tmpCols | group RoleAssigneeName | sort name | Select Name | ForEach{$feName = $_.Name; $feName = $feName.Replace(" ","");$x += $fename}

$tmpgmr = Get-ManagementRole | Sort Name
Write-Host "Getting Management Role Information"
ForEach($tmpRole in $tmpgmr){
  $tmpName = $tmpRole.Name
  Write-Host $tmpName
  $tmpArray = "" | Select $x
  $tmpCmd   = "" | Select RoleName, Commands

  ($tmpRole).RoleEntries | ForEach {$tmpcmd.Commands += $_.Name + " | "}

  $tmparray.RoleName = $tmpName #$_.Role
  $tmpCmd.RoleName   = $tmpName

  $gmra = $tmpCols | where {$_.Role -eq "$TmpName"}
  $gmra | sort RoleAssigneeName | ForEacH{$yy = $_.RoleAssigneeName;
    $yy = $yy.Replace(" ","")
    $tmparray.$yy = "x"
  }
  $RBACArray += $tmpArray
  $RBACCmd   += $tmpcmd
}

$tmpRoleGroups = $tmpCols | Where {$_.RoleAssigneeType -eq "RoleGroup"} | Group RoleAssigneeName | Select Name | Sort Name
$tmpRoleGroups | ForEach{
  $tmpmem = ""
  $tmpRG = "" | Select Name, Members
  $tmpRG.Name = $_.Name
  $tmpRG.Name
  $tmpGroup = Get-Group $tmpRG.Name
  $tmpGroupMembers = $tmpGroup.Members
  $tmpGroupMembers | ForEach{$tmpRG.Members += $_.Name + " | "}
  $RoleGroupArray += $tmpRG
}

$today = Get-Date
$HtmlHeader = "
<Style>
  TABLE{border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
  TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}
  TH{font-family:’Arial’;font-size:12px;border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;layout-flow:vertical-ideographic;Text-align:left}
  TR{font-family:’Arial’;font-size:10px}
  P{font-family:’Arial’;}
</Style>
<TITLE>Exchange Server 2010 RBAC</TITLE>"
$z="<B><FONT size=’2′ face=’VERDANA’>Exchange Server 2010 RBAC Information</B></FONT><BR><FONT size=’1′ face=’VERDANA’>Last updated: $today</FONT></font><HR size=6 color=Green>"
$xhtml = $RBACArray | ConvertTo-Html -head $HtmlHeader  -Title "Exchange Server 2010 RBAC" -body $z -PreContent "<FONT size=’2′ face=’VERDANA’>"

$txtYELLOW = @()
$i=0; $xHTML | foreach{IF ($_ -like "*<td>x</td>*"){ $txtYELLOW += $i}; $i++}
$txtYELLOW | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<td>x</td>","<td bgcolor=Yellow align=center><B>x</B></td>")}

$xHTML += "<HR>"
$xHTML += $RBACCmd | ConvertTo-Html -Fragment

$xHTML += "<HR>"
$xHTML += $RoleGroupArray  | ConvertTo-Html -Fragment

$xhtml | out-file c:psrbac.html

Get-RegistryValue

#Powershell

So I have been messing with Powershell for a while now, Jeff asked me to look at script he had that read remote registry values.  He was using PSRemoteRegistry but got some errors.

So I knocked this function up for him Winking smile

function Get-RegistryValue([Switch]$Recurse=$false, [String]$ComputerName=(hostname), [String]$Hive="HKLM", [String]$key)
{
  $OutArray = @()
  Switch($Hive){
    "HKCR"  {$type = [Microsoft.Win32.RegistryHive]::ClassesRoot}
    "HKU"   {$type = [Microsoft.Win32.RegistryHive]::Users}
    "HKPD"  {$type = [Microsoft.Win32.RegistryHive]::PerformanceData}
    "HKDD"  {$type = [Microsoft.Win32.RegistryHive]::DynData}
    "HKCU"  {$type = [Microsoft.Win32.RegistryHive]::CurrentUser}
    "HKLM"  {$type = [Microsoft.Win32.RegistryHive]::LocalMachine}
  }#Case

  $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $ComputerName)
  $regKey = $regKey.OpenSubKey($key)
  If($regKey -eq $Null){Write-Host "Registry Key ["$Hive""$key"] Not Found" -ForeGroundColor Red;Return}
  Write-Host "`n"$regkey -ForeGroundColor Blue
  If ($Recurse -AND $regKey.SubKeyCount -gt 0){

    ForEach($sub in $regKey.GetSubKeyNames()){
      $SUBkey = $key + "" + $Sub
      Get-RegistryValue -ComputerName $ComputerName -Hive $Hive -Key $SUBKey -Recurse $Recurse
    }#ForEach
  }#If
  ForEach($Subx in $RegKey.GetValueNames()){
    $RegArray = "" | Select ComputerName, Key, Value, path
    $RegArray.ComputerName = $ComputerName
    $RegArray.Key          = $SubX
    $RegArray.Value        = $Regkey.GetValue($SubX)
    $RegArray.Path         = $RegKey.Name
    $OutArray             += $RegArray
  }#ForEach
Return $OutArray
}#End Function Get-RegistryValue

Essentially all you need to do is

Get-RegistryValue –ComputerName <Computername> -Key "SYSTEMCurrentControlSetservicesSNMPParametersTrapConfiguration" -Hive HKLM –Recurse

You change the -Hive switch to the particular registry hive (by default it will use HKLM), give it a computername (by default it will use the localhost) and a registry key path .. Done!

You can also recurse a registry if there are subkeys .. nice Open-mouthed smile

Let me know what you think