We all have that set of users that either mainly use a mobile device for email access or possibly a client running a non Microsoft Windows OS as their main workstation.

Those users don’t get that friendly reminder to change their password that comes with logging onto a Windows OS near to their domain password expiration date, and this usually ends up with passwords expiring and phone calls to the IT Helpdesk to change them.

Wouldn’t it be much simpler if that group of users were emailed near to the time of password expiration, allowing the user to logon to OWA and change their password in their own time, negating the need for calls to the IT Helpdesk. In an attempt to reduce some of those calls to our own IT Helpdesk I wrote a PowerShell script to email members of a security group every day when their domain password was due to expire in 10 days or less.

Thanks to @AdamFowler_IT for a good bit of the code. See his post here.


#################################################
# Please Configure the following variables….
# expireindays1 + 2 = At what count of days left on a password do you want a notification?
$smtpServer=”mail.org.ie”
$expireindays1 = 10
$expireindays2 = 1
$from = “ITHelpdesk@org.ie”
#################################################
cls
#Get Users From AD who are enabled
Import-Module ActiveDirectory

$GroupMembers = Get-ADGroupMember -Server domain.org.ie “Mobile Users” | where {$_.objectclass-eq “user”} | Select SamAccountName | Out-File c:\temp\users.txt
$a, ${c:\temp\users.txt} = Get-Content c:\temp\users.txt
$a, ${c:\temp\users.txt} = Get-Content c:\temp\users.txt
$a, ${c:\temp\users.txt} = Get-Content c:\temp\users.txt

$GroupMembers = Get-Content C:\temp\users.txt
$GroupMembers | ForEach {$_.TrimEnd()} | Set-Content C:\temp\users.txt

(gc C:\temp\users.txt) | ? {$_.trim() -ne "" } | set-content C:\temp\users.txt

$GroupMembers = Get-Content C:\temp\users.txt

foreach ($user in $GroupMembers)
{
$CheckForNullPasswordSetDate = (get-aduser -Server domain.org.ie $user -properties passwordlastset | foreach { $_.PasswordLastSet })
if ($CheckForNullPasswordSetDate -ne $null)
{
$Name = Get-ADUser -Server domain.org.ie $user -Properties *
$emailaddress = $name.emailaddress
$givenname = $name.GivenName
$passwordSetDate = (get-aduser -Server domain.org.ie $user -properties passwordlastset | foreach { $_.PasswordLastSet })
$PasswordPol = (Get-AduserResultantPasswordPolicy -Server domain.org.ie $name)

# Check for Fine Grained Password
if (($PasswordPol) -ne $null)
{
$maxPasswordAge = ($PasswordPol).MaxPasswordAge
}

else
{
$maxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
}

$expireson = $passwordsetdate + $maxPasswordAge
$today = (get-date)
$daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days

if ($daystoexpire -le 0)
{
$subject=”IT Helpdesk Notification - Your domain password has expired”
}
else
{
$subject=”IT Helpdesk Notification - Your domain password will expire in $daystoExpire days”
}

if ($daystoexpire -le 0)
{
$subject=”IT Helpdesk Notification - Your domain password has expired”
}
else
{
$subject=”IT Helpdesk Notification - Your domain password will expire in $daystoExpire days”
}

if ($daystoexpire -le 0)
{
$body =”
Dear $givenname,

Your domain account password has expired.
To change your password please contact the
IT Helpdesk.

Regards,

IT Helpdesk


}
else
{
$body =”
Dear $givenname,

Your domain account password will expire in $daystoexpire day(s).
To change your password please logon to OWA and choose OPTIONS and CHANGE PASSWORD.

Regards,

IT Helpdesk


}

if ($daystoexpire -le 10)
{
Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -cc "ithelpdesk@org.ie" -subject $subject -body $body -bodyasHTML -priority High
}
}
else
{
Write-Warning "Last Password Set is null for $user"
}
}

Recently I had write a script that would be outputting a log file. As this script was going to be run on a schedule and the logs dumped to a directory I needed to make sure that each log would have a unique name.

To achieve this I created a $timestamp variable that I’d append to the end of the filename.

$timestamp = Get-Date -Format o | foreach {$_ -replace “:”, “.”}
$LogName = “AdminLog_$timestamp.log”

The end result is a filename called AdminLog_2014-08-13T22.45.28.9777185+01.00.log

Hope this might be of use to someone.

S

Quick update: Julian Siara (https://twitter.com/yula_ro) suggested the use of the -Format u instead of -Format -o so the filename is more readable. Must say I agree.

Code changed to:
$timestamp = Get-Date -Format u | foreach {$_ -replace “:”, “.”}
$timestamp = $timestamp | foreach {$_ -replace ” “, “_”}
$LogName = “AdminLog_$timestamp.log”

This will now give the filename of AdminLog_2014-08-14_10.50.28Z.log

When building images before I used to do fairly thick ones, now I make them as thin as reasonably possible. My current Windows 8.1 Update image contains the following;

Windows 8.1 fully patched at time of build
Office 2013 fully patched at time of build
Read & Write 10 (This didn’t play at all well with being deployed as it required each install to be activated post deployment. I baked it into the image and activated before capture and it’s working fine)
MS Visual C++ packages

The other applications we require are layered on at the time of deployment. This means we don’t have to change our image if we’re looking to deploy a new version of a certain application.

Applications we layer on top of the image;

Adobe Reader XI
EndNote X7
Google Chrome
SPSS 20
Java
Minitab
Mathamatica
F-Secure Antivirus for Workstation

For the most part these applications go on fine. Unfortunately with Minitab 16.2.4 there is a known issue with the licencing side of things where a message is displayed on first run. Now Minitab are aware of this and are working with MS to sort it out, and that’s fair enough.

Capture

I don’t have time right now for MS to address this so decided to take a look at what was going on myself… I’m noisy like that!

Like a large number of IT Pros, I do a lot of my snooping around with the Sysinternal tools. So I kicked off Process Monitor – Procmon.exe to see what was happening when I checked the “Don’t show this message again” box and clicked on CLOSE.

Working back from when I made the change and launched the application successfully a couple of things were immediately  obvious.

Right before the application was launched I could see that a registry key was created and settings a value.

Capture

A quick right click and Jump To brought up regedit in the desired location.

Capture

OK, this is good stuff. Quickly exported this key for reference later. Deleted the key and launched Minitab again to see if I was prompted… No joy. The key above was created automatically and the application launched without me being prompted. So, something else must have been created in the registry along with this key.

Also found that pcaui.exe was creating a registry key in much the same place as the one above.

Capture

Capture

Exported this, deleted the keys and launched Minitab again. WOOHOO! I was being prompted again. Cancelled this so no changes were made, imported the above keys and launched Minitab without being prompted… BINGO!

These keys will be added to the user using Group Policy Preferences so problem solved.

Hope this helps someone.

S

I’ve come across a Windows error a few times now when doing OS upgrades from WindowsXP to Windows7 with Configuration Manager.

The error reads “The Computer Restarted unexpectedly or encountered an encountered an unexpected error”. When you reboot the same messages comes up and you’re stuck in this error message loop.

image

To get our of the loop, boot up with everyone’s favourite recovery took kit, for me it’s got to be DaRT (thanks goodness for Software Assurance!).

Start Regedit and change the following registry key

HKEYLOCAL_MACHINE\SYSTEM\SETUP\STATUS\ChildCompletion

Now change the value of SETUP.EXE from 1 to 3 and reboot. You’ll get prompted to set the computer name and add a user and the Configuration Manager upgrade will proceed. At the end you will need to join the machine to the domain, but for me this is a fairly small concession as the solution before was to start the client OSD from scratch.

What I’d like to do next is have DaRT available as a PXE offering and use remote desktop to connect and there would be no need to have someone from our Helpdesk to call out to complete the call.

Hope that helps

S

Got a error when installing the Admin Console part of the KB2910552 Hotfix for Configuration Manager 2012 R2.

The install logs showed the following errors;

“System Center 2012 R2 Configuration Manager Console — Error 1706. An installation package for the product System Center 2012 R2 Configuration Manager Console cannot be found”

“System Center 2012 R2 Configuration Manager Console – Update ‘ConfigMgr2012AdminUI-R2-KB2910552-I386’ could not be installed. Error Code 1603”

Capture

Capture1

As you can see, the installer is unable to find the AdminConsole.msi file. This left me head scathing for a few minutes until I remembered that when installing the console I did so by mounting the Configuration Manager ISO, browsing to the folder and installing.

So just right clicked on the ISO again and mounted it, then installed the hotfix again and all was good.

Our users have admin rights… don’t go there… I know! One of the issues with this is that the user is in the position where they can save their data anywhere (and they do – one person had a over 70 folders off the root of the C drive!). This in turn, makes migrations from Windows XP to a newer OS a challenge. Due to the significant risk of loss of data, I’ve decided to take a WIM backup of the system before the new OS is deployed.

It’s not a decision I came to lightly as there are considerable overheads with doing this, to name a few obvious one;

1. Adds considerable time onto an OS upgrade
2. Some images are over 100GB in size
3. Decent bandwidth needed for moving that much data around

When running initial tests on VMs the WIM was created without any problems. In the real world though a problem manifested that caused ZTIBackup.wsf to fail in the creation of the WIM.

Capture

After much scratching of collective heads (namely Alan Doran https://twitter.com/AlanDoran and Peter Cashen https://twitter.com/petercashen) we sorted the issue. Alan suggested to add the /VERIFY switch to the ImageX command. Knowing that the /VERIFY was going to add a considerable amount of time to the creating of the WIM I decided I’d also change the compression from the default setting of maximum to fast – /COMPRESS FAST.

After taking a whopping 6.5 hours to create the image, it did so successfully. The next test was to remove the /VERIFY switch to see if I could reproduce a successful image creation. Thankfully the image was created successfully, so it looks like moving from the default to /COMPRESS FAST sorted the issue. So now we can now plough on with Windows XP migrations… Happy Days!

ImageX Command-Line Options : http://msdn.microsoft.com/en-us/library/cc749447(v=WS.10).aspx

All the best,
S

Recently our Helpdesk took in a machine that was to be upgraded from Windows XP to Windows 7. For some reason the Configuration Manager Agent wasn’t installed so I asked for it to be manually installed but the agent bombed out.

Took a quick look at the install logs and saw the following;

“File C:\Windows\ccmsetup\MicrosoftPolicyPlatformSetup.msi installation failed. Error text: ExitCode: 1603”

A quick look on Google pointed in the direction of a WMI issue… on a 5 year old Windows XP box, surly not!

Fortunately for me, rebuilding the WMI repository is fairly well documented on the old Interweb, and I came across a batch script on the Ask the Performance Team Blog;

http://blogs.technet.com/b/askperf/archive/2009/04/13/wmi-rebuilding-the-wmi-repository.aspx

Just copied the following into notepad, saved as ResetWMI.bat and ran it.

@echo off
sc config winmgmt start= disabled
net stop winmgmt /y
%systemdrive%
cd %windir%\system32\wbem
for /f %%s in (‘dir /b *.dll’) do regsvr32 /s %%s
wmiprvse /regserver
winmgmt /regserver
sc config winmgmt start= auto
net start winmgmt
for /f %%s in (‘dir /s /b *.mof *.mfl’) do mofcomp %%s

After it was finished I tried a manual install of the Configuration Manager Agent again and everything went perfectly. Once the agent was installed the Windows XP Upgrade Task Sequence ran and the machine was upgraded without any other user intervention.

All the best,

S

If you’re doing application deployment with Configuration Manager 2012, you’ll know what it’s fairly early to point it at an MSI, click next a few times taking the defaults when creating your application and deploy it to a collection. Easy.

Now, that’s all well and good for some applications…then you start to look at the likes of Acrobat Reader. With this you encounter quarterly update and out of band security updates.

What I like to do in these cases is use the supersedence feature. This will allow you to upgrade or uninstall the old version and install the latest one and keeping your client estate up-to-date.

In the example here, you can see that I’ve got Adobe Reader 11.0.03 superseded by Adobe Reader 11.0.05.

ConfigMgr - Supersedence

If I had chosen the defaults for creating the Adobe Reader 11.0.03, the application detection rule would have been as follows;

ConfigMgr_Detection

Then when the next quarterly update is released, you create your application taking the defaults and use supersedence to upgrade 11.0.03 to 11.0.05.

Now this is where things go wrong for you because the MSI product code for 11.0.05 is the same as 11.0.03. Now you have your clients stuck in a loop of detecting 11.0.03 being installed and installing the 11.0.05 application. Then a check is done and the MSI code for 11.0.03 is detected so it’s upgraded to 11.0.05 and so on.

This is why for the likes of Adobe Reader I change the default detection rule from the MSI installer code to using file existence and version number. Below you can see I’m checking for the presence of the AcroRd32.exe file and the version number being 11.0.3.37.

ConfigMgr_Detection_AR01

For the next quarterly update 11.0.05, we use the same detection method;

ConfigMgr_Detection_AR02

This allows us to avoid a loop situation as Acrobat Reader 11.0.03 has a different file version than Acrobat Reader  11.0.05.

Hope this helps.

S

One of the services I provide is offering devolved IT staff the ability to use our OS Deployment Service. These are local IT people in departments around the University but they are not part of the central IT Services department.

Up until I saw a recent post from Mikael Nystrom – https://twitter.com/mikael_nystrom/ on how to use PowerShell to output the MDT Monitor tab data to a webpage I had no way of providing these users with a view of how their OS Deployments were going.

http://deploymentbunny.com/2013/12/09/nice-to-know-dumping-mdt-monitor-data-to-a-webpage-using-powershell/

This meant that if a cluster of machines were being deployed, the user would have to go back and forth to check to see if they had finished. Or if a single machine was being done in a user’s office, they may have to sit there and watch the progress bar until the end. Not a very appealing situation!

This post is going to cover how I implemented Mikael’s script to our environment and made the interface a bit prettier for the end user. I like a bit of branding!

The default page, while being functional, isn’t the most appealing for giving to our service users so I wanted to give it a bit of a makeover.

MDT_DefaultWeb

Here is the full code that I’ve used;

MDT_UCCWeb_Code

First I added in our University logo and some welcome text. This needs to be put into an array so you can then have that array outputted in the –Body element of the ConvertTo-HTML cmdlet as it didn’t like the <img src=> tag.

I’ve also added a meta tag in to have the page refresh every minute, this is because I’ve a scheduled task running the script every 5 minutes to regenerate the webpage. This means there is no need for the end user to press F5 for up to date information.

MDT_UCCWeb_Code_snip1

The second change I made was just to have some text underneath the table.

MDT_UCCWeb_Code_snip2

So with a few small changes you can brand the page to suit your needs. Mine ended up looking like this.

MDT_UCCWeb

Hope someone finds this useful.

Update

Johan Arwidmark – https://twitter.com/jarwidmark has details of how to set up Configuration Manager with MDT Monitoring, works a treat. Now you can have both your MDT and Configuration Manger OS Deployments monitored from a single pane of glass.

http://www.deploymentresearch.com/Research/tabid/62/EntryId/131/Adding-DaRT-8-1-from-MDOP-2013-R2-to-ConfigMgr-2012-R2.aspx

You can see here, the highlighted deployment is one from Configmgr.

MDT_UCCWeb_CMg

all the best,

S

UPDATE:

A fellow IT Pro Damon Johns (https://twitter.com/DamonAJohns) reached out to say the page wasn’t adding in the -Title variable into the webpage when it was converted to HTML. A quick look at my own page confirmed it wasn’t working for me either.

When the script is run the variable $title has the correct content, I’m just not sure why Convertto-HTML isn’t picking up it. What I do know is that the -Head $Head element is working… 🙂

What I’ve done to get the title passed into the final HTML code is this;

$Head = “<title>”
$Head = $Head + “IT Services OS Deployment Monitor”
$Head = $Head + “</title>”
$Head = $Head + “<style>”
$Head = $Head + “BODY{background-color:white;}”
$Head = $Head + “TABLE{border-width: 3px;border-style: solid;border-color: black;border-collapse: collapse;}”
$Head = $Head + “TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#ffffff}”
$Head = $Head + “TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black}”
$Head = $Head + “</style>”

When you look at the outputted HTML code, yip the element is present, albeit kinda snuck in the back door, but there none the less.

<head>
<title>IT Services OS Deployment Monitor</title><style>BODY{background-color:white;}TABLE{border-width: 3px;border-style: solid;border-color: black;border-collapse: collapse;}TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#ffffff}TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black}</style>
</head>

Design a site like this with WordPress.com
Get started