PowerShell Monthly, June 2019

Blog Articles

An Example Azure DevOps Release Pipeline for PowerShell modules

Configuring Power Scheme with a PowerShell One-Liner

Create and Import Autopilot CSV File into Intune from OOBE

Export-CliXML and Import-CliXML serialization woes

Fixing Active Directory PasswordNotRequired with PowerShell

Getting Windows 10 build version from Active Directory

Iron Scripter challenge: A PowerShell Cryptogram

Locking Down PowerShell to Foil Attackers: 3 Essentials

PowerShell 7 gets new core, simplified credentials, logging

PowerShell Script to Delete Files By Age with Email Summary Report and MS Teams Notification

Restore Group Policy with PowerShell

SharePoint servers report using PowerShell

Using PowerShell to retrieve CAC Information

read more

Working with Windows Registry and PowerShell

Most people that does system administration in a Windows environment have had to work with the Windows Registry. This registry serves as a database of settings, used with everything from applications to drivers. The usual way of working with the Windows Registry is through regedit or Group Policy Objects but what if you have a server core that is not domain joined?

As per usual, PowerShell to the rescue!

How does it work

One magical thing about PowerShell is the concept of PowerShell Drives (PSDrives) which works with a PowerShell Provider to make it easy to use data stores in PowerShell. One example is your C-drive, which is available as a PSDrive through the FileSystem provider. There are several other providers that are mapped through PSDrives, like WSMan, Alias, Certificate and more importantly for this article the Registry-provider.

By using the drives HKLM: and HKCU: you can browse the registry, as if it was folders on your computer. Combined with the fact that a registry key is an item, you could then either add a new registry keys or add / change registry entries by changing the properties on said keys.


# List registry items
Get-ChildItem HKCU:
# List registry items, selecting just the name of the item
Get-ChildItem HKCU: | Select-Object Name
# List registry items, recursively 
Get-ChildItem HKCU: -Recurse

Creating new items and changing their property

# Create the item
New-Item HKCU:\Environment\Test
# Create a DWORD, set it to 1
Set-ItemProperty -Path HKCU:\Environment\test\ -Name "dword" -Value "1" -Type DWord
# List all values 
Get-ItemProperty -Path HKCU:\Environment\test\

You can see a lot more examples at the Microsoft documentations.

read more

Cross-Forest mailbox migration with Microsoft Exchange

We recently started a fun project, doing some mailbox migration. For this project, in particular, we were merging four Exchange organizations together and the new Active Directory was to consist of brand new user accounts. In other words, we’re not moving the accounts themselves but just the mailbox.

The solution was a mixture of what docs.microsoft.com and many of the articles that I had read, so my thinking is that there’s a need for a really explicit article about this process. As always I use PowerShell wherever it’s applicable and we will specifically be looking at how we can migrate mailbox to a forest where the users already exist.

Mailbox migration process </figure>

Prerequisite for cross-forest mailbox migration

There are a few things that need to be done before performing a cross-forest mailbox migration. Some are mandatory, others option or just nice to have done.

Run the latest patch of your Exchange server: Whenever I talk to customers about mailbox migration, I ask them to upgrade to the latest cumulative update. In some cases, it’s a necessity but either way, it should be done, just to make sure you don’t end up catching any bugs during the migration.

Have the right permissions: You can migrate mailboxes if you’re part of the Organization Management or the Recipient Management role group. Remember to practice the rule of least privilege.

Enable MRS Proxy endpoint: This is required for any cross-forest mailbox migration or remote move migrations between on-premises and Exchange Online. You could enable this either through EAC or with PowerShell.

If migrating mailboxes to existing users, they have to be mail enabled: So that the mailbox will match up, you have to run Enable-MailUser with the ExternalEmailAddress parameter.

The Exchange organizations should be connected: This one might be obvious, but it’s still worth mentioning. You need to be able to connect to EWS to migrate mailboxes.

Prepare for the mailbox migration

Preparing the mailbox is really a simple step. We utilize a script that comes with Exchange and then update the recipient. The script then copies some vital attributes from the source mailbox user to the target mail user. The following will be copied:

  • msExchMailboxGUID
  • msExchArchiveGUID
  • msExchArchiveName

Supposedly, the script should run the cmdlet Update-Recipient. This is to add the LegacyExchangeDN attribute to the user but this has not yet happened to me. Just in case it doesn’t happen, we will do this at the end of the script.

As you will see, we use the UseLocalObject and OverWriteLocalObject to merge the information of the mailbox to our existing user.

# Change directory to the script folder
CD "C:\Program Files\Microsoft\Exchange server\V15\Scripts"

# Add credentials, from both forests
## Remote = Source forest (Where the mailbox resides)
## Local  = Target forest (Where your new user is)

$RemoteCreds = Get-Credential
$LocalCreds = Get-Credential

# Create a splat with all our parameters and switches
$splat = @{
   identity = "johnny@old.domain.org"
   RemoteForestDomainController = "dc1.old.domain.org"
   RemoteForestCredential = $RemoteCreds
   LocalForestDomainController = "dc1.new.domain.org"
   localForestCredential = $LocalCreds
   UseLocalObject = $True
   OverWriteLocalObject = $true

# Run the script, with our splat
.\Prepare-MoveRequest.ps1 @splat

# Make sure that the LegacyExchangeDN is added
Update-Recipient johnny@new.domain.org

PowerShell will let us know that the command is done running and that your mailbox is ready to be migrated.

If you’re migrating more than one mailbox you could either pipe several users or use a CSV. In either case, remember to remove the identity parameter in your splat.

If you’re curious about splatting, feel free to read this short introduction I’ve written.

Start the mailbox migration

We will start off by defining what Exchange-server we are migrating from, and what the new

$splat = @{
   Identity = "johnny@old.domain.org"
   Remote = $True
   RemoteHostName = "exchange.old.domain.org"
   RemoteCredential = $RemoteCreds
   TargetDeliveryDomain = "new.domain.org"

New-MoveRequest @splat

You should now have created a new request that will migrate the users mailbox between forests, from one Exchange organization to another.

read more

Set up a domain to catch all emails in Exchange Online

How many websites do you sign up to every year? Usually, whenever you register at a website you use your primary email address, right? This is just easier, and you get the email straight away, login, and everyone is happy. How long does it take before a brand-new email address is filled to the brim with spam and phishing emails?

One way to combat this is to not use your email address whenever you register somewhere. Instead, we’ll create some nifty rules in our Exchange that will catch any mail that comes into our organization that is sent to a certain domain and redirect it directly to a folder in our mailbox.

What are the benefits {#0d69}

There are several reasons to do this but the most prominent one is that you won’t spread your primary email address around. You will always end up getting spam and phishing and there is no way around that but using your primary email address for everything puts it out into circulation.

If a site you’ve registered at goes rogue and sells their userbase, or gets hacked, your email will be on some very naughty lists. In the same way that you don’t want to use the same password for all sites, you don’t want to log in with the same email address everywhere.

The way we will do it, you could easily see who “betrayed” you. If you use facebook@myspamdomain.com _to log into Facebook, this is the address that will be the receiver if they get hacked and someone adds your email to a list of potential _suckers.

Setting up the mail flow rules in Exchange

I’m doing this in Exchange Online, but as far as I know these options are available in the on-premises version as well.

Navigate to Exchange Admin CenterMail Flow and the Rules tab.


As you can see, we start off by defining that this rule will trigger if the email is from outside of the organization and that the recipients domain is your dedicated catch-all domain. This will of course mean that you would have to have an extra domain available that is used for nothing else.

Now, you are more or less done. But you will now get all spam sent to your spam-domain straight into your inbox. This is not what we want, so let us create an inbox rule that moves these emails to a folder and out of sight.


You could get to the rules by pressing the cogwheel in the right corner of your Outlook Online and search for Inbox Rules. These rules can also be created in the desktop version of Outlook.

Here we have a condition that will move email that is sent to our spam-domain into a folder. This means that if someone sent you an email that ends with that domain name, it will be moved into that folder.

Of course, after setting up such rules we must test it.


That’s about it! And all you need is an extra domain that you don’t mind using for only one purpose.

This also works with a subdomain if you’ve set that up correctly. However, that means you must set up your domain as Internal Relay so if you need an email to bounce if not sent to a valid recipient you can use that. It will, of course, kind of stop our efforts here as we need to be open to receive emails sent to anything that ends in our domain.

read more

PowerShell Monthly, May 2019

New Releases

PowerShell 7 Preview

Release date: 2019-05-30 – Release Page: Github

The new release of PowerShell (formerly Core) is getting a new naming convention and porting code to .NET Core 3. You can read more about it here.

Blog Articles

PowerShell 7 Road Map

An Example Azure DevOps Build Pipeline for PowerShell modules

Follow this step-by-step guide to use AWS Lambda with PowerShell

How I didn’t know how powerful and fast hashtables are

What do we say to writing Active Directory documentation?https://evotec.xyz/what-do-we-say-to-writing-active-directory-documentation/

PowerShell Basics: Want to Use Exchange Online in Azure Cloud PowerShell?https://techcommunity.microsoft.com/t5/ITOps-Talk-Blog/PowerShell-Basics-Want-to-Use-Exchange-Online-in-Azure-Cloud/ba-p/544074

Follow this step-by-step guide to use AWS Lambda with PowerShell

read more