After my issue this week with attempting to decommission a Lync 2013 pool due to a lingering object, I decided to write a simple script that takes the pool name that you are attempting to remove, and runs though all possible objects and outputs any missed that are still attached to the pool.
Download OrphanedObjects.ps1
I have tested and confirmed that this works on Lync 2013 and S4B. It does NOT work on Lync 2010, but if I get enough interest in a 2010 version I could modify it to work.
Friday, August 14, 2015
Searching for Orphaned Objects
Recently when decommissioning a Lync 2013 pool, I ran into an issue where it said that by publishing the topology and removing the pool I would orphan existing users, endpoints, or devices:
Consult your Skype for Business Server documentation to learn how to move or disable objects still homed on the pool. To find those objects, execute the following cmdLets: Get-CsUser, Get-CsExUmContact, Get-CsCommonAreaPhone, Get-CsAnalogDevice, Get-CsRgsWorkflow, Get-CsDialInConferencingAccessNumber, Get-CsAudioTestServiceApplication, Get-CsTrustedApplicationEndpoint, Get-CsPersistentChatEndpoint.
Now I knew there were more objects that could trigger the orphaned objects failure, so I also ran Get-CsConferenceDirectory, Get-CsTrustedApplication, Get-CsTrustedApplicationComputer, Get-CsTrustedApplicationEndpoint, Get-CsTrustedApplicationPool. The only result I got was aCsAudioTestServiceApplication:
I attempted to remove this however there is no remove cmdlet, and there is no option to set it's registrar pool with Set-CsAudioTestServiceApplication.
I confirmed with one of my co-workers that it was not possible to remove this, however it should not be an object that prevents the removal of a pool. So what was causing the hold?
Solution:
I decided to go into the weeds and dumped all user objects from AD to a CSV via CDSVE ( csvde -f test.csv -r objectClass=user ), and then searched for all users who had the msRTCSIP-PrimaryHomeServer value that matched the Lync 2013 server. Low and behold there was a Lync Room System object that was still homed to the Lync 2013 pool. After moving this object to the new S4B pool, I was then able to publish the topology.
Consult your Skype for Business Server documentation to learn how to move or disable objects still homed on the pool. To find those objects, execute the following cmdLets: Get-CsUser, Get-CsExUmContact, Get-CsCommonAreaPhone, Get-CsAnalogDevice, Get-CsRgsWorkflow, Get-CsDialInConferencingAccessNumber, Get-CsAudioTestServiceApplication, Get-CsTrustedApplicationEndpoint, Get-CsPersistentChatEndpoint.
Now I knew there were more objects that could trigger the orphaned objects failure, so I also ran Get-CsConferenceDirectory, Get-CsTrustedApplication, Get-CsTrustedApplicationComputer, Get-CsTrustedApplicationEndpoint, Get-CsTrustedApplicationPool. The only result I got was aCsAudioTestServiceApplication:
I attempted to remove this however there is no remove cmdlet, and there is no option to set it's registrar pool with Set-CsAudioTestServiceApplication.
I confirmed with one of my co-workers that it was not possible to remove this, however it should not be an object that prevents the removal of a pool. So what was causing the hold?
Solution:
I decided to go into the weeds and dumped all user objects from AD to a CSV via CDSVE ( csvde -f test.csv -r objectClass=user ), and then searched for all users who had the msRTCSIP-PrimaryHomeServer value that matched the Lync 2013 server. Low and behold there was a Lync Room System object that was still homed to the Lync 2013 pool. After moving this object to the new S4B pool, I was then able to publish the topology.
Thursday, August 13, 2015
Lync 2013 to S4B CMS Migration Replication Issues
I recently moved the CMS from Lync 2013 to a new S4B pool for a
project I was working on. I followed the normal procedure and re-ran
bootstapper on all the nodes that make up the new pool hosting the CMS, as well
as the old Lync 2013 pool to remove the CMS role. I verified that the
S4B Master Replicator Agent and File Transfer Agent services were running
on all four of the new S4B nodes. I rebooted all four of the new S4B servers
individually and once complete I attempted to view the CMS replication status however
it reported nothing was updating. All entries show UpToDate False,
and all of them except the node I ran the Move-csManagmentServer cmdlet from
and the edge servers show laststatusreport from around the time I performed the
move:
I verified that I was able to download the Topology; I could see
that FE01 was the ActiveMaster of the CMS:
I ran a trace using ManagmentCore scenario and saw a couple errors
regarding the XDS-Replica folder:
This line stuck out particularly:
Query changes operation failed.
Exception [System.UnauthorizedAccessException: Access to the path '\\S4BFENJ01.spscom.com\xds-replica\xds-master\xds-master\working\replication\tmp\0c112834-9f3e-49bc-ba01-fb0e4227e56e'
is denied.
At this point I attempted to recreate the XDS-Replica folder by
following Ken’s blog ( http://ucken.blogspot.com/2012/04/resetting-lync-cms-replication.htm ) however this didn’t seem to solve it. At
this point I knew it had to be something to do with permissions/authentication. I checked and verified that all the servers in the new S4B pool were members of
the RTCUniversalConfigReplicator group.
Solution:
I finally enabled CAPI2 logs and saw that there was an expired certificate being passed. So I re-ran the deployment wizard, checked and sure enough the OAuth certificate had expired. Renewing the certificate and restarting each server propagated the OAuth certificate and replication began to work.
Solution:
I finally enabled CAPI2 logs and saw that there was an expired certificate being passed. So I re-ran the deployment wizard, checked and sure enough the OAuth certificate had expired. Renewing the certificate and restarting each server propagated the OAuth certificate and replication began to work.
Saturday, August 1, 2015
Exchange 2013 Cmdlets
I get asked often for various cmdlets on how to perform actions in Exchange PowerShell. So I have decided to post them on the blog. I will be updating this every time I find myself using a new one often so be sure to bookmark this page.
Export Mailbox folder sizes:
Get-Mailbox
-Identity User |
Get-MailboxFolderStatistics | Select
Identity,FolderPath,FolderSize,ItemsInFolder | Sort-Object ItemsInFolder | fl |
out-File C:\Temp\User-Mbox.txt
Export UPN of all users with an archive:
Get-Mailbox -Archive
| Select-Object UserPrincipalName | Export-Csv -Path
C:\Temp\AssignLicenseOptions.csv
Retrieve Message Tracking logs, sort by TotalBytes and
save to txt file:
Get-MessageTrackingLog
-EventId SEND -Start "9/1/2011 06:00:00" -End "9/1/2011
20:00:00" -resultsize unlimited | Sort-Object TotalBytes -Descending | FT
Sender, MessageSubject, TotalBytes > C:\test.txt
Retrieve send-as permissions on a mailbox that is not
the account tied to the mailbox:
Get-Mailbox
-Identity "ltemple" | Get-ADPermission | where { ($_.ExtendedRights
-like "*Send-As*") -and -not ($_.User -like "NT
AUTHORITY\SELF") } | select Identity, User, ExtendedRights, IsInherited |
FT -Wrap
Formatted List with Mailbox Size in Megabytes (MB) to
CSV File:
Get-Mailbox |
Get-MailboxStatistics | Select-Object
DisplayName,{$_.TotalItemSize.Value.ToMB()} | export-csv -path
C:\<FILENAME>.csv
Alternatively, you can specify the MBD also:
Get-MailboxDatabase
-Identity "MailboxDatabase" |
Get-Mailbox | Get-MailboxStatistics | Select-Object
DisplayName,{$_.TotalItemSize.Value.ToMB()} | export-csv -path
C:\Temp\MailboxSize.csv
Get Archive Size:
Get-Mailbox |
Get-MailboxStatistics -Archive | Select-Object
DisplayName,{$_.TotalItemSize.Value.ToMB()},Database | export-csv -path C:\Filename.csv
Formatted List with Mailbox Size in Megabytes (MB)
Output to Screen:
Get-Mailbox |
Get-MailboxStatistics | Format-Table
DisplayName,{$_.TotalItemSize.Value.ToMB()} -auto
Get whitespace in DB's:
2010/2013:
Get-MailboxDatabase
-Status | Select Servername, Name, AvailableNewMailboxSpace
2007:
Get-MailboxServer |
Get-MailboxDatabase | Select Server, StorageGroupName, Name,
@{Name="Size";expression={"{0:N2}" -f
((get-mailboxstatistics -database $_.Identity | Measure-Object -Property
TotalItemSize,TotalDeletedItemSize -Sum |Select-Object Sum |Measure-Object
-Property Sum -Sum).Sum.ToString() /1mb)}}
Get Mailbox Move Statistics:
Get-MoveRequest |
Get-MoveRequestStatistics | ft displayname,*stat*,perc*,totalmailboxsize
Only in Progress Moves:
Get-MoveRequest
–MoveStatus InProgress | Get-MoveRequestStatistics | ft
displayname,*stat*,perc*,totalmailboxsize
For a constant update:
while (1 -eq 1) {
Get-MoveRequest | Get-MoveRequestStatistics; Start-Sleep -Seconds 2;
Clear-Host; }
Empty Dumpster for User:
search-mailbox
-identity "MBauer" -searchdumpsterOnly -DeleteContent
Dump Message Tracking to GridView:
get-messagetrackinglog
-Start "7/14/2015 8:00:00 AM" -End "7/14/2015 4:30:00 PM"
-ResultSize Unlimited | select timestamp, ClientIp, ClientHostname, ServerIp,
ServerHostname, ConnectorId, Source, EventId, InternalMessageId, Sender, {$_.Recipients},
{$_.RecipientStatus},MessageSubject, SourceContext, MessageId, TotalBytes,
RecipientCount, RelatedRecipientAddress, Reference, ReturnPath, MessageInfo |
Out-GridView
Dump Message Tracking Results to CSV:
get-messagetrackinglog
-MessageSubject "Test Message to Verify
Tracking Details" -Start "1/26/2014 9:00:00 PM" -End
"1/26/2014 9:30:00 PM" | select timestamp, ClientIp, ClientHostname,
ServerIp, ServerHostname, SourceContext, ConnectorId, Source, EventId,
InternalMessageId, MessageId, {$_.Recipients}, {$_.RecipientStatus},
TotalBytes, RecipientCount, RelatedRecipientAddress, Reference, MessageSubject,
Sender, ReturnPath, MessageInfo | Export-Csv
"c:\Temp\Track-results.csv"
Get Message Tracking for whole domain:
get-messagetrackinglog
-Server "Exchange-server-name" -Start "7/1/2010 11:34:00
AM" -End "8/10/2010 9:44:00 AM" -resultsize unlimited |where
{$_.Sender -like "*@domain.org"}
Get Unified Messeging Extensions:
Get-UMMailbox |ft
name,extensions,UMDialPlan,UMMailboxPolicy
Get List of SMTP Addresses and export to CSV:
Get-Mailbox
-ResultSize Unlimited |Select-Object DisplayName,PrimarySmtpAddress,
@{Name=“EmailAddresses”;Expression={$_.EmailAddresses |Where-Object
{$_.PrefixString -ceq “smtp”} | ForEach-Object {$_.SmtpAddress}}} | Export-CSV
"C:\Temp\List-SMTP-Address.csv"
Get List ActiveSync Devices:
2013:
$Mailboxes =
Get-Mailbox
$Mailboxes | ForEach
{Get-MobileDeviceStatistics -Mailbox:$_.Identity} | Select
Identity,DeviceType,DeviceUserAgent,DeviceID,LastSyncAttemptTime,LastSuccessSync
| Export-CSV -Path C:\temp\ActiveSyncDevices.csv
2010:
Get-ActiveSyncDevice
-ResultSize Unlimited | Select-Object UserDisplayName, Name, DeviceUserAgent |
Export-Csv C:\Temp\ActiveSyncDevices.csv
Exch2007:
Get-Mailbox |
ForEach {Get-ActiveSyncDeviceStatistics -Mailbox:$_.Identity} | ft DisplayName,
Devicetype, DeviceUserAgent, LastSuccessSync
Get ActiveSync information for specific user:
Get-ActiveSyncDeviceStatistics
-Mailbox blye | ft DeviceType, DeviceUserAgent, LastSuccessSync
Grant Rights to a user for a public folder and all
sub-folders:
Get-PublicFolder
–Identity “\IT” –Recurse | Add-PublicFolderClientPermission –User pponzeka
–AccessRights PublishingEditor
See if anyone has sent or received email from a
specific domain:
Get-MessageTrackingLog
-resultsize unlimited |where-object {$_.Recipients -like “*@renovatingla.com,*@bhkruper.com,*@usaveremodeling.com,*@rmogency.com”
-AND $_.EventId -eq “Send”} |ft -auto >>C:\Temp\MailDomainSearch.txt
Batch move mailbox archives from text file:
$Mailboxes =
Get-Content .\TextFile.txt
For ($Start = 0;
$Start -lt $Mailboxes.length; $Start++) {New-MoveRequest –Identity
`$Mailboxes[$Start] -ArchiveOnly -ArchiveTargetDatabase 'MailboxDatabaseName'}
Remove messages from queue with specific subject:
Remove-Message
-Filter {Subject -eq "ENTERSUBJECT HERE"} -WithNDR $false
Export User's Contacts Folder:
New-MailboxExportRequest
-Mailbox user1 -IncludeFolders “#Contacts#” -ExcludeDumpster -filepath \\server\share\user1.pst
Dump Mail Relay to txt file:
(Get-ReceiveConnector
"exchange2007\allowedrelay").RemoteIPRanges | select
Lowerbound,Upperbound,RangeFormat | sort-object Lowerbound| export-csv
c:\rc.txt –NoTypeInformation
Move messages with a specific subject:
Get-Mailbox
-Identity “MBauer” | Search-Mailbox -SearchQuery subject:”Alert: Host Parent
Partition CPU Utilization high Resolution state: ”,from:”Honeypot@taskrepository.com” -TargetMailbox “MBauer”
-TargetFolder “SCOM\CPU”
Update OAB:
Update-OfflineAddressBook
“default offline address book”
Update DB Catalog Only (Re-Seed Content Index State_):
Update-MailboxDatabaseCopy
"Mailboxes M-O\MailboxServer" -CatalogOnly
Set Domain on OWA/ECP Login Page:
Set-OwaVirtualDirectory
ServerName\"owa (Default Web Site)" -LogonFormat Username
-DefaultDomain TaskRepository
DL Auditing:
Get-DistributionGroup | Select-Object PrimarySMTPAddress
| Sort-ObjectPrimarySMTPAddress
| Export-CSV DL-ALL.csv -notype
Get-MessageTrackingLog -Server EXCH1 -EventId Expand -ResultSize Unlimited
|Sort-Object RelatedRecipientAddress
| Group-Object RelatedRecipientAddress |Sort-Object Name
| Select-Object @{label="PrimarySmtpAddress";expression={$_.Name}},
Count | Export-CSV DL-Active.csv -notype
$file1 = Import-CSV -Path "DL-ALL.csv"
$file2 = Import-CSV -Path "DL-Active.csv"
Compare-Object $file1 $file2 -Property PrimarySmtpAddress -SyncWindow 500
|Sort-Object PrimarySmtpAddress
| Select-Object -Property PrimarySmtpAddress
|Export-Csv DL-Inactive.csv -NoType
Tracking Log Explorer:
Get-MessageTrackingLog
-ResultSize Unlimited -Start "June 18 2015” | Out-GridView
Disable Calendar Repair:
Set-Mailbox
-Identity username -Calendar
Repair Disabled $True
Get all unhealthy Exchange resources:
$test =
get-healthreport -server CATDALEXCH01 | where {$_.alertvalue -ne “healthy”}
foreach ($line in
$test) {$line.entries | where {$_.alertvalue -ne “healthy”} | ft -auto}
Remove Automatic Mapping of Mailbox:
Remove-MailboxPermission
-Identity celine -User ashley -AccessRights FullAccess
Add-MailboxPermission
-Identity celine -User ashley -AccessRights FullAccess -AutoMapping:$false
Subscribe to:
Posts (Atom)