How to: Search for the Password Change History of Users
The password change history is stored in three Windows Management Instrumentation (WMI) classes: MIIS_PasswordChangeHistorySource Class, MIIS_PasswordChangeHistoryTarget Class, and MIIS_PasswordChangeQueue Class.
The following Microsoft Visual Basic Scripting Edition (VBScript) example searches for the password change history for a user. To use the classes in this script, you must be logged on as a member of the MIISAdmin or MIISBrowse security group.
Option Explicit
On Error resume next
Dim MIIS_AccountName
Dim MIIS_Password
Dim MIIS_MachineName
Dim Service
Dim objLocator
Dim WMIQuery
Dim CsObjects
Dim CsObject
Dim CsObjCount
Dim SearchDomain
Dim SearchUser
Dim UserCsGuid
Dim Changes
Dim DetailCount
Dim PasswordChange
Dim BufferLen
Dim MAGuid
Dim MAName
Dim Targets
Dim Target
Dim TargetCount
Dim NumTargets
Dim QueueCount
Dim QueueEntry
Dim PasswordQueue
Dim NumQueue
Dim MVQuery
Dim ConnectorsCount
Dim RelatedCSObjects
Dim ConnectedCSObjects
Const MIIS_WMI_Namespace = "root\MicrosoftIdentityIntegrationServer"
Const PktPrivacy = 6
Const wbemAuthenticationLevelPkt= 6
Const strPad = " :"
Const strLine = "---------------------------------"
Const strQLine = " --------------------------------"
Const strTLine = " -------------------------------"
MAGuid = array()
MAName = array()
BufferLen = Len(strPad)
' Check that you have the correct number of options.
If WScript.Arguments.Count <> 2 and WScript.Arguments.Count <> 5 Then
If InStr(1,Wscript.Arguments.Item(0),"?",vbTextCompare) = 0 Then WScript.Echo _
"Invalid arguments detected" & vbcrlf
Usage
WScript.Quit(1)
End If
SearchDomain = WScript.Arguments.Item(0)
SearchUser = WScript.Arguments.Item(1)
If WScript.Arguments.Count = 5 Then
MIIS_AccountName = WScript.Arguments.Item(2)
MIIS_Password = WScript.Arguments.Item(3)
MIIS_MachineName = WScript.Arguments.Item(4)
End If
If Len(MIIS_AccountName) = 0 Then
Set Service = GetObject("WinMgmts:{authenticationLevel=PktPrivacy}!" & MIIS_WMI_Namespace)
Else
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
objLocator.Security_.AuthenticationLevel = wbemAuthenticationLevelPkt
Set Service = objLocator.ConnectServer(MIIS_MachineName , MIIS_WMI_Namespace, _
MIIS_AccountName, MIIS_Password)
End If
If Err.Number <> 0 Then ErrorHandler("ERROR: " & Err.Description)
FindCSObject SearchDomain, SearchUser
CsObjCount = CsObjects.Count
If CsObjCount = 0 and Err.Number = 0 Then ErrorHandler(vbCrLf & _
"Unable to locate " & SearchDomain & "\" & SearchUser & ".")
If CsObjCount = 0 and Err.Number <> 0 Then ErrorHandler(vbCrLf & _
"ACTION: Verify that your user account is in the MIIS_Browse NT Security Group."_
& vbCrLf & vbCrLf & "Error Number : " & Err.Number & vbCrLf & "Error Description: "_
& Err.Description )
If IsNull(CSObject.MvGuid) Then
ErrorHandler(vbCrLf & "The connector space object is a disconnector.")
WScript.Quit(0)
End If
UserCsGuid = CsObject.Guid
WMIQuery = "SELECT * FROM MIIS_PasswordChangeHistorySource WHERE " & _
"CsGuid = '" & UserCsGuid & "'"
Set Changes = Service.ExecQuery (WMIQuery)
Wscript.Echo ""
WScript.Echo FormatOutput("Account") & CsObject.Account
WScript.Echo FormatOutput("Domain") & CsObject.Domain
WScript.Echo FormatOutput("MA Name") & CsObject.MaName
WScript.Echo FormatOutput("MA Partition") & CsObject.PartitionName
WScript.Echo FormatOutput("MA Guid") & CsObject.MaGuid
WScript.Echo FormatOutput("CS Guid") & UserCsGuid
WScript.Echo FormatOutput("Password History Source Entries") & Changes.Count
MVQuery = "Select * from MIIS_CSObject where mvguid='" & CSObject.MVGUID & "'"
Set RelatedCSObjects = Service.ExecQuery(MVQuery)
WScript.Echo FormatOutput("Number of Connectors") & RelatedCSObjects.Count
ConnectorsCount = 0
Wscript.echo vbcrlf & strLine
Wscript.echo FormatOutput("WMI Password Change/Set History")
Wscript.echo strLine
For Each ConnectedCSObjects in RelatedCsObjects
ConnectorsCount = ConnectorsCount + 1
DisplayConnectorValues
Next
WScript.Echo ""
DetailCount = 0
For Each PasswordChange in Changes
DetailCount = DetailCount +1
QueueCount = 0
TargetCount = 0
WScript.Echo vbcrlf & strLine
WScript.Echo FormatOutput(" Password History Source Entry " & DetailCount)
WScript.Echo strLine & vbcrlf
DisplayPwdSrcValues
WMIQuery = "Select * from MIIS_PasswordChangeQueue WHERE " & _
"ReferenceGuid = '" & PasswordChange.ReferenceGuid & "'"
Set PasswordQueue = Service.ExecQuery (WMIQuery)
WMIQuery = "Select * from MIIS_PasswordChangeHistoryTarget WHERE " & _
"ReferenceGuid = '" & PasswordChange.ReferenceGuid & "'"
Set Targets = Service.ExecQuery (WMIQuery)
PrintQueueTitle
NumQueue = PasswordQueue.count
NumTargets = Targets.count
WScript.Echo FormatOutput(" Password Target Entries") & NumTargets
WScript.Echo
For Each Target in Targets
TargetCount=TargetCount+1
DisplayPwdTargetValues
Next
For Each QueueEntry in PasswordQueue
QueueCount = QueueCount + 1
Wscript.echo vbcrlf & strLine
Wscript.echo FormatOutput(" Password Queue Entries")
Wscript.echo strLine
DisplayPwdQueueValues
Next
Next
Sub PrintQueueTitle
WScript.Echo FormatOutput(" Password Queue Entries") & PasswordQueue.Count
End Sub
Sub FindCSObject(DomainName, UserName)
On Error Resume Next
WMIQuery = "SELECT * FROM MIIS_CSObject WHERE DOMAIN='" & DomainName & _
"' and ACCOUNT='" & UserName & "'"
Set CsObjects = Service.ExecQuery(WMIQuery)
'Move to the first object in the CsObjects Collection and Exit
For Each CsObject in CsObjects
Exit For
Next
End Sub
Sub DisplayPwdSrcValues
WScript.Echo FormatOutput(" DN") & PasswordChange.DN
WScript.Echo FormatOutput(" Source Server") & PasswordChange.SourceServer
WScript.Echo FormatOutput(" Source Change Time") & PasswordChange.SourceChangeTime
WScript.Echo FormatOutput(" <tla rid="fim_sync_short"/> Receive Time") & PasswordChange.MIISReceiveTime
WScript.Echo FormatOutput(" Tracking Guid") & PasswordChange.GUID
WScript.Echo FormatOutput(" Reference Guid") & PasswordChange.ReferenceGuid
WScript.Echo FormatOutput(" MA Name") & GetMANameFromGuid(PasswordChange.MAGUID)
WScript.Echo FormatOutput(" MA Guid") & PasswordChange.MAGUID
WScript.Echo FormatOutput(" CS Guid") & PasswordChange.CsGUID
WScript.Echo FormatOutput(" Return Code") & PasswordChange.ReturnCode
End Sub
Sub DisplayPwdTargetValues
Wscript.Echo strTLine
WScript.Echo FormatOutput(" : Target Entry " & TargetCount & " of " & NumTargets)
Wscript.Echo strTLine
WScript.Echo FormatOutput(" DN") & Target.DN
WScript.Echo FormatOutput(" Target Guid") & Target.Guid
Wscript.Echo FormatOutput(" Reference Guid") & Target.ReferenceGuid
WScript.Echo FormatOutput(" Retry Count") & Target.RetryCount
WScript.Echo FormatOutput(" MA Name") & GetMANameFromGuid(Target.MAGUID)
WScript.Echo FormatOutput(" MA Guid") & Target.MAGUID
WScript.Echo FormatOutput(" CS Guid") & Target.CsGUID
WScript.Echo FormatOutput(" RetryLimit") & Target.ReachedRetryLimit
WScript.Echo FormatOutput(" <tla rid="fim_sync_short"/> Time Received") & Target.MIISReceiveTime
Wscript.Echo FormatOutput(" Last Attempt Time") & Target.LastAttemptTime
WScript.Echo FormatOutput(" Final Return Code") & Target.FinalReturnCode
WScript.Echo FormatOutput(" Attempt Details") & vbCrLf & Target.AttemptDetails
WScript.Echo
End Sub
Sub DisplayPwdQueueValues
If QueueCount > 1 Then Wscript.Echo strTLine
WScript.Echo FormatOutput(" : Queue Entry " & QueueCount & " of " & NumQueue)
Wscript.Echo strTLine
WScript.Echo FormatOutput(" DN") & QueueEntry.DN
WScript.Echo FormatOutput(" Queue Guid") & QueueEntry.Guid
Wscript.Echo FormatOutput(" Reference Guid") & QueueEntry.ReferenceGuid
WScript.Echo FormatOutput(" Retry Count") & QueueEntry.RetryCount
WScript.Echo FormatOutput(" MA Name") & GetMANameFromGuid(QueueEntry.MAGUID)
WScript.Echo FormatOutput(" MA Guid") & QueueEntry.MAGUID
WScript.Echo FormatOutput(" CS Guid") & QueueEntry.CsGUID
WScript.Echo FormatOutput(" Originating CS Guid") & QueueEntry.OriginatingCSGuid
Wscript.Echo FormatOutput(" Last Attempt Time") & QueueEntry.LastAttemptTime
WScript.Echo FormatOutput(" Last Attempt Return Code") & QueueEntry.LastAttemptReturnCode
WScript.Echo FormatOutput(" <tla rid="fim_sync_short"/> Time Received") & QueueEntry.MIISReceiveTime
WScript.Echo FormatOutput(" Attempt Details") & vbCrLf & QueueEntry.AttemptDetails
WScript.Echo
End Sub
Sub DisplayConnectorValues
WScript.Echo FormatOutput(" Connector Object " & ConnectorsCount)
Wscript.Echo strTLine
If Len(ConnectedCsObjects.Account) > 0 Then
WScript.Echo FormatOutput(" Account") & ConnectedCsObjects.Account
Else
WScript.Echo FormatOutput(" Account") & "N/A"
End If
If Len(ConnectedCsObjects.Domain) > 0 Then
WScript.Echo FormatOutput(" Domain") & ConnectedCsObjects.Domain
Else
WScript.Echo FormatOutput(" Domain") & "N/A"
End If
WScript.Echo FormatOutput(" MA Name") & ConnectedCsObjects.MaName
WScript.Echo FormatOutput(" MA Partition") & ConnectedCsObjects.PartitionName
WScript.Echo FormatOutput(" MA Guid") & ConnectedCsObjects.MaGuid
WScript.Echo FormatOutput(" CS Guid") & ConnectedCsObjects.Guid
If Len(ConnectedCsObjects.PasswordChangeHistory) > 0 Then
WScript.Echo FormatOutput(" PasswordChangeHistory") & vbCrLf & _
ConnectedCSObjects.PasswordChangeHistory & vbcrlf
Else
WScript.Echo FormatOutput(" PasswordChangeHistory") & "None" & vbcrlf
End If
MADataAdd ConnectedCsObjects.MaName, ConnectedCsObjects.MAGuid
End Sub
Sub MADataAdd(CurrentMAName, CurrentMAGuid)
Dim Size
Size = Ubound(MAGuid) + 1
ReDim Preserve MAName(Size)
ReDim Preserve MAGuid(Size)
MAName(Size) = CurrentMAName
MAGuid(Size) = CurrentMAGuid
End Sub
Function GetMANameFromGuid(CurrentMAGuid)
Dim i
GetMANameFromGuid = "Unknown"
For i = 0 To Ubound(MAGuid)
If MAGuid(i) = CurrentMAGuid Then
GetMANameFromGuid = MAName(i)
Exit For
End If
Next
End Function
Function FormatOutput(DisplayString)
Dim DisplayStringLen
DisplayStringLen = Len(DisplayString)
If DisplayStringLen >= BufferLen Then
FormatOutput = DisplayString & ": "
Else
FormatOutput = DisplayString & Right(strPad, BufferLen - DisplayStringLen ) & " "
End If
End Function
Sub ErrorHandler (ErrorMessage)
WScript.Echo ErrorMessage
WScript.Quit(1)
End Sub
Sub Usage
Wscript.echo "Password Change History Source Usage Menu:" & vbCrlf
Wscript.echo "cscript PasswordChangeHistorySource.vbs SearchDomain SearchUser"
Wscript.echo " [MIIS_UserName MIIS_UserPassword MIIS_MachineName]" & vbcrlf
Wscript.echo "SearchDomain Domain name to search for within the CS"
Wscript.echo "SearchUser User name to search for within the CS"
Wscript.echo "MIIS_UserName Domain\UserName to connect as for a remote computer"
Wscript.echo "MIIS_UserPassword Password for the MIIS_UserName argument"
Wscript.echo "MIIS_MachineName Name of the remote computer <tla rid="fim_sync_short"/> is running on" & vbcrlf
End Sub
See Also
Reference
MIIS_PasswordChangeHistorySource Class
MIIS_PasswordChangeHistoryTarget Class
MIIS_PasswordChangeQueue Class
Concepts
Password Synchronization
Password Management
WMI Provider Overview
Using the WMI Provider