Had a unique situation where we want to export all Mailbox archives from an older exchange server that has very limited resources.
Issuing a bulk mailbox export to PST was causing serious performance issues on the exchange server.
For these reasons I needed to only export mailbox archives one at a time.
The following script, connects to a single exchange server, checks for archives on all mailboxes, and starts to export them one at a time. This script will monitor the export progress till it reaches 100%, it will then clear the completed request, and move onto the next archive.
Make sure that you have permissions set as required by MS for your mailboxexport requests to work.
Also makes sure at the least to edit the "$ArchivePath" variable.
---------------------------------------Begin Script----------------------------------------------------------
#Load Exchange powershell commandlets
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
Connect-ExchangeServer -auto
#Define PST UNC share for all exports
$ArchivePath="\\" #Specify a local or UNC path here.
#Process Archives
$Archives=get-mailbox -Archive | sort name
ForEach ($Archive in $Archives)
{
$ArchiveOut=$ArchivePath + "\" + $Archive + "-Archive" + ".pst"
cls
echo " "
echo " "
write-host "I found an Archive called $Archive" -foregroundcolor green
echo " "
write-host "Issuing PST Export command for $Archive" -foregroundcolor Cyan
echo " "
New-MailboxExportRequest -mailbox $Archive -Isarchive -FilePath $ArchiveOut
echo " "
$Loop="1"
While ($Loop -eq "1")
{
$ExportInfo=get-mailboxexportrequest | get-mailboxexportrequeststatistics
$ExportProgress=$ExportInfo.PercentComplete
$ExportProgress2=$ExportInfo.Status
IF ($ExportProgress -eq "100")
{
echo " "
write-host "The PST export for $Archive has completed" -foregroundcolor Green
echo " "
timeout /t 25 /nobreak
get-mailboxexportrequest | remove-mailboxexportrequest -confirm:$false
echo " "
write-host "Completed processing this Archive, moving onto next..."
echo " "
$Loop="2"
}
ELSE
{
echo " "
write-host "working on exporting archive..." -foregroundcolor Yellow
write-host $Archive
write-host $ExportProgress2
write-host $ExportProgress
echo " "
timeout /t 15 /nobreak
}
}
}
cls
echo " "
echo " "
write-host "All processing of mailbox archives has completed" -foregroundcolor Green
echo " "
echo " "
read-host "press any key to continue:"
---------------------------------------------End Script---------------------------------------------------------
Windows scripts / powershell / kix / vbs / wsh
Thursday, March 19, 2015
Tuesday, March 10, 2015
Powershell Function - Check process
I wrote a quick powershell function for tracking if a process is running. I've found this useful for cases where I want my script to wait for a process to complete before continuing, or for providing 'visual' feedback that work is occurring.
In the sample below, the process I'm tracking with the function is "robocopy". (as declared with $Process=)
----------------------------------------------Begin Script-------------------------------------------------------------
$Process="Robocopy"
Function Check-Process-Alive
{
<#
.Synopsis
Checks if a process is running, and updates the screen with a new "line" for each second the process continues to run.
.Description
This particular function is helpful to see when a long running process stops.
.Example
PS C:\> Check-Process-Alive %processname%
#>
Param ($X)
While (Get-Process $X -ErrorAction SilentlyContinue)
{
Write-Host "Copying files..." -foregroundcolor Green
Start-Sleep -s 10
}
} # End function
Check-Process-Alive $Process
-------------------------------------------------End Script-----------------------------------------------------------
This code essentially allows you to call off a process in your script (an install or a file copy for instance) and your script will then 'pause' in essence while waiting for the process you launched to complete.
In the sample below, the process I'm tracking with the function is "robocopy". (as declared with $Process=)
----------------------------------------------Begin Script-------------------------------------------------------------
$Process="Robocopy"
Function Check-Process-Alive
{
<#
.Synopsis
Checks if a process is running, and updates the screen with a new "line" for each second the process continues to run.
.Description
This particular function is helpful to see when a long running process stops.
.Example
PS C:\> Check-Process-Alive %processname%
#>
Param ($X)
While (Get-Process $X -ErrorAction SilentlyContinue)
{
Write-Host "Copying files..." -foregroundcolor Green
Start-Sleep -s 10
}
} # End function
Check-Process-Alive $Process
-------------------------------------------------End Script-----------------------------------------------------------
This code essentially allows you to call off a process in your script (an install or a file copy for instance) and your script will then 'pause' in essence while waiting for the process you launched to complete.
Powershell - search a folder tree and remove select objects.
Had an interesting issue the other day. We're migrating user data from a different domain, and all the user folders which were copied, showed up in windows explorer as "documents" instead of their real names.
This was an issue with the desktop.ini file under each of the folders, which was causing windows explorer to display the folders with a different name. The fix was a simple "delete" of the desktop.ini from under each user directory . . however getting powershell to help me out with this took me a little bit of tinkering.
Desktop.ini by default is a hidden system file. Powershell, has known bugs with it's "remove-item" command, and the common work around is "get-childitem". Most references I could find for having powershell recursively search a directory structure didn't find the files I wanted to delete, so I built the following:
----------------------------Begin Script----------------------------------------------------------------------------
$path="c:\RootFolderToBeSearched"
$folders=Get-ChildItem -path $path -force | Where-Object{$_.PsIsContainer} | ForEach-Object{$_.FullName}
foreach ($folder in $folders)
{
$BadItem=Get-ChildItem $folder -Filter desktop.ini -Force
If ($BadItem -ne $null)
{
$bad=$folder + "\" + $BadItem
remove-item $bad -force
}
ELSE
{
write-host "$folder is clean..." -foregroundcolor Green
}
}
This was an issue with the desktop.ini file under each of the folders, which was causing windows explorer to display the folders with a different name. The fix was a simple "delete" of the desktop.ini from under each user directory . . however getting powershell to help me out with this took me a little bit of tinkering.
Desktop.ini by default is a hidden system file. Powershell, has known bugs with it's "remove-item" command, and the common work around is "get-childitem". Most references I could find for having powershell recursively search a directory structure didn't find the files I wanted to delete, so I built the following:
----------------------------Begin Script----------------------------------------------------------------------------
$path="c:\RootFolderToBeSearched"
$folders=Get-ChildItem -path $path -force | Where-Object{$_.PsIsContainer} | ForEach-Object{$_.FullName}
foreach ($folder in $folders)
{
$BadItem=Get-ChildItem $folder -Filter desktop.ini -Force
If ($BadItem -ne $null)
{
$bad=$folder + "\" + $BadItem
remove-item $bad -force
}
ELSE
{
write-host "$folder is clean..." -foregroundcolor Green
}
}
-----------------------------End Script-----------------------------------------------------------------
In my case, i was looking specifically for the file desktop.ini, to search and remove other files, simply replace the file name.
This script is specifically only looking 2 folders deep into a folder tree, adding a "-recurse" to either of the "get-childitem" lines, will return content from all subfolders. If you wish to play with this particular option, you'll want to edit the "remove" lines, as well since they won't work based on paths returned from 'recursive' searches of the folders.
Subscribe to:
Posts (Atom)