Selecting specific rows from a CSV file to perform Powershell functions/commands against

Scenario: You have a large CSV file that you need to import and perform specific PowerShell commands against. You need the results in a hurry and you want to split up the CSV so you can run multiple PowerShell sessions at once to pull the results in parallel. Instead of creating separate CSV files to import for each PowerShell session, you can tell PowerShell which rows of the import you want to target.

Code Example:   In each PowerShell you can import the CSV file. When calling the variable for the loop you can specify the rows you want to target.  In this example we are going to set customattribute1 to the string “MigrateME” for the first 1000 (well 1001) entries in the csv file in one PowerShell session.  In a second PowerShell session I would import the code but change [0..1000] to [1001..2000],  and repeat the increment for each additional PowerShell session.

$users = Import-csv C:TempAll_Mailboxes.csv

$users[0..1000] | Select -expandproperty alias | %{ set-mailbox $_ -customattribute1 “MigrateMe”}


Check MountPoints for Database

Scenario:  You use mountpoints in your Exchange organization and you want to check for specific disk information for your mountpoints by database name.   Note: The label of the mountpoint reflects the database name.



#Enter the DB Variable
$Db = "DB01"
$Servers = Get-mailboxdatabasecopystatus $DB | Select -ExpandProperty MailboxServer
$1 = @()
$Servers | %{
    "Checking on $_ for $Db"
    $1+= Invoke-Command -Computer $_ -argumentlist $db -ScriptBlock {Get-WmiObject win32_volume | Where label -like $args[0] | Select Name, Label, FreeSpace, FileSystem, SerialNumber}


Replace A Mailbox’s Explicit Full Access Permission With A Mail Enabled Security Group To Allow Non-Admins To Manage Access.

Scenario:  Currently you have mailboxes that have explicit full access to a shared mailbox. Instead of giving full access permission at the root mailbox level, you want an automated way to define the full access permission to a mail enabled security group. You would like the distribution group populated with those mailboxes who had the explicit full access permission at the root mailbox level and then to remove those users explicit permission at the root mailbox level.  What you will be left with is a populated mail enabled security group with full permissions to a shared mailbox.

One of the biggest benefits for this is that you can assign a user as a  manager/owner of the distribution group who does not need Exchange permission.  They can then modify the membership of the group, thus giving or taking away full permission to other users for the shared mailbox without a call to the help desk.

Solution:  The script below will create a mail enabled security group which will be prefixed with ‘grp-‘, add the membership of the group for those users explicitly defined with full access to the shared mailbox and send-as permissions, add the group as having full control to the shared mailbox, and then remove the users explicit full access permission from the shared mailbox.

All you need is to either query, or import from a csv file, a list of shared mailboxes. If you use a csv file, make sure the column header is labeled Name.

#This script replaces a users explicit full access permission to a mailbox with a Mail Enabled Security Group that will have full access permission.

#This script will automatically gather those explicit users with full access permissions and put them into the mail enabled security group.

#This script give also make a specific user managedby permissions for the group.

#Import service accounts from CSV
$SvcMbx = Import-csv C:tempsvcmbx.csv

#Loop through each Service Mailbox
$SvcMbx | %{

#Define Variables
$N = $_.Name
$g = "GRP-"+$N
Write-Host "Now starting this service mailbox:$N"

#Gather FullMailbox permission with Explicit Access
$explicitmembers = (Get-MailboxPermission $N | Where {($_.IsInherited -eq $false) -and ($_.User -notlike '*Authority*') -and ($_.AccessRights -like "FullAccess")}).user

#Create the Mail Enabled Security Group and add the manager(s) of the group. Then lock the group down so it cannot accept messages except from the manager.
Write-Host "Creating the AD Universal Security Group"
New-ADGroup -name $g -GroupScope Universal -Path "OU=TestGroups,DC=domain,DC=com" -DisplayName $g 
Write-Host "Waiting for Replication"
Sleep 30
Write-Host "Provision the AD group as a Mail enabled Security Group"
Enable-DistributionGroup $g 
Write-Host "Waiting for Replication"
Sleep 30
Write-Host "Configuring the Mail Enabled Security Group:$g"
Set-distributionGroup $g -managedby "jdoe1" -bypasssecuritygroupmanagercheck -acceptmessagesonlyfrom "jdoe1" 

#Populate the explicit mailboxes that have permission to the service mailbox to the new mail enabled distribution group

Write-Host "Populating the Mail Enabled Security Group: Group:$g"
$explicitmembers | %{
Add-DistributionGroupMember $g -member $_.RawIdentity -bypasssecuritygroupmanagercheck 

#Add the mail enabled security group to the service mailbox with full permission and automapping set to false
Write-Host "Adding $g with Full Permission and Send As permission to $n" 
Add-mailboxpermission $n -user $g -accessrights fullaccess -automapping $false 
Add-ADPermission $n -user $g -extendedRights 'Send-As'

#Remove the users explicit access to the service mailbox
Write-host "Removing the users Explicit access to $n"
$explicitmembers | %{
Remove-mailboxPermission $n -user $_.RawIdentity -accessrights FullAccess -confirm:$false 



Exchange Script to collect the Alias and the LastLogonTime for a list of users.

Scenario:  You have a list of mailboxes in a csv file that you need to check the lastlogontime property for each mailbox.


#Import CSV
$1 = Import-csv C:tempusers.csv

#Create the Variable
$final = @()

#Loop through your users.
$1 | %{
$alias = $
$2 = Get-mailboxStatistics $ | Select DisplayName, LastLogonTime
$disp = $2.DisplayName
$LastLogon = $2.LastLogonTime

#Build the Array
 $ServerObj = New-Object PSObject
 $ServerObj | Add-Member NoteProperty -Name "Alias" -Value $alias
 $ServerObj | Add-Member NoteProperty -Name "DisplayName" -Value $disp
 $ServerObj | Add-Member NoteProperty -Name "LastLogonTime" -Value $lastlogon
     $Final += $ServerObj    

$final | Export-csv C:tempresults.csv


Exchange PowerShell to check to see if a list of mailboxes exist.

Scenario:  You have a list of mailboxes that you want to check to see if a mailbox exists for each user.  You want to output it to a table with a true or false.

Resolution: In my users.csv that I import, the column that I reference in this script has a column name labeled ‘name’. Note: If a mailbox doesn’t exist, it may display with “The operation couldn’t be performed because object couldn’t be found” in the Powershell window.  The $Final variable will have a clean list with true or false for each mailbox.

#Create the Variable
$final = @()

#Import the CSV file with a column labeled 'name'.
$1 = Import-CSV C:tempusers.csv
#Loop it for each entry
$1 | %{
$n = $
$r = [bool](get-mailbox "$n")

#Build the Array
 $ServerObj = New-Object PSObject
 $ServerObj | Add-Member NoteProperty -Name "User" -Value $n
 $ServerObj | Add-Member NoteProperty -Name "Exists" -Value $r
     $Final += $ServerObj    

#Display the Results

#Export the CSV to a file
$Final | Export-csv C:tempResults_Users.csv

Use PowerShell to determine lastbootup time of a server or multiple servers

scenarios:  You want to quickly determine the bootup time for your Exchange Servers via Powershell.

Resolution: Run the following:

#For a Single Server:
Get-WmiObject win32_operatingsystem -computername ExSvr1 | select csname, @{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}

#For Multiple Servers:
$1 = Get-ExchangeServer ExSvr*
$1 | %{Get-WmiObject win32_operatingsystem -computername $ | select csname, @{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}}

Use PowerShell to search through multiple log files for specific text and export the results

Scenario:  You have multiple log/txt files you need to search through for specific text.  You would like to export/dump the text into another file.

Solution:  Run the following PowerShell Script.  Note the pattern contains the word you are looking for.  Unlike the “FIND” function in the command prompt, the PowerShell search does not require an exact case sensitive match.

#Look for any lines that has a text Pattern of "Fail" on it.
$1 = Get-ChildItem c:Temp*.log | Select-String -Pattern "Fail"

#For each line, export it to a csv.
$1 | Select line | Export-csv C:temptestline.csv

Disconnect RDP sessions via PowerShell

Scenario:  You are about to start maintenance on your servers and you want to remove any existing RDP session whether active of disconnected.  You want a quick way of doing this on all of your Exchange servers.

Solution:  Download the PSTerminalServices module from:

Once download and installed, copy the PSTerminalServices folder from the install path into C:windowssystem32WindowsPowerShellv1.0.  Then run the following script in Exchange Powershell:

#Imports Terminal Services module
import-module psTerminalServices 

#Collect each Exchange Server in a variable
$Servers = Get-exchangeserver Ex2013*

#Now loop it to remove any existing TS Session.
$servers | %{
$Sessions = get-tssession -computername $ | where {($_.useraccount -like "domainname*")}
$sessions | %{Stop-TSSession $_.sessionid -force}



Copy and then Rename files via PowerShell

Scenario:  You want to collect logs from various servers and place the copied logs into a single directory.  Due to the log names being the same on each server, we want avoid overwriting existing logs. We also want to know the server from where each log was copied from.

Solution:  The following will copy the IMAP logs from 4 servers into 1 local directory. Each file when copied to the directory will be renamed by prefixing the file with the server name.  It will also add the counter to the end of the file.

$Servers = "ExSvr1","ExSvr2","ExSvr3","ExSvr4"
$servers | %{$File = Get-ChildItem -Path "\$_c$Program FilesMicrosoftExchange ServerV15LoggingIMAP4" -Recurse;$i=1;Foreach ($f in $File) {Copy-Item $f.FullName ("C:TempIMAPPOP$_" + $f.BaseName + $i +".log");$i++}}