I understand domain-joined computers have machine accounts in AD and these accounts have passwords that expire (apparently every 30 days by default) and those passwords are automatically changed without user intervention.

Given that this is known to cause issues when restoring snapshots of domain-joined virtual machines, is it possible to query the domain-joined computer or AD to determine when the machine account password is next scheduled to be changed?

  • What is the functional level of your AD domain? – MDMarra Jun 9 '10 at 10:35
  • The domain functional level is "Windows Server 2008 R2". – Jason Stangroome Jun 10 '10 at 2:29
  • We should all be so lucky. – MDMarra Jun 11 '10 at 0:41

It is possible to query the domain for this, the script below will tell you when a particular machine's domain password was last reset.

'Replace "yourdom.com" with your domain name.
DomainName = "yourdom.com"

querymachine = UCase(inputbox("Enter full machine name"))
lngBias = 2

'****************Setup Log file******************************************************

Set fso = CreateObject("Scripting.FileSystemObject")
'The 8 in this line will append to an existing file, replace with a 2 to override
set txtStream = fso.OpenTextFile("System.txt", 8, True)
txtStream.WriteLine "Ran on " & Date & " *******************************"

'****************Setup ADSI connection and populate ADSI Collection******************

Set objADOconnADSI = CreateObject("ADODB.Connection")
objADOconnADSI.Open "Provider=ADsDSOObject;"
Set objCommandADSI = CreateObject("ADODB.Command")
objCommandADSI.ActiveConnection = objADOconnADSI
'there is a 1000 object default if these next 2 lines are omited.
objCommandADSI.Properties("Size Limit")= 100000
objCommandADSI.Properties("Page Size")= 100000
objCommandADSI.Properties("Sort on") = "sAMAccountName"
objCommandADSI.CommandText = "<LDAP://" & DomainName & ">;(objectClass=computer);sAMAccountName,pwdLastSet,name,distinguishedname,operatingSystem;subtree"
Set objRSADSI = objCommandADSI.Execute

'Loop through record set and compare machine name*************************************

do while NOT objRSADSI.EOF
    if not isnull(objRSADSI.Fields("distinguishedname")) and objRSADSI.Fields("distinguishedname") <> "" then
    objDate = objRSADSI.Fields("PwdLastSet")
    'Go to function to make sense of the PwdLastSet value from AD for the machine account.
    dtmPwdLastSet = Integer8Date(objDate, lngBias)
    'calculate the current age of the password.
    DiffADate = DateDiff("d", dtmPwdLastSet, Now)

    'Is the machine the one we're looking for?
        if UCase(objRSADSI.Fields("name")) = querymachine then
        txtStream.WriteLine objRSADSI.Fields("name") & ";" & dtmPwdLastSet & ";" & DiffADate & ";" & objRSADSI.Fields("operatingSystem") 
        wscript.echo objRSADSI.Fields("name") & ", Last set: " & dtmPwdLastSet & ", Days since last change: " & DiffADate
        end if
    end if
wscript.echo "Done!"

Function Integer8Date(objDate, lngBias)
' Function to convert Integer8 (64-bit) value to a date, adjusted for
' local time zone bias.
Dim lngAdjust, lngDate, lngHigh, lngLow
lngAdjust = lngBias
lngHigh = objDate.HighPart
lngLow = objdate.LowPart
' Account for bug in IADslargeInteger property methods.
If lngLow < 0 Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0) Then
lngAdjust = 0
End If
lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000 - lngAdjust) / 1440
Integer8Date = CDate(lngDate)
End Function 

(I'd love to give credit for the above script but it's been handed around from person to person and modified in various ways, I have no idea where it originally came from)

Save this as something like MachinePasswordDate.vbs, doubleclicking the file in Windows should pop up a box you can put a machine name into, which should then query the domain and tell you when that machine's password was last changed.

If you're regularly restoring virtual machine snapshots it might be worth having a look at the security policies on those machines before you save off an image. You can change the machine password reset interval up to 999 days quite easily, assuming your domain GPOs won't override it, and your security policy allows this sort of thing:

Click Start, click Run, type Gpedit.msc, and then press ENTER.

Expand Local Computer Policy, Computer Configuration, expand Windows Settings, expand Security Settings, expand Local Policies, and then expand Security Options.

Configure the following settings:

  • Domain Member: Disable machine account password changes (Enabled)

  • Domain Member: Maximum machine account password age (999 days)

  • Domain Controller: Refuse machine account password changes (Enabled)

  • From this I've discovered I can find the date of PwdLastSet by enabling View, Advanced Features in the AD Users and Computers management console then looking for PwdLastSet in the Attribute Editor tab of a computer account's property window. Also, from PowerShell, with the Quest AD Snapin, the following works too: Get-QADComputer -IncludedProperties PwdLastSet | Select Name, PwdLastSet – Jason Stangroome Jun 10 '10 at 2:36

On the DC or any computer with RSAT you can run dsquery computer -name ComputerName -stalepwd x

ComputerName is the name of the computer you want to check
x is the number of days since the password is last set.

If the password hasn't been set since x number of days, it will return the name and containers of the computer. If the password has been set within the last x days, it will return nothing.

  • According to the dsquery documentation, the -stalepwd argument is the number of days, not weeks, so it is quite accurate but does require a divide and conquer approach to determine the current value. technet.microsoft.com/en-us/library/cc730720(WS.10).aspx – Jason Stangroome Jun 10 '10 at 2:25
  • @Jason - You're right. I was thinking of -inactive, which is measured in weeks. – MDMarra Jun 10 '10 at 2:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.