Powershell – Invoke-Command Remote UAC Workaround
I recently had to install a software agent on several remote servers with that had UAC (User Account Control) enabled. The issue was with the way Invoke-Command runs the commands, it uses the credentials of the person/account running the script to authenticate with the server then tries to use another account to run the command the permissions or lowers the privileges of the user so that certain commands cannot be run. I was able to get the software to install using the SYSTEM account by using a work around with the task scheduler. The following snippet creates a scheduled task to run as SYSTEM on the remote server, starts the task, and then deletes the task. In my case all servers follow a common naming convention, however it wouldn’t be difficult to adapt this snippet to other environments.
$siteCodes = @('PDX','NYC','LAX') ForEach ($x in $siteCodes) { # create PSSession on remote server $Session = New-PSSession -ComputerName "$x-fs.constoso.com" # run command on remote server $Job = Invoke-Command -ComputerName "$x-fs.contoso.com" -ErrorAction SilentlyContinue -ArgumentList $x -ScriptBlock { param($site) # get bogus time $currTime = Get-Date $currTime.AddMinutes(90) $currTime = Get-Date $currTime -Format %H:m # create scheduled task schtasks /create /tn "SoftInstall" /ru SYSTEM /tr "\\$site-fs.contoso.com\setup.exe /some /switches /go /here" /sc once /st $currTime # run the task schtasks /run /tn "SoftInstall" # sleep for 10 sec Start-Sleep -s 10 # delete the task schtasks /delete /f /tn "SoftInstall" } # close the PSSession Remove-PSSession -Session $Session }.
Exchange 2010 – Locating Disconnected Mailboxes
Here is a quick Powershell function to make finding disconnected mailboxes easier.
Save this as Get-DisconnectedMailbox.ps1:
function Get-DisconnectedMailbox { [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false)] [System.String] $Name = '*' ) $mailboxes = Get-MailboxServer $mailboxes | %{ $disconn = Get-Mailboxstatistics -Server $_.name | ?{ $_.DisconnectDate -ne $null } $disconn | ?{$_.displayname -like $Name} | Select DisplayName, @{n="StoreMailboxIdentity";e={$_.MailboxGuid}}, Database } }
Open the Powershell console, and dot source the function, assuming PS1 is stored in c:\scripts
cd c:\scripts . .\Get-DisconnectedMailbox.ps1 Get-DisconnectedMailbox mailserver1.contoso.com.
Exchange 2010 – Determine Mailbox Sizes With Powershell
Below is a quick snippet for retrieving mailboxes sizes for all mailboxes in a specific mailbox database:
Get-MailboxDatabase -Identity "EXAMPLE" | Get-MailboxStatistics | where {$_.ObjectClass –eq “Mailbox”} | Sort-Object TotalItemSize –Descending | ft @{label=”User”;expression={$_.DisplayName}},@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}},@{label=”Items”;expression={$_.ItemCount}} -auto.
Powershell – Get Network Adapter Connection Speed
One-Liner to get network adapter speed in Powershell.
Get-WmiObject -ComputerName computer.contoso.com -Class Win32_NetworkAdapter | Where-Object { $_.Speed -ne $null -and $_.MACAddress -ne $null } | Format-Table -Property NetConnectionID,@{Label='Speed(MB)'; Expression = {$_.Speed/1MB}}.
Powershell – Get Time On Remote Computer
Short but useful snippet to get the time on a remote computer using Powershell & WMI.
$rt = Get-WmiObject -Class Win32_OperatingSystem -ComputerName computer.consoto.com $rt.ConvertToDateTime($rt.LocalDateTime).
Exchange 2010 – Move All Mailboxes From OU To Specific Database
I needed to move all mailboxes for accounts in a specific OU to a specific Mailbox Database. Below are the powershell commands I used to accomplish this.
To create the necessary move requests:
$ou = "constoso.com/account purgatory" Get-Mailbox -OrganizationalUnit $ou | New-MoveRequest -TargetDatabase "Purgatory"
To clean up the move requests when complete:
Get-MoveRequest | Where-Object { $_.Identity -like "$ou*" -and $_.Status -eq "Completed" } | Remove-MoveRequest -Confirm:$false.
Scripting – Delete Files and Folders Older Than X Days
Removing files / folders older than X days. This post contains a batch file, and a Powershell script that will do this.
Batch File:
@echo off :: set folder path set dump_path=c:\shares\dump :: set min age of files and folders to delete set max_days=7 :: remove files from %dump_path% forfiles -p %dump_path% -m *.* -d -%max_days% -c "cmd /c del /q @path" :: remove sub directories from %dump_path% forfiles -p %dump_path% -d -%max_days% -c "cmd /c IF @isdir == TRUE rd /S /Q @path"
Powershell:
# set folder path $dump_path = "C:\shares\dump" # set min age of files $max_days = "-7" # get the current date $curr_date = Get-Date # determine how far back we go based on current date $del_date = $curr_date.AddDays($max_days) # delete the files Get-ChildItem $dump_path -Recurse | Where-Object { $_.LastWriteTime -lt $del_date } | Remove-Item.
Exchange 2007 – EventID 9554 – Unable to update Mailbox SD in the DS
How to fix EventID 9554 in Exchange 2007. One of the following recurring events may appear in the Application Log of the Event Viewer every 30 minutes:
Unable to update Mailbox SD in the DS. Mailbox Guid: 844fec0b-405a-4e74-9b7d-3fea8e1373ae. Error Code 0x80070005 Unable to update Mailbox SD in the DS. Mailbox Guid: 844fec0b-405a-4e74-9b7d-3fea8e1373ae. Error Code 0x80070005
First you need to determine what mailbox is having the issues. To do this we use the Exchange Management Shell:
Get-MailboxStatistics | Where-Object { $_.MailboxGuid -eq '844fec0b-405a-4e74-9b7d-3fea8e1373ae' } | ft DisplayName, MailboxGuid
Next we fix the permissions on the active directory object:
- Start the Active Directory Users and Computers snap-in.
- Right-click the user whose permissions you want to change, and then click Properties.
- Click the Security tab, click to select the Allow inheritable permissions from parent to propagate to this object check box, and then click OK.
Exchange 2010 – DAG Maintenance With Two Member DAGs
I ran into an issue when attempting to install Exchange 2010 SP2 on a two member dag. It turns out you can’t use the StartDAGServerMaintenance.ps1 and StopDAGServerMaintenance.ps1 scripts on a two node DAG because the 2nd part of StartDAGServerMaintenance fails to complete its tasks and cannot put the node into maintenance mode (although it does move the databases). Below is the procedure I used to manually put the DAG member into maintenance mode so I could install Exchange 2010 SP2. In the example MB-DAG2 is the member I wanted to put into maintenance mode, MB-DAG1 is the other node, and DAG.DOMAIN.COM is the DAG fqdn.
Verify that at least one other non-lagged copy of the replicated database(s) is healthy.
Get-MailboxDatabaseCopyStatus *
Move the databases to another node:
Move-ActiveMailboxDatabase -Server DAG-MB1 -Confirm:$FALSE
Move the cluster core resources to another node:
cluster dag.domain.com group "Cluster Group" /moveto:DAG-MB1
Pause the cluster node:
cluster dag.domain.com node DAG-MB1 /pause
Set the DatabaseCopyAutoActivationPolicy of the node to BLOCKED.
Set-MailboxServer -Identity DAG-MB1 -DatabaseCopyAutoActivationPolicy:BLOCKED
Suspend all individual database copies for activation.
Get-MailboxDatabaseCopyStatus *\DAG-MB1 | Suspend-MailboxDatabaseCopy -ActivationOnly:$TRUE
This is where you perform server maintenance (install Exchange 2010 SP2) on that the MB-DAG1 node. When the service pack install finished, I took the node out of maintenance:
Resume the node:
cluster dag.domain.com node DAG-MB1 /resume
Move the cluster resources back to the other node:
cluster dag.domain.com group "Cluster Group" /moveto:DAG-MB2
Resume the DB replication:
Get-MailboxDatabaseCopyStatus *\DAG-MB2 | Resume-MailboxDatabaseCopy
Done. Now repeat these steps for the other DAG member.
.Exchange 2010 – Import PST Into Mailbox with CAS Array
Unfortunately, using the New-MailboxImportRequest cmdlet with a CAS array doesn’t work. To workaround this we will create a Temp database, set a specific CAS server as the RpcClientAccessServer for that mailbox database, move the target mailbox to it, import the PST, and then move the mailbox back to the original database. These instructions assume you have both the Active Directory and Exchange 2010 management powershell roles/modules enabled.
When you try to use New-MailboxImportRequest with a CAS array you will receive the following error:
Couldn’t connect to target mailbox.
First we will configure the prerequisites, then we can get to work. In order for this to work, you need the PSTs on a file share, make sure you grant “Exchange Trusted Subsystem” full access to this share, otherwise you will run into errors.
Create an active directory group to grant import/export access to:
New-ADGroup -Name "ImpEx_Admins" -SamAccountName ImpExAdmins -GroupCategory Security -GroupScope Universal -DisplayName "ImpEx Admins" -Path "CN=Users,DC=Contoso,DC=Com" -Description "Members of this group are mailbox import export administrators"
Grant the created group the necessary permissions to import/export mailboxes as PSTs:
New-ManagementRoleAssignment -Name "Import Export Mailbox Admins" -SecurityGroup "ImpEx_Admins" -Role "Mailbox Import Export"
Now add yourself to that group and we can continue.
Create temporary mailbox database to move mailbox to:
New-MailboxDatabase -Name "SomeTmpDB" -EdbFilePath D:\SomePath\MailboxDatabase01.edb -LogFolderPath D:\SomePath\LogFolder
Set the RCPClientAccessServer value on the temp database to a specific CAS server:
Get-MailboxDatabase TempDB | Set-MailboxDatabase -RpcClientAccessServer cas1.domain.com
Move mailbox to MDB that has specific CAS array set as RCPClientAccessServer:
New-MoveRequest -Identity '[email protected]' -TargetDatabase SomeTmpDB
Clear the mailbox move request for the mailbox
Remove-MoveRequest -Identity '[email protected]'
Import the PST into the mailbox in a folder name “Recovery”:
New-MailboxImportRequest -Mailbox someUser -FilePath \\someserver\c$\pst\anotherUser.pst -TargetRootFolder Recovery
Remove the Mailbox Import Request
Remove-MailboxImportRequest -Identity someUser
Move the mailbox back to the original mailbox database:
New-MoveRequest -Identity '[email protected]' -TargetDatabase OriginalDB
Once the move is complete, remove the move request:
Remove-MoveRequest -Identity '[email protected]'.
subscribe via RSS