Link to home
Start Free TrialLog in
Avatar of bsharath
bsharathFlag for India

asked on

Script To check All The Users who is set to Change The Password On Next Logon.

Hi,

Script To check All The Users who is set to  Change The Password On Next Logon.

i want to query a OU and all Ou's below that i mean child ou's and get the names of users who has the check box selected for "Next login password change"

Which ever are ticked.

Regards
Sharath
Avatar of snurker
snurker
Flag of United States of America image

http://ss64.com/nt/dsget-user.html

Link for all DSGET commands.
It would be DSGET user (UserDN) -mustchpwd yes

Avatar of Joseph Daly
Try this

dsquery user {distinguished name of starting ou} | dsget user -ln -fn -mustchpwd

And just in case you have over 1000 users in that ou

dsquery user {distinguished name of starting ou} -limit 0 | dsget user -ln -fn -mustchpwd

And just in case you want it to ouput to a file

dsquery user {distinguished name of starting ou} | dsget user -ln -fn -mustchpwd > C:\outfile.txt

And if  you dont know how to get the distinguished name of the OU download and install ADexplorer. This tool makes it very easy to browse your AD structure and get the Distinguishged name of any objewct

http://technet.microsoft.com/en-us/sysinternals/bb963907.aspx
Avatar of bsharath

ASKER

Thanks it works but the output format is not clear
Can i get the full names and Description to the output
Sharath, I have taken some time to write a script that will change the output format to CSV.  All you should need to change is the OU path to read users from.

Regards,

Rob.
strOutputFile = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "MustChangePassword.csv"
strOU = "OU=OUName2,OU=OUName1,DC=domain,DC=com"

Set objFSO = CreateObject("Scripting.FileSystemObject")
Const intForReading = 1
' mustchgpwd MUST be the last field in this array
arrFields = Array("fn","ln","display","mustchpwd")
strTempOutput = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & objFSO.GetTempName
strCommand = "cmd /c dsquery user """ & strOU & """ | dsget user"
For Each strField In arrFields
	strCommand = strCommand & " -" & strField
Next
strCommand = strCommand & " > """ & strTempOutput & """"
Set objShell = CreateObject("WScript.Shell")
objShell.Run strCommand, 0, True
Set objFile = objFSO.OpenTextFile(strTempOutput, intForReading, False)
Set objOutput = objFSO.CreateTextFile(strOutputFile, True)
strHeader = ""
For Each strField In arrFields
	If strHeader = "" Then
		strHeader = """" & strField & """"
	Else
		strHeader = strHeader & ",""" & strField & """"
	End If
Next
objOutput.WriteLine strHeader
intHeader = True
intPos = 1
While Not objFile.AtEndOfStream
	strLine = objFile.ReadLine
	If strLine <> "" And strLine <> "dsget succeeded" Then
		If intHeader = True Then
			strPos = ""
			For Each strField In arrFields
				If intPos = 1 Then
					intPos = InStr(intPos, strLine, strField)
				Else
					intPos = InStr(intPos + Len(strField), strLine, strField)
				End If
				If strPos = "" Then
					strPos = intPos
				Else
					strPos = strPos & "," & intPos
				End If
			Next
			arrPos = Split(strPos, ",")
			intHeader = False
		Else
			If LCase(Trim(Mid(strLine, arrPos(UBound(arrPos))))) = "yes" Then
				strNewLine = ""
				For intBit = LBound(arrPos) To UBound(arrPos)
					If intBit < UBound(arrPos) Then
						If strNewLine = "" Then
							strNewLine = """" & Trim(Mid(strLine, arrPos(intBit), arrPos(intBit + 1) - arrPos(intBit))) & """"
						Else
							strNewLine = strNewLine & ",""" & Trim(Mid(strLine, arrPos(intBit), arrPos(intBit + 1) - arrPos(intBit))) & """"
						End If
					Else
						If strNewLine = "" Then
							strNewLine = """" & Trim(Mid(strLine, arrPos(intBit))) & """"
						Else
							strNewLine = strNewLine & ",""" & Trim(Mid(strLine, arrPos(intBit))) & """"
						End If
					End If
				Next
				objOutput.WriteLine strNewLine
			End If
		End If
	End If
Wend
objFile.Close
objOutput.Close
objFSO.DeleteFile strTempOutput, True
MsgBox "Done. Please see " & strOutputFile

Open in new window

Although, come to think of it, it probably would have been easier for me to just read those attributes directly from AD, rather that dsget and massage the output.....

Oh well, too late....
Rob i get this

---------------------------
Windows Script Host
---------------------------
Script:      D:\Find Next login password change.vbs
Line:      16
Char:      1
Error:      File not found
Code:      800A0035
Source:       Microsoft VBScript runtime error

---------------------------
OK  
---------------------------
That's odd.....above this:
objShell.Run strCommand, 0, True

can you put
MsgBox "Creating temporary output file: " & vbCrLf & strTempOutput

and see if that file path is valid?  That's a path for outputting the temporary results.

Rob.
I get this

---------------------------

---------------------------
Creating temporary output file:

D:\radF2066.tmp
---------------------------
OK  
---------------------------

And then the error
That's odd....do you have rights to create files there?  Can you run the command manually:
dsquery user "OU=StartOU,DC=Domain,DC=com" | dsget user -ln -fn -mustchpwd > D:\DummyOutput.tmp

and then open the tmp file with Notepad?

Rob.
Sorry Rob i was running the script on a xp machine
Now it works
If i mention the root path will it scan through all the Ou's below if?
As it gets just 3 users where as i have many more in them
Yes, it should, although it may be reaching the default limit of 100 users.....change line 9 from this:
strCommand = "cmd /c dsquery user """ & strOU & """ | dsget user"

to this
strCommand = "cmd /c dsquery -limit 0 user """ & strOU & """ | dsget user"

Regards,

Rob.
Rob i get nothing in the results.
I am mentioning the root OU. Hope it will check all sub Ou's within it
Are you sure that you are putting in the correct DSN?

If my user's folder was in the company folder in the root of domain.local, my DSN would be "OU=users,OU=Company,DC=Domain,DC=local"

Try this to test dsquery user "DNS"

dsquery user "OU=users,OU=Company,DC=Domain,DC=local" in the example above.

You can even just do "DSquery -limit 0 user" and it will list all user accounts. This should give you an idea of what the DSN should be. Exclude the CN
That DNS should be DSN
I tried this
dsquery user "OU=ai,OU=ia,OU=Offices,DC=lth,DC=local"

and it does lists
Can we have the script show all users that its queried
So we know its reading all users
That will only list users that are in the AI OU nested in the IA OU nested in Offices in your domain lth.local.

If you want all users in your domain, your line would be

dsquery user "DC=lth,DC=local"
What i meant was the main script when run shows a log of all files it ran over. So we know if the script covers all users that i wanted
why does this not work for you?

dsquery user {distinguished name of starting ou} | dsget user -ln -fn -mustchpwd > C:\outfile.txt
xxdcmast
It does list how should the command be for Unlimited usersi put - limit but it errors
xxdcmast's cmd line should work if you have the correct DSN.

dsquery user "DC=lth,DC=local" | dsget user -ln -fn  -mustchpwd > C:\outfile.txt

That should get all users in your domain with the results.
Do you have permissions to write to c:?
This will remove the limit

dsquery user {distinguished name of starting ou} -limit 0 | dsget user -ln -fn -samid -mustchpwd > C:\outfile.txt
Sharath, in my code, if you want it to show every user (not just those that must change their password), comment out line 49, which is this:
                  If LCase(Trim(Mid(strLine, arrPos(UBound(arrPos))))) = "yes" Then

and it's corresponding
                  End If

on line 67.

In any case, it should already be recursive....

Rob.
Hi rob still does not list all users with or without the password change check box

strOutputFile = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "MustChangePassword.csv"
strOU = "OU=Offices,DC=lth,DC=local"

Set objFSO = CreateObject("Scripting.FileSystemObject")
Const intForReading = 1
' mustchgpwd MUST be the last field in this array
arrFields = Array("fn","ln","display","mustchpwd")
strTempOutput = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & objFSO.GetTempName
strCommand = "cmd /c dsquery -limit 0 user """ & strOU & """ | dsget user"
For Each strField In arrFields
	strCommand = strCommand & " -" & strField
Next
strCommand = strCommand & " > """ & strTempOutput & """"
Set objShell = CreateObject("WScript.Shell")
MsgBox "Creating temporary output file: " & vbCrLf & strTempOutput
objShell.Run strCommand, 0, True
Set objFile = objFSO.OpenTextFile(strTempOutput, intForReading, False)
Set objOutput = objFSO.CreateTextFile(strOutputFile, True)
strHeader = ""
For Each strField In arrFields
	If strHeader = "" Then
		strHeader = """" & strField & """"
	Else
		strHeader = strHeader & ",""" & strField & """"
	End If
Next
objOutput.WriteLine strHeader
intHeader = True
intPos = 1
While Not objFile.AtEndOfStream
	strLine = objFile.ReadLine
	If strLine <> "" And strLine <> "dsget succeeded" Then
		If intHeader = True Then
			strPos = ""
			For Each strField In arrFields
				If intPos = 1 Then
					intPos = InStr(intPos, strLine, strField)
				Else
					intPos = InStr(intPos + Len(strField), strLine, strField)
				End If
				If strPos = "" Then
					strPos = intPos
				Else
					strPos = strPos & "," & intPos
				End If
			Next
			arrPos = Split(strPos, ",")
			intHeader = False
		Else
'			If LCase(Trim(Mid(strLine, arrPos(UBound(arrPos))))) = "yes" Then
				strNewLine = ""
				For intBit = LBound(arrPos) To UBound(arrPos)
					If intBit < UBound(arrPos) Then
						If strNewLine = "" Then
							strNewLine = """" & Trim(Mid(strLine, arrPos(intBit), arrPos(intBit + 1) - arrPos(intBit))) & """"
						Else
							strNewLine = strNewLine & ",""" & Trim(Mid(strLine, arrPos(intBit), arrPos(intBit + 1) - arrPos(intBit))) & """"
						End If
					Else
						If strNewLine = "" Then
							strNewLine = """" & Trim(Mid(strLine, arrPos(intBit))) & """"
						Else
							strNewLine = strNewLine & ",""" & Trim(Mid(strLine, arrPos(intBit))) & """"
						End If
				End If
				Next
				objOutput.WriteLine strNewLine
		'	End If
		End If
	End If
Wend
objFile.Close
objOutput.Close
objFSO.DeleteFile strTempOutput, True
MsgBox "Done. Please see " & strOutputFile

Open in new window

xxdcmast
I still get nothing in the log
You get nothing in the log even when using the DSN "DC=lth,DC=local"?

If your trying to get all the users in the domain dont even bother with putting the DN in there. Just do this.

dsquery user -samid * -limit 0 | dsget user -ln -fn -samid -mustchpwd > C:\outfile.txt
I want just for specific OU and all sub Ou's below it...
I was just mentioning to test your DSN. If you run it for the whole domain and it works, then it is in the DSN. If you run it and it does not work, then you know there is something else incorrect.
Then use the DN for the OU and it will use that as the start base for the search. I posted that in one of my first reponses here.
Even without a DN i get this
C:\>dsquery user -samid * -limit 0 | dsget user -ln -fn -samid -mustchpwd > C:\outfile.txt
dsget failed:Directory object not found.
type dsget /? for help.
I dont know something may be up with your AD. I just copied and pasted exactly what you just commented and came up with a list of users.
Sharath, as you have just tried, you really need to get this working:
dsquery user "OU=YourOU,DC=Domain,DC=Com" | dsget user -ln -fn  -mustchpwd

If that doesn't produce any output, then something must be wrong.

I notice above though, that DSGet failed, while DSQuery looks like it succeeded.  Would there be any special characters in any DNs that cause the pipe to DSGet to fail?

If the above failed again, try just:
dsquery user "OU=YourOU,DC=Domain,DC=Com"

and see if you get results.  If that works, what is listed might show you that there is a special character in one or more of the names.

Regards,

Rob.
Rob this line does work

dsquery user "OU=YourOU,DC=Domain,DC=Com" | dsget user -ln -fn  -mustchpwd
it shows me all users in the OU with  mustchpwd yes\No
OK, have you tried the code in ID:33180356 again?

If that doesn't work, above this line:
MsgBox "Creating temporary output file: " & vbCrLf & strTempOutput

add
InputBox "About to run:", "Command", strCommand

and see if that command looks correct.

Regards,

Rob.
Rob i get this

cmd /c dsquery -limit 0 user "OU=Former,DC=lth,DC=local" | dsget user -fn -ln -display -mustchpwd > "C:\radB5E50.tmp"
But no output still
dsquery user "OU=YourOU,DC=Domain,DC=Com" | dsget user -ln -fn   -mustchpwd > file.csv

should produce the csv if you are getting data from the cmd line without the "> file.csv"
dsquery user "OU=YourOU,DC=Domain,DC=Com" | dsget user -ln -fn   -mustchpwd > c:\file.csv
Sorry, did not put it in the root directory.

If you run this manually at a command prompt:
dsquery -limit 0 user "OU=Former,DC=lth,DC=local" | dsget user -fn -ln -display -mustchpwd > "C:\radB5E50.tmp"

does radB5E50.tmp get created?  Can you open it with Notepad?

Rob.
Rob i get this

dsquery failed:The parameter is incorrect.:Incorrect object type specified.
type dsquery /? for help.dsget failed:`Target object for this command' is missin
g.
type dsget /? for help.

The OU path is correct
ASKER CERTIFIED SOLUTION
Avatar of RobSampson
RobSampson
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Rob works fine.. :-)
Sorry that took so long to figure out! I swear I tested it that way before!

Rob.
Thank you Rob...
You are the best...
:-)