Installing updates manually once approved via Configuration Manager and checking the install status for each server remotely

Scenario:  You use Microsoft System Center 2012 Configuration Manager to receive updates for Windows.  Once your updates are approved for installation, you can use the following script to perform a manual install. Once the manual install is kicked off from a remote machine, you can use additional PowerShell commands to determine the statuses for each update.

Here is a copy of the script we are using that is located on each one of our servers.  Reference to the script found here.

InstallUpdates.PS1

$MissingUpdates = Get-WmiObject -Class CCM_SoftwareUpdate -Filter ComplianceState=0 -Namespace rootCCMClientSDK 

$MissingUpdatesReformatted = @($MissingUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}}) 

$InstallReturn = Invoke-WmiMethod -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace rootccmclientsdk 

$objCurrentPSProcess = [System.Diagnostics.Process]::GetCurrentProcess();

Stop-Process -Id $objCurrentPSProcess.ID;

 

To kick this script off remotely on your servers, you can use a similar PowerShell command such as:

Invoke-Command { powershell.exe -executionpolicy unrestricted C:updatesInstallUpdates.ps1} -ComputerName Win2012Svr1

OR, to run against multiple servers at once… Lets Loop It!

$Servers = Get-ExchangeServer Win2012Svr*

$Servers | %{Invoke-Command { powershell.exe -executionpolicy unrestricted C:updatesInstallUpdates.ps1} -ComputerName $_}

Instead of using Software Center to check the status of your updates via an RDP session to multiple servers,  lets use PowerShell again to invoke a command that will return the EvaluationState for each update:

Invoke-Command -computername Win2012Svr1 -scriptblock {Get-WmiObject -Class CCM_SoftwareUpdate -Namespace rootCCMC
lientSDK | Group EvaluationState}

OR against multiple servers, Lets loop it again!

$Servers = Get-ExchangeServer Win2012Svr*

$Servers  | %{Invoke-Command -computername $_ -scriptblock {Get-WmiObject -Class CCM_SoftwareUpdate -Namespace rootCCMClientSDK | Group EvaluationState}}

Below is what we determined each status represents.  Obviously there are some numerical codes missing, but these are the normal status codes we occasionally see:

0 = Not Started
5 = Downloading
6 = Waiting to Install
7 = Installing
8 = Requires Restart
13 = Failed

To restart the computers remotely, you can issue the following PowerShell Commands:

Restart-Computer Win2012Svr1 -force

or multiple servers:

$Servers = Get-ExchangeServer Win2012Svr*

$Servers  | Restart-computer -force

Happy updating!

 

 

 

 

 

 

Compare 2 powershell variable arrays and show values that do not match.

Scenario:  When performing a migration, we noticed a discrepancy in the  count of users that are in a distribution group compared to the count of users that have move requests (the move requests  were originally generated from that distribution group).  We have to determine which mailboxes are missing.

Resolution: Here is a quick way of comparing those 2 lists:

1. Pull the Distribution Group Members into a Variable:

$1 = Get-DistributionGroupMember Migration_710 | Select Alias

2. Pull the Move Requests that were batch into a second Variable:

$2 = Get-MoveRequest -batchname Migration_710 | Select Alias

3. Export both of those Aliases into a CSV file:

$1 | export-csv C:1.csv

$2 | export-csv C:2.csv

4. Import those csv back into new variables :

$file1 = Import-csv C:1.csv

$file2 = Import-csv C:2.csv

5. Compare the lists by running the following command.  The output should be the missing objects.

compare-object $file1 $file2

Search a mailbox for a specific email without using OWA or Outlook.

Scenario:  A user is missing a message in their mailbox claiming it ‘disappeared’.  The possibilities are:

  1.  The message was accidentally deleted.
  2. The message was accidentally moved into another folder.
  3.  The message exists in the mailbox folder, except the items in that folder are not sorted correctly. Note:Sorting by the Received date will make all emails in that folder in chronological order

Solutions:

You could request permission from the user who owns the mailbox to allow you to have full access permission and search their mailbox via OWA — but this can be a little time consuming.  Instead  perform a ‘search-mailbox’ against the mailbox to locate the missing message:

Get a count of all messages that match the subject line:

Search-Mailbox jdoe1 -SearchQuery Subject:”Attention: Please Read this Email” -EstimateResultOnly

Create a copy of the messages that match the subject line:

Search-Mailbox jdoe1 -SearchQuery Subject:”Attention: Please Read this Email” -targetmailbox ExAdmin1  -searchdumpster

OR for a search with additional properties to be queried:

Search-Mailbox jdoe1 -SearchQuery {Subject:”Attention: Please Read this Email” AND from:”President@Domain.com”  AND Sent:”7/10/2015″} -Targetmailbox ExAdmin1 -searchDumpster

Note: it may request you to name a target folder so it can create that folder in the ExAdmin1 mailbox.  The search results will be then copied to that target folder in the folder hierarchy for where the messages are stored. For example, if there are messages in the inbox and deleted items of the mailbox being searched against, you will have the search results copied to the inbox and deleted items folder under the targetfolder that was created.

Message Tracking to find the first hop into Exchange 2013

Scenario: You have added new Exchange 2013 servers to your existing Exchange 2013 environment and you just configured your perimeter devices to route SMTP email to the new servers in addition to the old servers.  You want to gather a log of emails to review to make sure no issues are occurring, but you first need to trace down which emails are coming into the new Exchange 2013 servers so you can trace those emails down until they are delivered into the mailbox.

Determine the IP address or the DNS host name of your perimeter devices and run the command below.  We will use the IP 10.10.1.2 as the perimeter system delivering email into the new Exchange 2013 servers.

PowerShell:

Get-transportserver NewServerName | Get-messagetrackinglog -start “7/7/2015 9:00am” -eventID Receive | Where EventData -like “*10.10.1.2*”

Note: The event data will display the term “firstforesthop” and the proxied connection info (Info of the Perimeter Devices). The term ‘FirstForestHop’  wasn’t a good way for us to rely on a query as we have had a mix of Exchange 2010 and Exchange 2013.  When it entered into Exchange 2013, it would have ‘FirstForestHop’ listed in the event data even if it wasn’t really the first forest hop as it came in from Exchange 2010.  But it did have the Perimeter device info in which did provide successful queries.

 

Check the Total Physical Memory via Powershell

Scenario:  You add a bunch of memory to multiple servers and you want to check the amount on each server to verify it.

Powershell:

Check one Server in GB:   [math]::Round((Get-WmiObject -Class Win32_ComputerSystem  -computer ServerName).TotalPhysicalMemory/1GB)

Check one server in MB: [math]::Round((Get-WmiObject -Class Win32_ComputerSystem  -computer ServerName).TotalPhysicalMemory/1MB)

Check Multiple Exchange Servers:

$server = Get-exchangeservers

$server | %{ Write-Host $_; [math]::Round((Get-WmiObject -Class Win32_ComputerSystem  -computer $_).TotalPhysicalMemory/1GB)}

Cannot Remove a Exchange 2013 Database

Scenario: When you are trying to remove an Exchange Database,  you receive the following error below.

This mailbox database contains one or more mailboxes, mailbox plans, archive mailboxes, public folder mailboxes or
arbitration mailboxes. To get a list of all mailboxes in this database, run the command Get-Mailbox -Database
<Database ID>. To get a list of all mailbox plans in this database, run the command Get-MailboxPlan. To get a list of
archive mailboxes in this database, run the command Get-Mailbox -Database <Database ID> -Archive. To get a list of all
public folder mailboxes in this database, run the command Get-Mailbox -Database <Database ID> -PublicFolder. To get a
list of all arbitration mailboxes in this database, run the command Get-Mailbox -Database <Database ID> -Arbitration.
To disable a non-arbitration mailbox so that you can delete the mailbox database, run the command Disable-Mailbox
<Mailbox ID>. To disable an archive mailbox so you can delete the mailbox database, run the command Disable-Mailbox
<Mailbox ID> -Archive. To disable a public folder mailbox so that you can delete the mailbox database, run the command
Disable-Mailbox <Mailbox ID> -PublicFolder. Arbitration mailboxes should be moved to another server; to do this, run
the command New-MoveRequest <parameters>. If this is the last server in the organization, run the command
Disable-Mailbox <Mailbox ID> -Arbitration -DisableLastArbitrationMailboxAllowed to disable the arbitration mailbox.
Mailbox plans should be moved to another server; to do this, run the command Set-MailboxPlan <MailboxPlan ID>
-Database <Database ID>.

You have also verified that there are no mailbox/mailbox types on the database you wish to remove by running the following commands:

get-mailbox -database DB01
get-mailbox -archive -database DB01 -DomainController <root dc>
get-mailbox -PublicFolder -database DB01
get-mailbox -Arbitration -database DB01

Resolution:  Although an archive mailbox did not reside on the database we are trying to remove, we found that the database was still referenced in an archive mailbox that resided on a different database.  The archive mailbox was referencing the database via the msExchArchiveDatabaseLink property in ADSIEdit.

Once we discovered the archive mailbox, we moved it to another database, thus refreshing the properties in ADSI Edit and removing the database we wished to remove.

To determine which mailbox may be holding you up from removing an Exchange Database, follow these steps:

1. Remove the database in verbose:   remove-mailboxdatabase DB01 -verbose

2. Before it shows the error message, pay attention to the Verbose logging as it references the mailbox which is preventing the database from being removed.
VERBOSE: [18:03:27.819 GMT] Remove-MailboxDatabase : Runspace context: Executing user:
domain.com/users/exadmin, Executing user organization: , Current organization: , RBAC-enabled:
Enabled.
VERBOSE: [18:03:27.851 GMT] Remove-MailboxDatabase : Active Directory session settings for ‘Remove-MailboxDatabase’
are: View Entire Forest: ‘False’, Default Scope: ‘domain.com’, Configuration Domain Controller:
‘DC1.domain.com’, Preferred Global Catalog: ‘DC1.domain.com’, Preferred Domain Controllers: ‘{
DC1.domain.com }’
VERBOSE: [18:03:27.866 GMT] Remove-MailboxDatabase : Beginning processing Remove-MailboxDatabase
VERBOSE: [18:03:27.866 GMT] Remove-MailboxDatabase : Instantiating handler with index 0 for cmdlet extension agent
“Admin Audit Log Agent”.
VERBOSE: [18:03:27.866 GMT] Remove-MailboxDatabase : Current ScopeSet is: { Recipient Read Scope: {{, }}, Recipient
Write Scopes: {{, }}, Configuration Read Scope: {{, }}, Configuration Write Scope(s): {{, }, }, Exclusive Recipient
Scope(s): {}, Exclusive Configuration Scope(s): {} }
VERBOSE: [18:03:27.866 GMT] Remove-MailboxDatabase : Searching objects “db01” of type “MailboxDatabase” under the
root “$null”.
VERBOSE: [18:03:27.882 GMT] Remove-MailboxDatabase : Previous operation run on domain controller
‘DC1.domain.com’.
VERBOSE: [18:03:27.960 GMT] Remove-MailboxDatabase : Verifying that there is no associated mailbox user or move request
 on the mailbox database “db01”.
VERBOSE: [18:03:28.023 GMT] Remove-MailboxDatabase : Mailbox with DistinguishedName
“CN=jdoe1,CN=Users,DC=domain,DC=com” is still present in this database.
VERBOSE: [18:03:28.038 GMT] Remove-MailboxDatabase : Admin Audit Log: Entered Handler:OnComplete.

 

Add a IP Address to the RemoteIPRanges of an existing Receive Connector

Scenario:  Your Exchange 2013 Servers Receive Connector already has multiple values assigned to it.  Because its a multi-valued field,  you cannot easily add a single IP address to it without overwriting the contents of the field using a command similar to: set-receiveconnector -remoteipranges 10.10.0.2

Solution: In order to add a IP address to an existing set of RemoteIPRanges for a receiveconnector, run the following:

$RC = Get-ReceiveConnector "Ex2013-1Default FrontEnd Ex2013-1"

$RC.RemoteIPRanges += "10.10.0.2"

Set-ReceiveConnector "Ex2013-1Default FrontEnd Ex2013-1" -RemoteIPRanges $RC.RemoteIPRanges

 

Determine the IP Address and check to see if a PTR record exists for each Exchange Server

Scenario:  You want to determine the IP Address and PTR record for each Exchange Server in your environment.   Below is the script I used.  This will query for DNS and put the results into a table called $final.

Script:

$servers = get-exchangeserver ex2013* | Where AdminDisplayVersion -like *15*

$final = @()

$Servers | %{ 
write-host $_.Name
$Name = ([System.Net.Dns]::GetHostEntry("$_")).HostName;
$Address = ([System.Net.Dns]::GetHostEntry("$_")).AddressList;
$PTR = ([System.Net.Dns]::GetHostByAddress($Address)).HostName

$returnobj = new-object psobject
$returnobj |Add-Member -MemberType NoteProperty -Name "ServerName" -Value $Name
$returnobj |Add-Member -MemberType NoteProperty -Name "IPAddress" -Value $Address
$returnobj |Add-Member -MemberType NoteProperty -Name "PTR" -Value $PTR
$final += $returnObj

$Name = $null
$address = $null
$ptr = $null


}

$final

 

 

 

Working with Mailbox Database Copy Activation

This example only suspends activation for the copy of the database DB1 hosted on the Mailbox server MBX3.
Suspend-MailboxDatabaseCopy –identity DB1MBX3 –ActivationOnly

To Resume activation
Resume-MailboxDatabaseCopy –identity DB1MBX3

To block all databases hosted on a server from activating.
Set-MailboxServer –identity MBX3 –DatabaseCopyAutoActivationPolicy Blocked

Resume activation of server
Set-MailboxServer –identity MBX3 –DatabaseCopyAutoActivationPolicy Unrestricted

To block all databases hosted on a group of servers from activating. Use wildcard (MBX*)
Set-MailboxServer –identity MBX* –DatabaseCopyAutoActivationPolicy Blocked