Aug 31

Remove RDS CALs from RDS Server

Background

There are many circumstances where you will need to remove a RDS CALs from an RDS Server, or in some cases you want to rebuild the entire RD licensing database.  Microsoft allows you to remove an individual CAL license pack using powershell, or rebuild the entire database.  However, if neither of those work, it’s quite easy to manually rebuild the RD licensing database.  I’ve included directions for all 3 methods below, and have tested this on Windows Server 2008, 2008R2, 2012, 2012R2, and 2016.

Remove An Individual RDS CAL License Pack Using Powershell (User or Device CAL)

  • Open powershell elevated as an administrator
  • Type the following command to list the RDS Licenses and note the KeyPackID
    • Alternatively, open RD Licensing Manager and note the Keypack ID

  • Run the below command to remove the licenses pack from your RD Server
    • Replace KEYPACKID with the number you obtained above

 

Rebuild the RD Licensing Database

Microsoft provides directions on how to do this automatically, via a web browser, or via the phone:

https://technet.microsoft.com/en-us/library/dd851428.aspx

 

Manually Rebuild the Licensing Database (Guaranteed to Work if the Previous 2 methods Fail)

  • Make sure you have documentation of your MS License agreement that includes Authorization number, License number, License type (User/Device CAL), and Quantity before proceeding
  • Stop the Remote Desktop Licensing service

Stop Remote Desktop Licensing Service

  • Rename C:\Windows\System32\lserver\TLSLic.edb to C:\Windows\System32\lserver\TLSLic.old
  • Start the Remote Desktop Licensing service
  • All licenses will now be cleared out of RD Licensing Manager, and you’ll need to re-install the licenses you want to add back in
Jul 14

Complex Password Generator

 

Jul 14

365 Password Generator

This powershell script bulk generates passwords in a similar style as the password generator in Office 365.  The passwords begin with a capital letter, followed by 5 lower case letters, and 2 digits at the end.  You can modify the pattern to suite your needs (Note: It’s using the ASCII table ranges as the set it randomly chooses from).

 

Mar 03

Determine If Distribution Group is Being Used in 365 Exchange

“What distribution groups are in use?” and “How many emails are sent to a specific distribution group per month?” are common questions I receive with 365 Exchange or Exchange.  Unfortunately, there is nothing built in that tracks how many emails on sent to a distribution group.  However we can use Get-MessageTrace to count the number of messages sent to a distribution group for a time range with the max being 30 days.  Also note, the by default PageSize returns 1000 items but you can increase the PageSize to 5000 items.  For example, to get the number of emails sent to the distribution group everyone@domain.com for a single day we can use:

Using this method, we can count the number of emails sent to each distribution group each day and store the results in an output file.  We can then query those output files and create a report.  In my example, the report will show the total emails sent to each distribution group by month and go back 12 months.  Now without further ado, let’s get to the two scripts needed.

365_DGCounter.ps1

Note: [DateTime]::Today returns 12:00 AM of the Current Date.  Let’s assume the date is currently 3/3/2016.  The script above would return the range 3/2/2016 12:00 AM to 3/3/2016 12:00 AM.  Running this script will actually return the email counts from yesterday since today has not ended.

365_DGCounterReport.ps1

 

Oct 27

List All DNS Records with Powershell

UPDATED 6/16/2016 Thanks for the comments!

Here’s a nice quick script to list all DNS records in each zone on the DNS server(includes sub-zones):

From the DNS Server

From a Remote DNS Server

From a Remote DNS Server (Output to Tab Delimited File)

 

May 14

Search for Emails in a 365 User’s Mailbox

Overview

Often times, my posts are influenced by the questions of others in IT forums.  The other day, an IT pro asked “How can I retrieve emails a 365 user sent to a certain recipient”?  Obviously, I thought to myself, there should be a way to search a mailbox with powershell.  While writing the small script to answer their question, I realized I could do more than just search and copy with the search-mailbox cmdlet.

  • Search recoverable items.  This can be useful if a terminated employee deleted important emails that their manager needs.
  • Delete Emails.  This can useful for a scenario where a virus makes it to all user’s inbox or a disgruntled employee emails a nasty email to everyone.
  • There’s a TON of properties indexed by Exchange that you can query

Without further ado, let’s get to the script

Prerequisites

Delegate Full Access to Mailboxes

In order to search mailboxes, you’ll need to ensure your account has Full Access to each user’s mailbox.  You can do this through the 365 Exchange Admin Center, or you can give yourself full access to all user’s mailbox with the following powershell script.  Make sure you authenticate using an Exchange Admin and replace bsteinmeyer@yourdomain.onmicrosoft.com with the account you need to delegate access.

Search Mailbox For Email Sent to a Specific Email

  • jsmith@yourdomain.onmicrosoft.com = User’s mailbox you want to search
  • foo@bar.com = Email address sent to
  • bsteinmeyer@yourdomain.onmicrosoft.com = The Mailbox you want to copy the emails to
  • SearchDumpster = Search recoverable items (Emails that were deleted from the Trash)
  • *Note: If you only want to test the command and NOT copy anything, you can add the -LogOnly switch

The above will search a specified user’s mailbox for all emails sent to the specified email address.  The results and emails will be copied to the specified mailbox in the specified folder (This will most likely be your admin account).  If the folder does not exist, it will be automatically created.

Search All Mailboxes for Specific Email and Delete It

In order to delete emails with the -DeleteContent switch, you must be assigned the Discovery Management role and Mailbox Import Export role.  By default, the Mailbox Import Export role isn’t assigned to any role group, so we’ll need to create a new group and assign our user.

With that complete, we can now search everyone’s email by the subject and date and delete it.

*Note: If you only want to test the command and NOT delete anything, you can add the -LogOnly switch

Final Comments

If you’d like to further refine your queries or do more advanced queries, see the complete message properties indexed by Exchange Search below:

https://technet.microsoft.com/en-us/library/jj983804(v=exchg.150).aspx

Apr 28

Determine If A Date Is Between Two Dates

If you need to know if a date is between two dates, you can easily figure this out by treating the date as a number and doing comparisons.  This can be useful for instances where you need a script to do a different task on different months, days, years, etc.  Let’s start with our first example, which will demonstrate how the comparison works.

Example 1 – Time Matters

In this example, if the current date/time is 4/27/2015 12:01:00 PM then it would return False due to the time being outside of our defined end range.  If the date/time was 4/27/2015 12:00:00 PM then it would return True.  If you do not specify the time then it will automatically be defined as 12:00:00 AM in the $start and $end variables; it is important to understand this or else it will affect your date comparisons.  If you do not want time to be a factor, I’d suggest always defining your start time as 12:00:00 AM and your end time as 11:59:59 PM.

Example 2 – Year Does Not Matter

In this example, I’m replacing the year from any specified date and making it the current year.  This allows us to focus our comparison based on the month, day, and time.  For example, if the current date/time is 4/27/2015 12:00:00 PM and want to know if our script is running during April.  We can input the start date/time as 4/1/2016 12:00:00 AM our end date/time as 4/30/2016 11:59:59 PM and the script would return True despite the year not matching.

Conclusion

With a basic understanding of compairing dates in powershell, you can easily customize the above scripts to meet any custom needs.

Feb 18

Mail Merge with Attachment

There is not native way to add an attachment when doing an mail merge in Microsoft Office (Outlook/Word/Excel).  However, there are 3rd party apps that allow you to add attachments when doing a mail merge, but these programs usually cost $.  If you’re like me and don’t want to spend money on an application you’ll probably use once, then I came up with an alternative free solution with Powershell.  This method works similar to a Microsoft Office mail merge because it will require a data source, email template, and an Outlook profile.

Step 1 – Create Data Source

I will use a users.csv as the data source of users we want to email.  The users.csv file will look as follows:

FirstName LastName Email Username Password
Joseph smith jsmith@domain.com jsmith VideoGame01
Bill Contoso bcontoso@company.com bcontoso LilyFlower18
Jim Rufus jim.rufus@yahoo.com jrufus StuffedAnimal23

Step 2 – Create Outlook Profile to Send Mail Merge From

Now that you have your data source, you’ll need to make sure you have an Outlook profile.  This profile should be setup with the email address you wish to send the mail merge from.

Step 3 – Create Powershell Script

In the below powershell script, you’ll need to modify the following variables:

$DataSourcePath to the data source (users.csv) file created in step 1
$AttachFile – Path to the file to attach to the email
$EmailSubject – Subject of the email

In addition to modifying the above variables, you’ll need to modify $Mail.Body, which is the body of the email.  The below example is referencing data fields in users.csv for the mail merge, which you may want to modify.  These correspond as follows:

$($_.FIRSTNAME) FIRSTNAME field in users.csv

$($_.LASTNAME) LASTNAME field in users.csv

$($_.USERNAME) USERNAME field in users.csv

$($_.PASSWORD) PASSWORD field in users.csv

Special Note:  To add a new line in the body text use a backtick + n ( `n

Extra Special Note:  If you want to have the email body be HTML formatted instead of Plain Text, just modify $Mail.Body to $Mail.HTMLBody and add your HTML tags in the text.  Using the example above:

 

Step 4 – Send the Mail Merge

Open Microsoft Outlook with the profile created in step 2 (It is required for Outlook to be open in order for the powershell script to work!)  Then open Powershell, and run the powershell script in step 3.  You can confirm the emails are sending by looking in the “Sent Items” in Outlook.

Note: – If you’re using User Account Control (UAC), Outlook and Powershell must be running at the same security level.  This simply means, if you open powershell using “Run as administrator” you must open Outlook with “Run as administrator”.  Alternatively, if you open powershell normally (not elevated) you must open Outlook normally (not elevated).

Jan 06

Restart Computers by OU

 

Dec 24

Restart Computers in Sequential Order

Restarting servers is a necessary evil in a Windows administrator’s world.  Unfortunately, you cannot not always just restart servers during maintenance as they may have a service dependent on another server.  Due to this, you may need to restart your servers in sequential order.  Luckily, powershell 3.0 makes this quite easy using the restart-computer commandlet.  Please note, the restart-computer commandlet added several important parameters vs the 2.0 version, which includes the following (Good Explanation Here):

  • -Delay
  • -For
  • -Timeout
  • -Wait

The above parameters allow you to ensure a server rebooted before moving on in the script.  For a full description, see Restart-Computer on TechNet

For our script, we will use a CSV file that lists the server names and the sequence to group them for restarting (Yes we can have multiple servers in the same sequence number).  Our powershell script will then read in the the servers.csv, group the servers by their sequence number, and reboot the servers according to the sequence number group.  The below powershell script will wait until the servers have fully rebooted before moving to the next sequence number to reboot.  You may wish to modify the restart-computer parameters to suit your needs.  Additionally, you will need to modify the $filePath and $creds variables accordingly.

SERVERS.CSV

 RESTART_SEQUENTIAL_ORDER.PS1