Hybrid Exchange PowerShell Part 2: Creating a New User Account

In the first part of this series, we set up our PowerShell environment for Hybrid Exchange administration. If you haven’t done that, review the other article to make sure you are ready for this one.

Now we will get down to business and create a new user. This is something that can take an annoying amount of time to do using the various web portals and things that Microsoft offers, so PowerShell is going to be very helpful here.

I always use PowerShell ISE. ISE stands for “Integrated Scripting Environment”. One of the good things about ISE is that you can have a text editor next to or above your PowerShell window, like this:

This makes it easier to keep track of your script.

In our scenario we will be assuming this is a brand new user. A new hire. They don’t have an Active Directory account yet so they need one of those and they need an email account.

Gathering the User’s Information

You are going to have to supply certain information about the user in order to create the account. If you leave any of these things out, you will either get an error or it will prompt you to enter the missing information before you can continue. Lets gather this info together now and store it in variables so we can plug them into the New-Mailbox command later.

You will need:

  • First name
  • Last name
  • Your domain
  • The orginizational unit in Active Directory that the user will belong to
  • The Exchange database the user’s mailbox will go into
  • The user’s password
  • The email address
  • The user’s display name, which is usually their first and last names
  • The user’s alias, which is the part of the email address before the @

Create these variables in PowerShell’s Script Pane. It will look something like this:

$last = "Ted"                
$first = "Logan"
$domain = "WyldStallyns.com"
$OU = "CN=Ted Logan,OU=WSUsers,DC=BAND,DC=WyldStallyns,DC=com"
$DB = "DB4"
$pass = "SanDimasHighSchoolF00tBallRules!"
$name = ($first + " " + $last)
$alias = ($first.substring(0,1)+$last)
$UPN = ($first.substring(0,1)+$last+$domain)

If you don’t know, the words with the dollar sign in front of them are variables. Naming them like this and then using an equals sign with words in quotes will assign the words to the variable so you can just type, for example, $domain and it will be as if you typed the words in the quotes. This makes it easy to modify the script later for another user. You would only need to change the names, password, and maybe the OU and the database.

The variables with the parentheses are modifying the previous variables to make new ones. Once you have all of these entered in to the Script Pane, click the green “Run Script” button to save your variables and then type $UPN in the blue bottom pane and press Enter. You’ll see that the $UPN variable is made from some of the other variables, just rearranged into an email address.

This is basic PowerShell, but I want to mention it now so no one gets confused when I add variables later without declaring them. They’ll be created just like the ones above, only off-screen, as they say in the movies.

Creating the Mailbox

Now that we have the user’s information entered into PowerShell (you clicked the green “Run” button, right?), we can plug them into the New-Mailbox command:

New-Mailbox -Lastname $last -FirstName $first -Name $name -DisplayName $name -Alias $alias -userprincipalname $UPN -OrganizationalUnit $OU -database $DB -password (ConvertTo-SecureString -string $pass -AsPlainText -Force) | set-mailbox -singleitemrecoveryenabled $true

This is the command that actually tells Exchange to create the new user account, so make sure everything is correct before you run it! If you named your variables the same as mine, you can literally just copy and paste that New-Mailbox command into PowerShell and run it. To check that it worked, run the following:

get-mailbox $name | fl

That will give you a ton of info about the new user’s new mailbox. Now you can go check in your Exchange Management Center portal and you will see the new user mailbox. If you open Active Directory Users and Computers you will also see the new user there.

Now that the new user account is created we can start adding valuable information to the account like job title, manager, address, phone number, etc. We’ll do that and more in the next article.

Later, in the final part of the series I will give you my complete NewUser.ps1 script that combines all of these steps into one really easy to use process.

Hybrid Exchange PowerShell Part 1: PowerShell Setup For System Administration

A “hybrid” Exchange deployment is when you have on-premise Exchange email servers, but some other aspects of your email system is on Microsoft’s servers. Thus, your deployment is split between “local” and “cloud” servers. There are many reasons to have this type of setup, but a common one is that you are transitioning from on-premise email servers to a completely Office 365 configuration. In other cases you may go hybrid to take advantage of a particular license structure for your Microsoft Office situation.

As you might expect this requires some new approaches to the usual system administration tasks. In the next article I’ll show you how to create a new user account. There are, of course, graphical methods for doing this, but it takes multiple programs across the Windows Server OS and the Exchange and Office 365 administration portals. It frankly takes way too much time to do it that way and it’s not very efficient.

This series will focus on PowerShell for Hybrid Exchange. When I work with user accounts, I use PowerShell to remote into an Exchange server on my domain with the Active Directory PowerShell module installed. You may want to work directly on the Exchange server or something completely different so some of your setup may be different than mine.

The Active Directory Module

The first thing we need to do is to make sure we have the required PowerShell modules installed. PowerShell is most likely going to be installed on your server or computer already, but it probably doesn’t automatically have all of the commands we need right out of the box. For that we need to install the correct module into PowerShell that has all of the stuff we need.

I always use PowerShell ISE. ISE stands for “Integrated Scripting Environment”. One of the many good things about ISE is that you can have a text editor next to or above your PowerShell window, like this:

The upper, white area is the Script Pane. Type this into the Script Pane and then press enter:

get-aduser -filter * | ft

If you already have the Active Directory module installed this will output a table of all Active Directory user accounts. If you don’t have the module installed, you will get an error like this:

get-aduser : The term 'get-aduser' is not recognized as the name of a cmdlet, function, script file, or operable program.

This is because the module isn’t installed so PowerShell doesn’t recognize the command (cmdlet). There are a few ways to install the module depending on the version of Windows you are using.

If you are using the newer (2019 +) versions of Windows 10, the methods have changed and the documentation isn’t very specific yet. What you need to do now is just click the Start button or taskbar search and type “
Manage optional features”. On the “Optional Features” page, click “Add a feature”. Now you will see a long list of features you can install. The one we want is called “RSAT: Active Directory Domain Services and Lightweight Directory Services Tools”. Click “Install” and it will disappear (without any kind of notification?) and go to the previous screen that lists the installed features.

If you are using Windows Server, you can use Server Manager > “Add Roles and Features” > Click through to the “Select Features” list > “Remote Server Administration Tools” > “Role Administration Tools” > “AD DS and LDS Tools”.

For other versions of Windows, this guy here has a really good resource for you.

Now when you run “get-aduser -filter * | ft” again you should get your table of users.

The Exchange PowerShell Module

When you installed Exchange on your server it should have installed the Exchange Management Shell (EMS) which is what it sounds like: a command-line interface for Exchange. The EMS automatically connects to exchange when it opens so you can start running Exchange Powershell commands. If you want, you can use the Exchange modules on the Exchange server, but in regular Powershell by using add-pssnapin:

add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

You can also use PowerShell to remote into the Exchange server if you don’t want to – or can’t – use Remote Desktop to log into the Exchange server. First, you need to give PowerShell your username and password. This command will prompt for your credentials and store them in a variable:

$UserCredential = Get-Credential

Next, we create a session object for the connection with the Exchange server:

 $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<FQDN of Exchange server>/PowerShell/ -Authentication Kerberos -Credential $UserCredential

And finally we begin the session:

 Import-PSSession $Session

To end the remote session (this will actually end all sessions):

Get-PSSession | Remove-PSSession

Now you can run this to get a table of all Exchange mailboxes:

get-mailbox | sort alias | ft

In the next article we will create a new Active Directory user account.

Project: Setting Up a Server From Scratch

Lately, I’ve been installing enough new servers (or inheriting newly installed servers) that now seems like a good time to show what it’s like to start from scratch with a brand new server. Obviously, no one will have exactly the same implementation as this, but the idea is to show the basics of what it’s like to set up a new server.

This will not cover everything you can do with a server. It’s basically just a way for me to organize my posts into something fun.

This page right here is going to host links that, if followed chronologically, will show what it looks like to build a brand new server straight out of the box. Basically all I’m doing is reordering some of my existing posts, but this page will corral them into a mighty Voltron of a larger project. I will probably go back and edit the old posts to make more sense in the context of this project (or not depending on how much time I have). Don’t worry, the original posts will work as standalones.

Anyway, here’s what it’s like to buy and implement a server!

(This is a work in progress. All of the steps may not be here yet. I’ll remove this disclaimer when I feel it is more complete)

Unboxing the HPE DL380 Gen10 server

Enabling The Third Drive Box On An HPE DL380 Gen10 Server

Installing Windows Server 2019

New Windows Server 2019 Server: Miscellaneous Setup

Automating Windows Server Updates Part 1: Sconfig

Automating Windows Server Updates Part 2: PowerShell

Automating Windows Server Updates Part 3: Scheduling the Task

HPE Server Hardware Alert Emails: Gen 10 Changes

Automating Windows Server Updates Part 3: Scheduling the Task

Automating Windows Server Updates Part 1: Sconfig

Automating Windows Server Updates Part 2: PowerShell

In the previous post I showed how to use PowerShell to find and install Windows Updates. In this one, we will run our PowerShell script every Sunday afternoon using Task Scheduler. The script will install any available Windows Updates, reboot the computer if necessary, and email us the details of the installation.

The Scheduled Task

Open Task Scheduler. One way to do this is to hold the Windows key and press R. In the Run box type: taskschd.msc. In Task Scheduler, right-click on the Task Scheduler Library and choose “Create Basic Task”.

The “Create Basic Task Wizard” will open. Name your task something descriptive.

In my case I want the task to run on Sundays so I choose “Weekly”. Yours may differ.

Your next screen could look different. In my case I chose Weekly so I choose the day of the week here.

Next we choose “Start a Program” because we want to start PowerShell to run our Windows Update script. We will be sending an email also, but that part is in our PowerShell script so we can ignore the “Send and e-mail” option here. It doesn’t work anymore anyway.

For the “Program/Script” field you will either paste in or browse to the .exe for PowerShell. Chances are good it’s the same as mine below. In the “Add Arguments” field you put the path to your .ps1 script file including the file name. For example if it’s on the same computer you’re running the Task Scheduler on it may be C:\Scripts\WUpdate.ps1 or if the script is on a file share it may look like \\Server1\Share\Scripts\WUpdate.ps1. “Start In” can stay blank unless you really need it.

The last page lets you review the task before you create it. If everything looks ok, click “Finish”.

Double-click on the new task. The only thing you should have left to do in the settings is click the radio button next to “Run whether user is logged on or not.” This is important because we will be at the beach on Sunday when the task needs to be run so we will definitely not be logged in. You may also want to change the user account used to run the task, but that depends on your circumstances. Click OK. You will be asked to give the password for the account that will run the task since it will not be logged in at the time the task will run.

Now, to test it! Right-click on the new task and choose “Run”. If everything was done correctly you will get an email that looks like this:

Moving the Scheduled Task to Other Servers

You can export the task to XML so you can import it into another server. All you need to do is right-click the task in Task Scheduler and choose “Export”. Here is my XML. Yours may differ.

<?xml version="1.0" encoding="UTF-16"?>
-<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task" version="1.2">
  -<RegistrationInfo>
    <Date>2018-09-12T13:42:45.1141389</Date>
    <Author>domain\username</Author>
    <URI>\WindowsUpdate</URI>
  </RegistrationInfo>
 -<Triggers>
   -<CalendarTrigger>
      <StartBoundary>2018-09-16T18:00:00</StartBoundary>
      <Enabled>true</Enabled>
     -<ScheduleByWeek>
       -<DaysOfWeek>
          <Sunday/>
        </DaysOfWeek>
        <WeeksInterval>1</WeeksInterval>
      </ScheduleByWeek>
    </CalendarTrigger>
   -<CalendarTrigger>
      <StartBoundary>2018-09-16T20:30:00</StartBoundary>
      <Enabled>true</Enabled>
     -<ScheduleByWeek>
       -<DaysOfWeek>
          <Sunday/>
        </DaysOfWeek>
        <WeeksInterval>1</WeeksInterval>
      </ScheduleByWeek>
    </CalendarTrigger>
   -<TimeTrigger>
      <StartBoundary>2019-02-23T22:00:00</StartBoundary>
      <Enabled>true</Enabled>
    </TimeTrigger>
</Triggers>
-<Principals>
   -<Principal id="Author">
      <UserId>UserId</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>LeastPrivilege</RunLevel>
    </Principal>
</Principals>
-<Settings>
   <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
   <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
   <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
   <AllowHardTerminate>true</AllowHardTerminate>
   <StartWhenAvailable>false</StartWhenAvailable>
   <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
  -<IdleSettings>
     <StopOnIdleEnd>true</StopOnIdleEnd>
     <RestartOnIdle>false</RestartOnIdle>
   </IdleSettings>
   <AllowStartOnDemand>true</AllowStartOnDemand>
   <Enabled>true</Enabled>
   <Hidden>false</Hidden>
   <RunOnlyIfIdle>false</RunOnlyIfIdle>
   <WakeToRun>false</WakeToRun>
   <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
   <Priority>7</Priority>
</Settings>
-<Actions Context="Author">
  -<Exec>
 <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
       <Arguments>PathToFile</Arguments>
     </Exec>
   </Actions>
</Task>

To import the task into the second server open Task Scheduler on that server and right-click on “Task Scheduler Library”. This time choose “Import Task” and browse to your XML file that you exported. The settings of the task will automatically open so you can review or change them.

Automating Windows Server Updates Part 2: PowerShell

Automating Windows Server Updates Part 1: Sconfig

Automating Windows Server Updates Part 3: Scheduling the Task 

Windows updates can be a blessing and a curse. On the one hand, it’s great that Microsoft is proactive in fixing issues with their operating system. On the other hand many of the issues with their operating system come from botched Windows Updates. Like deleting your files, for example:
https://www.howtogeek.com/fyi/bug-in-windows-10s-latest-update-might-be-deleting-files-back-up-your-data-now/

Another annoying thing about Windows Updates is that they often require a reboot and a long time watching percentages slowly rise (Often we find ourselves staring at 100% complete for a half an hour). This is especially bad when dealing with production servers that can only be rebooted on a Sunday.

Windows does have a built-in scheduling for installing Windows Updates, but it often just doesn’t work and you don’t have much flexibility about the timing of when things end up happening. In the newest version of Windows 10 you can delay updates for up to a week, but that’s it. Working hours can be set so the thing doesn’t reboot during the day, but there are limits to that, too.

Another, more fun way to handle Windows Updates is, of course, PowerShell! In this article we are going to learn how to use PowerShell to install Windows Updates and in the next article we will use Task Scheduler to run the script on Sunday afternoon when no one is at work.

(See my previous post for instructions on setting Windows Updates to manual only with Sconfig. Keep in mind Sconfig is only for Windows Server, not Windows 10.)

Installing the Windows Update PowerShell Module

First we will need to download the PowerShell module that controls Windows Updates. Download the required module here: tp://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc/
It’s small so it won’t take long.

Unzip the file to C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ and then open PowerShell as an administrator (Right-click to find that option). I like to use PowerShell ISE because it’s got the nice “script pane” built in so you can copy and paste my examples in there and modify them to suit your environment.

To make sure it installed correctly and to see what new functions we have run:

Get-Command –module PSWindowsUpdate

If you get an error like: ” FullyQualifiedErrorId : CommandNotFoundException Get-WUInstall : The term ‘Get-WUInstall’ is not recognized as the name of a cmdlet, function, script file, or operable program” then run this:

Import-Module PSWindowsUpdate

This next command will list all of the Windows Updates you can install on your computer, but does not install them.

Get-WUInstall
–WindowsUpdate –ListOnly

You may know that in the Settings GUI version of Windows Update you can use Windows Update to get updates for other things besides Windows, like Microsoft Office. You can do that with PowerShell, too! It just requires one extra step in the initial setup.

The command for the wider search of Microsoft (as opposed to Windows) Updates is:

Get-WUInstall –MicrosoftUpdate –ListOnly

If you run that one now you will get an error:

Luckily, this is easy to fix. Just run this to register the proper service:

Add-WUServiceManager -ServiceID
7971f918-a847-4430-9279-4a52d1efe18d

Now run Get-WUInstall –MicrosoftUpdate –ListOnly again:

As you can see, I now have an update for Silverlight in addition to the Windows Defender updates.

Installing The Updates With PowerShell

Now that you’ve seen what updates are ready to install you can install them simply by running:

Get-WUInstall –MicrosoftUpdate

You will get a popup asking for permission to install the update:

You can click “Yes” or “No” for each indvidual update or click “Yes to All” to install all of them from the first popup. Another approach would be to run this so you don’t have to approve them and they will just install:

Get-WUInstall –MicrosoftUpdate –AcceptAll

You can even add -AutoReboot at the end to have the server automatically reboot after installing the updates if required to do so. This is what we will be doing in our scheduled task so we don’t have to remote in to the server on a Sunday when we’d rather be at the beach:

Get-WUInstall –MicrosoftUpdate –AcceptAll –AutoReboot

This what it will look like as it does its thing. Notice the message displayed above the code window as it goes through the steps of Accepted, Downloaded, and Installed:

And when it’s finished installing it will look like this (assuming everything installed correctly):

There is a chance that an update could fail. If one does you will get output like:

4 Failed                63 KB Microsoft driver update for MS Publisher 

If you have an update that repeatedly fails to install you could download it from the Microsoft Update Catalog (https://www.catalog.update.microsoft.com/Home.aspx ) and install it manually or you could disable installing the one specific update if you decide you don’t need it.

Disabling Specific Windows Updates

One of the other useful commands is Get-WUHistory. This will show you all of the Windows Updates that installed on the computer, their KB, and the date and time of installation. This is handy for finding updates that broke your computer and need to be uninstalled. You can always Google the KB to find out exactly what the update entails.

If you find one that you want to uninstall, here’s how to do it (replace the KB with the one you want to uninstall):

Get-WUUninstall -KBArticleID KB4501375

Sometimes the KB isn’t listed so you have to use the title. Here is a way to disable an update easily assuming it’s the only update left:

$u = Get-WUInstall –WindowsUpdate –ListOnly
$t = $u.title
Hide-WUUpdate –title $t –MicrosoftUpdate –Confirm:$false

To keep Windows from installing that update again you will have to “hide” it or it will install it again later:

 Hide-WUUpdate –KBArticleID KB4501375–MicrosoftUpdate –Confirm:$false

If you change your mind and want to “un-hide” an update:

Hide-WUUpdate -KBArticleID KB4501375-hidestatus:$false

The PowerShell Script

Ok, lets build our script that we want the task to run for us. I’ll give you the whole thing, then break it down into its parts.

$file = "PathToTranscriptFile"  
$from = "from@domain.com"
$to = "to@domain.com"
$subject = "Windows Update Report"
$smtp = "smtpserver.domain.com"
Start-Transcript -path $file
Get-WUInstall –MicrosoftUpdate –AcceptAll –AutoReboot
#Get-WUInstall –MicrosoftUpdate –ListOnly
Stop-Transcript
$body = [IO.File]::ReadAllText($file)
send-mailmessage -from "$from" -to "$to" -subject "$subject" -smtpserver "$smtp" -body "$body"

You can copy and paste this into a text editor and then change the variables in bold to values that make sense for your environment. Save the text file with a .ps1 file extension.

If you don’t need the details of the script explained you can skip to the next section.

$file = "PathToTranscriptFile"  
$from = "from@domain.com"
$to = "to@domain.com"
$subject = "Windows Update Report"
$smtp = "smtpserver.domain.com"

Anything beginning with a dollar sign ($) is a variable in PowerShell. The ones above are our email settings. PowerShell will need to know how to send the email so you will need to swap out your values for the parts in bold.

$file = "PathToTranscriptFile" 

This variable stores the path to the transcript file to simplify adding it into the body of the email.

Start-Transcript -path $file

Start-Transcript does pretty much what you’d think: it saves what happens in the PowerShell window to a file. This is how we’re going to harvest the status of the Windows Updates so we know what got installed.

Get-WUInstall –MicrosoftUpdate –AcceptAll –AutoReboot

This is the command we learned in the last post. It installs all of the available Windows Updates and reboots the computer if necessary.

#Get-WUInstall –MicrosoftUpdate –ListOnly

This line with the “#” in front of it will not run. The “#” tells PowerShell to ignore the line and go to the next line. I have this line in here for testing purposes. When I only want to get an email about the available updates, but I don’t want to install them (and I DEFINITELY don’t want to reboot the server) I will move the “#” up one line to expose this test line and hide the one that does the real update. You might want this line for initial testing just in case the email doesn’t work how you need it to at first. When you get everything how you like it you can move the “#” back down a line.

Stop-Transcript

Then we stop the transcript so we can get the file the transcript created and put it in the body of an email.

$server = $env:COMPUTERNAME

In this line we are creating a variable that holds the name of the server we are running the Windows Updates on. The server name is only useful if you are running this script on multiple computers, which I am.

$env is basically a list of variables that you can use to get (or set) information about your computer. You can run Get-ChildItem Env: to see a list of all of the Environment variables. COMPUTERNAME is the name of the computer, of course, and using the Environment Variable for it enables us to use this same script on any computer; we don’t need to supply the computer’s name because the script gets it for us at runtime!

$body = [IO.File]::ReadAllText($file)

The $body variable reads the $file variable that has our Update info and stores it to use in our email alert.

send-mailmessage -from "lslerts@lslog.com" -to "twood@lslog.com" -subject "Windows Update Report" -smtpserver "xserver.lslog.com" -body "$body"

Finally, we send the email alert. Send-mailmessage is the commandlet that sends an email. It requires a sending email address, a destination email address, a subject line, an email server and the body of the email which contains the details of our Windows Updates.

You can test this script by opening PowerShell ISE as an administrator and loading the script from “File” > “Open” or the folder icon.
Don’t forget to move the “#” up to the -AutoReboot line if you don’t actually want to install and reboot the server. Press the green “play” icon to run the script.

If everything was done correctly you should get an email that looks like this:

In the next post I will show you how to set up a scheduled task that will run Windows Updates every Sunday afternoon.

Automating Windows Server Updates Part 3: Scheduling the Task