Password Change Notification Script


Version 1.4

Recently I found myself in need of a password change notification script. What do all efficient/lazy administrators do when they need a script for any purpose? Right, I searched one online, downloaded it, checked it, suppressed any desire to fiddle with it and then scheduled it to run.

For those interested, I used the script provided by Robert Pearman over at the Technet Gallery. For Office365 compatibility check his post here

Version 2.0

But then… that annoying little Mutant-OCD gene (those of you who have it surely recognize it!) crept up on me today and I started fiddling with it anyway. I told myself the script needed to include some customizations for my company, but who am I kidding, I would lose sleep if I didn’t give in to my OCD quirks every once in a while.

In general, I changed the script to include a proper description block, parameters, cleanup of casing for variables and refactoring of some Boolean uses to shorten the if statements. The part I needed to change specifically for Silverside was the Filter for the Get-ADUser command, this allows me to filter out Admin accounts in our organization:

… -and $_.UserPrincipalName -notlike 'adm*' …

Overall the script is now easier to deploy out of the box with the use of parameters (including defaults), so long as you remember to adjust at least the $smtpServer and $from variables under the config section:

$smtpServer = "mail.yourdomain.local"
$from = "Your Company IT <>"

The script

As you no doubt found this post after efficiently searching for a free scipt online, feel free to use, I hope it saves you some time. Just remember to include the original author as described in the comments:

	Get all users with a soon to expire password and send them a reminder to do so.
	This script gets all users with a soon to expire password and sends them a reminder to do so. This script was originally created by Robert Pearman and posted on the technet gallery. Since modified by Mike Beerman to include changes specific for Silverside. Settings such as the destination SMTP server and From address can only be configured within the script.

	Optional input allowing an override to the number of days at which the script will send a reminder. Defaults to 30 days.
	Switch which determines if a seperate CSV logfile should be created. Default to false without the switch.

	Folderpath for the logfile, plain string format.
	Switch which determines if the emails should be sent to the test recipient instead of the actual users. Default to false without the switch.
.PARAMETER TestRecipient
	Optional string for setting a different recipient in testing for testing purposes. Will not be used if Testing is not included in the command or email is disabled.
.PARAMETER TestMailDisabled
	Switch for disabling email functionality.
	Send-PasswordChangeNotification.ps1 -Expire 60 -Logging -Logile "C:\Logs\PasswordChangeNotifications.csv" -Testing -TestRecipient ""
Password Change Notification Script
.NOTES Authors : Mike Beerman Company : Silverside Date : 2016-06-23 Version : 2.0 Authors : Robert Pearman (WSSMB MVP) Company : Windows Server Essentials Date : 2016-02-03 Version : 1.4 #> Param ( [ValidateRange(1,365)][int]$ExpireInDays = 30, [switch]$Logging, [string]$LogPath = "C:\Logs", [switch]$Testing, [string]$TestRecipient = "", [switch]$TestMailDisabled ) ## # Config values ## $smtpServer = "mail.yourdomain.local" $from = "Your Company IT <>" $textEncoding = [System.Text.Encoding]::UTF8 $logDate = Get-Date -Format yyyyMMdd $LogPath = ($LogPath).TrimEnd("\") $logFile = $LogPath + "\PasswordChangeNotifications.csv" ## #Initiate PowerShell session ## # Set threading $ver = $host | select Version if($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = "ReuseThread"} # Load Active Directory PowerShell snap-in Import-Module ActiveDirectory Write-Verbose ("[{0}] - AD PowerShell SnapIn loaded" -f (Get-Date -Format T)) $verbosePreference = 'Continue' # Check Logging Settings if ($Logging) { # Test Log Folder Path and create new directory if false if (!(Test-Path $LogPath)) { # Create CSV File and Headers $newItem = New-Item $LogPath -ItemType Directory Write-Verbose ("[{0}] - New folder created at [{1}]" -f (Get-Date -Format T), $LogPath) } # Test Log File Path and create new file if false if (!(Test-Path $logFile)) { # Create CSV File and Headers $newItem = New-Item $logFile -ItemType File Add-Content $logFile "Date,Name,EmailAddress,DaystoExpire,ExpiresOn,Notified" Write-Verbose ("[{0}] - New logfile created at [{1}]" -f (Get-Date -Format T), $logFile) } } # End Logging Check $DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge # Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired $users = Get-ADUser -Filter * -Properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress | ? { $_.Enabled -eq $true -and $_.PasswordNeverExpires -eq $false -and $_.passwordexpired -eq $false -and $_.UserPrincipalName -notlike 'adm*' } # Process Each User for Password Expiry foreach ($user in $users) { $name = $user.Name $emailAddress = $user.EmailAddress $passwordSetDate = $user.PasswordLastSet $PasswordPol = (Get-ADUserResultantPasswordPolicy $user) $sent = "" # Reset Sent Flag # Check for Fine Grained Password if (($PasswordPol) -ne $null) { $maxPasswordAge = ($PasswordPol).MaxPasswordAge } else { # No FGP set to Domain Default $maxPasswordAge = $DefaultmaxPasswordAge } $expiresOn = $passwordSetDate + $maxPasswordAge $today = (Get-Date) $daysToExpire = (New-TimeSpan -Start $today -End $expiresOn).Days # Set Greeting based on Number of Days to Expiry. # Check Number of Days to Expiry $messageDays = $daysToExpire if (($messageDays) -gt "1") { $messageDays = "in " + "$daysToExpire" + " days." } else { $messageDays = "today." } # Email Subject Set Here $subject="Your password will expire $messageDays" # Email Body Set Here, Note You can use HTML, including Images. $body =" Dear $name, <p> Your Password will expire $messageDays<br> To change your password on a PC press CTRL ALT Delete and choose Change Password <br> <p>Thanks, <br> Your Comany IT Administrators </P>" # If Testing Is Enabled - Email Administrator if ($Testing) { $emailAddress = $TestRecipient } # End Testing # If a user has no email address listed if (($emailAddress) -eq $null) { $emailAddress = $TestRecipient }# End No Valid Email # Send Email Message if (($daysToExpire -eq '0') -or ($daysToExpire -eq '14') -or ($daysToExpire -eq $ExpireInDays)) { $sent = "Yes" # If Logging is Enabled Log Details if ($Logging) { Add-Content $logFile "$logDate,$name,$emailAddress,$daysToExpire,$expiresOn,$sent" Write-Verbose ("[{0}] - Entry added to logfile for user [{1}]" -f (Get-Date -Format T), $user.UserPrincipalName) } # Send Email Message if not disabled by switch if (!($TestMailDisabled)) { Send-Mailmessage -SmtpServer $smtpServer -From $from -To $emailAddress -Subject $subject -Body $body -BodyAsHTML -Priority High -Encoding $textEncoding Write-Verbose ("[{0}] - Email sent to [{1}]" -f (Get-Date -Format T), $emailAddress) } } # End Send Message else { # Log Non Expiring Password $sent = "No" # If Logging is Enabled Log Details if ($Logging) { Add-Content $logFile "$logDate,$name,$emailAddress,$daysToExpire,$expiresOn,$sent" Write-Verbose ("[{0}] - Entry added to logfile for user [{1}]" -f (Get-Date -Format T), $user.UserPrincipalName) } } } # End User Processing $verbosePreference = 'SilentlyContinue' # End

The Castle, the city, and the outlands

The education sector

In consultancy we see a wide range of business sectors. From healthcare, to banking, but also the education sector. Yesterday I was providing advice on user adoption and migration strategies for a large educational institute. In attempting to explain the security architecture of Office365 and SharePoint Online I used several metaphors. To summarize what I had told him, my customer offered a metaphor of his own in return which I found to be very effective. The metaphor is one based on medieval times and castle related terms.

The medieval metaphor

In medieval times there was a rough division in security policies based on the layers:

–         Castle and keep;

–         The (walled) city surrounding the castle;

–         All the lands outside of said walls.


Within the castle security measures were strict and centrally managed. All comings and goings were tightly regulated.

A city enjoyed the safety provided by castle walls, under the conditions of central regulations by castle administration. However, the city was primarily a civilian zone with itself a decentralized management structure. Giving some freedom to areas such as commerce.

The outlying lands had no walls to protect them, yet no rules were enforced from a centralized command structure.

The castle that is SharePoint

In this case the metaphor was used to reflect a security setup for Office365 and SharePoint. In this scenario we’ve suggested creating a tightly controlled SharePoint environment, where users can mainly collaborate with each other and where functional support / key users determine if changes are needed and how to implement them. Literally, users receive access to readymade sites and libraries, but are unable to create new sites themselves, or customize content types and so on.

Yammer is the platform where users are allowed to engage more freely, creating their own groups and inviting users to those groups on their own. This would be the city with walls where users get to interact and invite users through an open gate. The centralized guidelines however state the general purpose for Yammer, without strictly monitoring or enforcing its use.

The outlands are herein represented by OneDrive for Business, mysite / personal storage specifically. Where users are allowed to bring in any content, structure it with folders to their own ideas and invite whomever them want for shared content.

By no way is OneDrive a clear representation for the outlands since OneDrive is still built on ‘land of the king’, errrr… Office 365. But for the purposes of the design this customer is going for, it fits.

True outlands would in fact be user laptops, fileshares, or in older environments SharePoint 2010 Workspaces.

Just a useful tool

The metaphor is a tool to help you illustrate complicated IT concepts, by using a common reference. Although it isn’t an exact match for a complicated structure such as Office 365, I bet administrators in medieval times would say the same about running a city state.

Use at your own behest!

Custom Domain names with Azurewebsites

I’ve only recently set up this blog and since it’s always busy at work, I don’t always have the time to sort out those ‘nice to haves’.

I’m hosting this blog using AzureWebsites, but obviously I use my own domain name. My pain? For the life of me I couldn’t figure out the magic rule to rewrite my url to the proper ‘’ hostname I’m using now.

Shame on me, Microsoft consultant couldn’t figure out a simple IIS redirect rule… In my defense, I hadn’t really taken the time to do it properly and I had in fact solved it, but in the wrong order.

To setup an AzureWebsite using a custom domain you need to configure it in several places:

  • In the Azure portal;
  • DNS records with your domain registrar;
  • In your application, in my case WordPress;
  • An IIS rule to do the actual rewrite/redirect.

Where to configure in Azure? In the Azure Portal find your Web App settings and under the Routing header click on Custom Domains and SSL. Select Bring External Domain and follow the instructions. Pay attention to using the correct type of DNS records, A records and CNAME records, depending on the correct entry.

With your domain registrar find the DNS Manager to actually enter the records. You need to set the awverify.* record with a CNAME to verify your custom domain with Azure. I went and created an A record for my domain to the AzureWebsite. Most registrars provide a warning stating you need to wait a maximum of up to 24 hours before the records are updated, in my case they were available within a minute, this may vary based on the receiving location however.

In your application add your custom domain, in the case of WordPress go to General Settings and edit your WordPress Address (URL) and WordPress Address (URL) accordingly.

Finally comes the last bit of magic, the IIS rewrite rule. Kudo’s to the author of the solution for the final makeup of the IIS rule and DevJev for nudging me in the right direction 🙂

<?xml version="1.0" encoding="UTF-8"?>
        <rule name="Disable Azure Domain" patternSyntax="Wildcard" stopProcessing="true">
          <match url="*" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
            <add input="{HTTP_HOST}" pattern="*" />
          <action type="Redirect" url="{REQUEST_URI}" redirectType="Permanent" />

So why couldn’t I figure this last bit of magic out on my own… I tried to set this up before completing the other steps. Working on this yourself? Sort your Azure, DNS and WordPress config first!


SfB: HA – SQL DAG Configuration

One of those silly mistakes…

As mentioned in my previous post, I’ve recently installed and configured a new Skype for Business landscape at my company. While implementing this I made one of those silly mistakes that cause you to spend hours looking for a solution… which is in fact one simple undocumented configuration setting.

For our SfB configuration we use a high availability SQL cluster and we’ve also set up a Database Availability Group, or DAG. Once enabled, the first field gets relabeled ‘SQL Server Availability Group Listener FQDN’, the second ‘SQL Server FQDN’.

Initially before enabling the DAG I set these values:
–         Field 1, SQL Server DAG FQDN;
–         Field 2, any given SQL Server node FQDN which will become part of the DAG.

Which looks like this:

After the installation was complete and my published topology was running I ran into all sorts of problems, the root of which was the SQL datasource being read-only.

Shortly after I determined the errors went away for a while when I switched the active node in the SQL cluster, so something had to be wrong with those settings… but what?!

The fix

So what’s the correct configuration? After the initial installation of SfB and finalizing the replication of all the databases for the SQL DAG, you need to change the SQL server FQDN back to the DAG FQDN.
–         Field 1 requires, SQL Server DAG FQDN;
–         Field 2 requires, SQL Server DAG FQDN.


Why are there two fields for the same setting? You need to install the databases onto a single SQL node once before you can switch on the DAG settings, then remember to reconfigure the SQL store in your SfB topology with the DAG FQDN. Would be nice if the Microsoft documentation was explicit on the little things like these.

One final tip, whenever you see a field that requires the FQDN, double check you actually used the FQDN before publishing your topology. Changing the FQDN on the SQL Server store after the topology has been published can be a chore…

Customers don’t have a *frakking* clue


Part 1: The origin story

The origin story

As a consultant in the IT industry it is expected to have a thorough understanding of all IT related products in one’s portfolio. When considering what these solutions are intended to provide, we all know the problems our customers face. Right? Wrong. Often enough I’ve heard colleagues in IT mention customers don’t have a clue and vice versa. What everyone should consider is that we’re both wrong unless we listen to each other!

Most often customers find me through channels related to the solutions we offer, but the very first question I ask all customers is, ‘Why do you want this product?’ The problem they describe is usually a business related concept and through the years I’ve come to understand business concepts and problems.

Recently when I came to work for my new employer, Silverside, I was asked to set up a new on premise server deployment of Skype for Business. Naturally my first question was, ‘Why? What’s the problem?’ At which my new colleague grinned, ‘Funny you should ask, we’d like to implement the business scenario Smarter Meetings .’

It might seem counter intuitive to question a customer asking to buy the product you’re selling. What I’ve discovered is a process of defining solutions without including the product. Do we still sell those same products? Yes, we do. Does this change the products themselves? No, it doesn’t. Does this help me sell more of my products and services? Not at first.

The concept

By being honest both to our customers and to ourselves we are able to find the best solution for our customers. In turn our customers value our opinion even more and are more likely to return to us for future services. Seeking a partnership like this can be challenging at first, as steering a customer away from our services does not directly support our business. In the long run however I’ve built more lasting and rewarding partnerships in this manner than any other.

Back to our concrete example of Smarter Meetings. My current project involves getting all our colleagues to stop and think about the way we communicate together. Am I implementing Skype for Business as a part of it? Yes, I might be. The first question when announcing to implement Skype for Business however boiled down to this, ‘A new product is not going to change the way we do things, why change a winning team?’ When we announced that we’re implementing a smarter way of having our meetings, the first question was one of pure interest, ‘How would we do that?’

This isn’t a new way of thinking necessarily, yet forcing both ourselves and our customers to work toward a common goal and wanting to find a solution together is. Key points to keep in mind in this trend are,

– Nothing is sacred, be open to new ideas. This includes you, the consultant!
– Find common goals, truly want to achieve them.
– Agree on how to get there.
– Offer your product if it fits, but don’t be afraid to offer alternatives if it doesn’t.

Skype for Business

So why are we using Skype for Business to promote the concept of Smarter Meetings at Silverside? As a company we used to be addicted to phones, emails and paper notes. We traveled the world, literally spending 8 hours a day flying or driving to common locations simply to meet face to face. Now we’ve set out to change that mindset by tackling the following concepts:

– By far the behavior most in need of change is our use of phones. Pointing out monthly phone bills racking up to €500, – a month was a real eye opener for some of our colleagues.
– Most of us are familiar with the use of paper, drawing out what you’re trying to say is sometimes just that much more comfortable. Most assume there is no digital equivalent, but have you ever used a whiteboard in a Skype meeting?
– In person meetings provide more feedback about the other person in the room, body language, micro expressions, etc. However, we’ve committed to using a Microsoft Surface Hub together with high definition cameras to ensure we have a virtual presence with which we can interact in a natural way using touch.

But what are we really using Skype for Business for? To jog our customers (and colleagues) out of a rusty paradigm where the best solution is to keep working as we have been for years. Stop. Think about the way you’re doing things today. Is there another way of doing these things that might be better and/or cheaper? Don’t hesitate and choose to find this path together with your customers.


IT consultants should truly listen to the customer and try to find the actual problem. We’re literally getting paid for it so:

– Take 5 minutes to listen silently, nod every so often, take notes.
– Summarize what you’ve just heard explicitly and ask for confirmation.
– Be patient and give the customer the idea they’re money is being well spent.

The morale of this story is most IT consultants think they know better than their customers, while customers think consultants aren’t really listening to what they’re saying. A lot of brilliant IT techies could become brilliant consultant if they want to.

This is the first in a series where I’ll be shedding some light on the non-technical aspects of IT consultancy, the part of our industry that can usually do with a virtual prod in the rear towards the future. Stay tuned for more stories from @BearTheHammer