How to enable remote Powershell?

Interestingly, it was quite confusing to find out how to setup it properly, so I decided to create a blog post about it.

On the server side, open Powershell with elevated privileges (Run as Administrator), an execute this command:

Enable-PsRemoting

Unfortunately, this will not be enough if any of your current network interfaces are not in a private or domain network. For example, if VMWare Workstation is installed on your system, its virtual network interfaces are categorized as members of unidentified networks. To overcome this issue, check the solution introduced by this post.

Now we can move to the client side. In the case of not being joined to a domain network, we have to mark the servers as trusted hosts. To achieve this, open cmd.exe (not Powershell) with elevated privileges and run this command:

winrm set winrm/config/client @{TrustedHosts="server1, server2"}

You can read or write the TrustedHosts property with Powershell too: run the Powershell command prompt with elevated trust and use the Get-Item and Set-Item cmdlets with the appropriate wsman path. The path is autocompleted, so it is much easier to type it here. You can also use the Concatenate switch to simply add a new host. In order to allow the client connect to any server, use the wildcard character.

Get-Item WSMan:\localhost\Client\TrustedHosts | select -ExpandProperty Value
Set-Item WSMan:\localhost\Client\TrustedHosts "server1,server2"
Set-Item WSMan:\localhost\Client\TrustedHosts "server3" -Concatenate -Force
Set-Item WSMan:\localhost\Client\TrustedHosts *

Now we can connect to the server with a Powershell session. On a domain network this might be enough:

Enter-PsSession server1

If you are on a non-domain network or your current user does not have the appropriate rights, you have to specify the appropriate credentials explicitly.

Enter-PsSession server1 -Credential (Get-Credentials)

You can also run multiple sessions simultaneously, and switch between them on demand.

$s = @("server1", "server2") | New-PsSession
Enter-PsSession $s[0]
Exit-PsSession
Enter-PsSession $s[1]
exit

Unfortunately these commands are only for interactive usage, so you are not able to use them in scripts. For remote script execution Invoke-Command is the way to go, but this a much longer story…

Exchange well-known folder hell

During an Exchange Server migration I have encountered an annoying problem. I have exported the mailboxes from an old Exchange 2003 server into PST files. After that, these files were imported into the newly created mailboxes of a new Exchange 2010 server. This process did not go absolutely smoothly, the following problem occurred:

The former figure presents what happens if the language of the new and exported mailbox are not identical (e.g. hu/HU => en/US), the latter shows how the mailbox look like if the the languages are identical (e.g. en/US => en/US).

owa2        owa1

I searched around the internet and I found out that this is a really common phenomenon and is said to be a bug. It seems that the well-known folders are referenced by their localized name instead of an invariant name in the PST files. Furthermore, if the folder already exists, the imported folder will be renamed (number is concatenated). Fortunately, I found a very impressive Powershell script on the Microsoft Technet forum that is meant to solve this issue.

After a bit examination and preparation the script worked flawlessly, it cleaned up the mess in the mailboxes nicely. I really appreciate the author‘s effort and generosity. I also worked on the script a bit too. I think it is much easier to use now.

First of all, the script is based on EWS 1.1, so you have to download and install it on the Exchange Server. (Update: It seems the EWS 1.1 link is dead, try EWS 1.2, it should work too)

Now, create a CSV file that describes the folder mappings:

folder,source
Inbox,"Beérkezett üzenetek"
Inbox,"Beérkezett üzenetek1"
Inbox,Inbox
Inbox,Inbox1
SentItems,"Elküldött üzenetek"
SentItems,"Elküldött üzenetek1"
SentItems,"Sent Items"
SentItems,"Sent Items1"
Notes,Feljegyzések
...

The first element of each row is the invariant name of a well-known folder (my sample file contains all of them), the second is a possible localized name that the script should look for.

In the following example, the script is going to be executed on my mailbox. First, import the Exchange Powershell snapin and the cleanup script.

Add-PSSnapin Microsoft.Exchange.Management.Powershell.E2010
. ./Cleanup-Mailbox.ps1

Query the problematic mailboxes, in this case: mine.

$m = Get-Mailbox tom

The user that executes the script needs Full Access permission on the mailboxes.

$m | Add-MailboxPermission -User Admin -Accessright Fullaccess

Now, run the cleanup script on the mailboxes by simply piping them to the Cleanup-Mailbox function. The Mapping parameter should point to the previously created CSV file. If the Test switch is specified, than the script will only output the diagnostics messages without doing the modifications. I suggest to try it before production use.

$m | Cleanup-Mailbox -Mapping ./folders.csv -Test

That’s it, my mailbox has been cleaned up! It is recommended to remove the Full Access permission.

$m | Remove-MailboxPermission -User Admin -Accessright Fullaccess

You can download the cleanup script from here, and the previously mentioned sample mapping CSV file here.