Link to home
Start Free TrialLog in
Avatar of PonyboyCurtis00
PonyboyCurtis00

asked on

LDAP query in AD for user profile path and TS profile path

I have been assigned the task of writing an LDAP query in Active Directory to generate a printable or viewable report of every user, their profile path setting, and their Terminal Services Profile path setting. I know nothing of writing LDAP queries, but started playing with ADSI edit and LDP (both part of the Windows 2000 support tools) to see if I could find anything. I even created some queries in ADUC (Active Directory USers and Computers), but to no avail. DOes anyone have any idea where to look or if this is even possible to query on these 2 items?

Thanks,
Boggled WAN Admin
Avatar of mdiglio
mdiglio
Flag of United States of America image

Hello,
Take a look at this.

It is rather involved and there are many diffrent ways of doing this.
One quick and easy way would be downlaoding ADSI Scriptomatic from here:
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/scriptcenter/tools/admatic.asp

but this code will show you a few different ways of querying AD
Open a new vbproject and place a command button on a new form

You will need to make a text file named report.txt on your C drive
this can be changed or eliminated
'set a reference to
'Microsoft ActiveX Data Objects 2.7 Library
Private Sub Command1_Click()

Const ADS_SCOPE_SUBTREE = 2
' ADS_SCOPE_SUBTREE = 2 used when querying AD, subtree means everything beneath
'other options are.... ADS_SCOPE_BASE = 0, ADS_SCOPE_ONELEVEL = 1

'next 6 lines are getting a text file ready to handle the output
Dim fso As Object
Dim f As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim objFileSys As Object
'Create a file before you run this
Set f = fso.OpenTextFile("c:\report.txt", 8)

'these next 4 strings aren't very necessary but it makes it look cleaner
'towards the end
Dim strName As String
Dim strTSProfile As String
Dim strTSHomeDrive As String
'strprofile will error on a null value so I am
Dim strProfile

Dim rs As ADODB.Recordset
Dim cnn As ADODB.Connection
Dim cmd As ADODB.Command
Set cnn = CreateObject("ADODB.Connection")
Set cmd = CreateObject("ADODB.Command")
' Open the connection.
cnn.Provider = "ADsDSOObject"  ' This is the ADSI OLE-DB provider name
cnn.Open "Active Directory Provider"
' Create a command object for this connection.
Set cmd.ActiveConnection = cnn

' Compose a search string and replace DC=YourDomain, DC=COM
cmd.CommandText = "select name, distinguishedname,profilepath " _
& " from 'LDAP:// DC=YourDomain, DC=COM' WHERE objectCategory='user'"
cmd.Properties("Page Size") = 1000
cmd.Properties("Timeout") = 30
cmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE 'search all containers
cmd.Properties("Cache Results") = False

Set rs = cmd.Execute
'----------------------------------------
' Navigate the record set we just created
'----------------------------------------
   
    Do While Not rs.EOF
   
   
        Set objuser = GetObject("LDAP:// " & rs.Fields("distinguishedname") & "")
        'the basic way this looks ( the line above) is
        'getobject("ldap://cn=name,ou=OrgUnit,dc=domain,dc=com")
        'if it wasn't for the TermServicesProfile we wouldn't need this
        'I wasn't able to query that AD Property the way I queried for name,
        'distinguished name and profilepath
   
        strName = rs.Fields("name")
        'you can get rid of this if statement by declaring strProfile
        ' as something else like a variant
        'also you could use the getobject for this property e.g. objuser.profilepath
            If Not IsNull(rs.Fields("profilepath")) Then
                strProfile = rs.Fields("profilepath")
            End If
   
        strTSProfile = objuser.TerminalServicesHomeDirectory
   
        'don't know if you need the property below
        strTSHomeDrive = objuser.TerminalServicesHomeDrive
       
        f.Write strName & "," & strTSProfile & "," & strTSHomeDrive & "," & strProfile
        f.WriteBlankLines (1)
   
        rs.MoveNext
    Loop
MsgBox "done"
End Sub
ASKER CERTIFIED SOLUTION
Avatar of mdiglio
mdiglio
Flag of United States of America 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..I'm glad it worked for you
Avatar of PonyboyCurtis00
PonyboyCurtis00

ASKER

Hey thanks for all your help mdiglio!

I wanted to run something by you real quick...

Since this stuff is a bit over my head (I am a network engineer and not really proficient in development) and since the code you gave me requires VB to be installed on my computer, I thought I would try the ADSIscriptomatic tool first. But let me tell you I am having a heck of a time trying to understand how to modify the ADSI code to get what I need. DO you know if there is any commercial product that offers the ability to easily generate info like what I am looking for, or is someone like myself stuck clicking on each individual user and modifying their settings if I can't get the code to work? Like I said, I haven't tried the VB code yet, but just thought I would ask in case you knew of something...

Thanks!
Hello,
No, off hand I do not know of any utilities that are better than the Scriptomatic tool for showing
how to enumerate user/group properties.
I spend a lot of time stealing code from the Microsoft Tech Net site

http://www.microsoft.com/technet/treeview/default.asp?url=/technet/scriptcenter/user/scrug37.asp
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/scriptcenter/default.asp

these scripts from MS can be used as a script (.vbs) or they can be placed into a VB program

but I also have VB installed so I can step through each line of code one by one and see
how it works a little clearer.

Let me think about this some more, I will see if I can make this work without you having to install VB
and without me sending you a .exe file

Thanks a lot! I'll keep beating on the Scriptomatic tool. I think I might be making some slight progress in the understanding department...
are your users all in one OU?
Unfortunately no. They are in different OU's by location.

On a lighter note, I followed the links you posted and came to the following to articles...

http://www.microsoft.com/technet/scriptcenter/network/scrnet58.asp?frame=true
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/scriptcenter/network/scrnet58.asp

Unfortunately both of these only work on 2003 server and XP clients. We have XP clients but are running 2000 Terminal Server....

Getting closer.....


Hello,
those little scripts came right out of something called scriptomatic
which I have found to be more useful than the adsi one.

I don't see why you can not use that in your environment.
I was using it in an environment like yours for awhile

Either way you should check this scriptomatic out.
It has come in handy many times.
for example performing hardware, software inventory
or even if you wanted to resolve A SID to a name
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/scriptcenter/tools/wmimatic.asp

Here is part of code that will work for user profile and name
'!!Begin

Dim fso, f, strname, strprofile
Set fso = CreateObject("Scripting.FileSystemObject")

'Create a file before you run this
Set f = fso.OpenTextFile("c:\report.txt", 8)

Set NTDomain = GetObject("WinNT://YOURDOMAIN")
NTDomain.Filter = Array("user")

For Each usr In NTDomain

wscript.echo usr.name
strname = usr.name

wscript.echo usr.profile
strprofile = usr.profile
'!!!!Ideally I would like to pass the usr.name into something else here to get the
'!!!!Terminal Service settings  
f.write strname & "," & strprofile
f.WriteBlankLines (1)

Next
'!!!End

You can save this as a .vbs file

Right. Yeah, I got that tool as well after following your link to the ADSI scriptomatic tool you showed me. I haven't tried using it yet. Those scripts I found used syntax and references for 2003 server so I am not sure if the variables and the sting names are the right ones. I will try out some stuff. Thanks again and if you do come up with a way to run your VB code I would definitely like to give it a try. Much appreciated! Thanks!
Just out of curiosity,

When I create the .vbs file and run it, and the only thing I do is add my domain name where it says to (i put mydomain.com), and run the script I get a Microsoft error. Without a debug util, it is hard to see what line the code is erroring on. Can you think of anything I am doing wrong?

Thanks!
It worked for me when I used my domain as just my domain name
not using the full path e.g. msdn NOT msdn.microsoft.com

and make sure there is a file by the name referenced in the script.

to troubleshoot this further you can start commenting out the parts that deal with
writing it to a file.

sometimes the script errors give a line number of where it failed.

but first I would change the domain name used from mydomain.com to mydomain
Ok. So I ran the code and it worked for each user's profile path in Windows. Awsome! So in theory, if I can find the right string name or object name, then I will be able to do the same for the TS Profile? I know that the TS Profile is in WMI in the Win32_TerminalServiceSetting class. And I believe the title is ProfilePath. This was for 2003 Terminal Server though. Do you think if I can find the right names, then I can replace the following 2 lines

wscript.echo usr.profile
strprofile = usr.profile

with the accurate TS variables where instead of usr.profile it would read whatever the TSProfile variable is and make it work?

P.S.> Thanks for all the help and whomever you work for needs to be paying you more!
Hello,
I guess the answer was closer than I thought
I just modified the original code to work in VBScript.
so copy and paste this into notepad and save it with a .vbs extension


Dim strName, strTSProfile, strTSHomeDrive, strProfile
Dim rs,cnn , cmd

Set cnn = CreateObject("ADODB.Connection")
Set cmd = CreateObject("ADODB.Command")
' Open the connection.
cnn.Provider = "ADsDSOObject"  ' This is the ADSI OLE-DB provider name
cnn.Open "Active Directory Provider"
' Create a command object for this connection.
Set cmd.ActiveConnection = cnn
Set f = fso.OpenTextFile("c:\report.txt", 8)

' Compose a search string and replace DC=YourDomain, DC=COM
cmd.CommandText = "select name, distinguishedname,profilepath " _
& " from 'LDAP:// DC=YOUR, DC=DOMAIN, dc=COM' WHERE objectCategory='user'"
cmd.Properties("Page Size") = 1000
cmd.Properties("Timeout") = 30
cmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE 'search all containers
cmd.Properties("Cache Results") = False

Set rs = cmd.Execute
'----------------------------------------
' Navigate the record set we just created
'----------------------------------------
   
    Do While Not rs.EOF
   
   
        Set objuser = GetObject("LDAP:// " & rs.Fields("distinguishedname") & "")
        'the basic way this looks ( the line above) is
        'getobject("ldap://cn=name,ou=OrgUnit,dc=domain,dc=com")
        'if it wasn't for the TermServicesProfile we wouldn't need this
        'I wasn't able to query that AD Property the way I queried for name,
        'distinguished name and profilepath
   
        strName = rs.Fields("name")


        'you can get rid of this if statement by declaring strProfile
        ' as something else like a variant
        'also you could use the getobject for this property e.g. objuser.profilepath
            If Not IsNull(rs.Fields("profilepath")) Then
                strProfile = rs.Fields("profilepath")

            End If
   
        strTSProfile = objuser.TerminalServicesHomeDirectory
   
        'don't know if you need the property below
        strTSHomeDrive = objuser.TerminalServicesHomeDrive
       
        f.Write strName & "," & strTSProfile & "," & strTSHomeDrive & "," & strProfile
        f.WriteBlankLines (1)
   
        rs.MoveNext
    Loop
let me know if you get any errors

same thing applies:
change this line about 15 down
& " from 'LDAP:// DC=YOUR, DC=DOMAIN, dc=COM' WHERE objectCategory='user'"

and have a text file named report.txt on the root of your c drive
ooops paste this into the code:
Set fso = CreateObject("Scripting.FileSystemObject")

preferably right under the ist 2 lines that begin with "dim"
OK OK forget the above stuff.
sorry...but I really think this is the final edition :)

'!!!BEGIN COPY

Dim strName
dim strTSProfile
dim strTSHomeDrive
dim strProfile
Dim rs
dim cnn
dim cmd
dim fso

const ADS_SCOPE_SUBTREE = 2
Set fso = CreateObject("Scripting.FileSystemObject")
Set cnn = CreateObject("ADODB.Connection")
Set cmd = CreateObject("ADODB.Command")
' Open the connection.
cnn.Provider = "ADsDSOObject"  ' This is the ADSI OLE-DB provider name
cnn.Open "Active Directory Provider"
' Create a command object for this connection.
Set cmd.ActiveConnection = cnn
Set f = fso.OpenTextFile("c:\report.txt", 8)


' Compose a search string and replace DC=YourDomain, DC=COM
cmd.CommandText = "select name, distinguishedname, profilepath " _
& " from 'LDAP:// DC=YOUR, DC=DOMAIN, dc=COM' WHERE objectCategory='user'"
cmd.Properties("Page Size") = 1000
cmd.Properties("Timeout") = 30
cmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE 'search all containers
cmd.Properties("Cache Results") = False

Set rs = cmd.Execute
 
    Do While Not rs.EOF
   
       Set objuser = GetObject("LDAP:// " & rs.Fields("distinguishedname") & "")
       'the basic way this looks ( the line above) is
       'getobject("ldap://cn=name,ou=OrgUnit,dc=domain,dc=com")
       'if it wasn't for the TermServicesProfile we wouldn't need this
       'I wasn't able to query that AD Property the way I queried for name,
       'distinguished name and profilepath
   
       strName = rs.Fields("name")


       'you can get rid of this if statement by declaring strProfile
       ' as something else like a variant
       'also you could use the getobject for this property e.g. objuser.profilepath
           If Not IsNull(rs.Fields("profilepath")) Then
               strProfile = rs.Fields("profilepath")

           End If
   
       strTSProfile = objuser.TerminalServicesHomeDirectory
   
       'don't know if you need the property below
       strTSHomeDrive = objuser.TerminalServicesHomeDrive
       
       f.Write strName & "," & strTSProfile & "," & strTSHomeDrive & "," & strProfile
       f.WriteBlankLines (1)
   
       rs.MoveNext
   Loop

'!!!END COPY

same thing applies:
change this line about 15 down
& " from 'LDAP:// DC=YOUR, DC=DOMAIN, dc=COM' WHERE objectCategory='user'"

and have a text file named report.txt on the root of your c drive
Hello.

We ran the code and changed the info to match our domain names and such. We got the code to run and it even output some info to the report.txt file. But the code errors out on line 58 and throws the error that there is no object for objuser.TerminalServicesProfilePath. I don't think it is able to access the properties page of AD for Terminal Services Profile page since it uses an ADSI extension and is not part of the standard property pages for an Active Directory user. Not sure exactly where to approach it from here, except there is a Technet article on using a GetINFO command to load the Terminal Services blah blah blah before being able to script on it....I have to find the page I printed out to try and find the URL. I will post it in the a.m. once I get back to my desk. Hope some of this makes some sense...
Hello,
If you take look at the adsi scriptomatic tool, when you have read attributes from user selected
there is a special not regarding getting the TerminalServices properties.
It seems as if it is not that easy to query for this property.

Tomorrow do a search on the computer running this script for a file named tsuserex.dll
(I'm hoping you have an XP machine)
If it is in your windows\system32 folder then I think it needs to be registered by clicking start >> run >>
regsvr32 c:\%systemroot%\system32\tsuserex.dll

If you do not have this file then you must download the Windows Server 2003 adminpak.
Windows Server 2003 Administration Tools Pack
http://www.microsoft.com/downloads/details.aspx?familyid=c16ae515-c8f4-47ef-a1e4-a8dcbacff8e3&displaylang=en

If you did not want to install the full adminsitration kit you can extract certain tools from it
http://support.microsoft.com/?kbid=314978

Also, IF you are getting this error message on a user
that does not have this property set (TerminalServicesProfilePath)
In other words you know the value is empty
then add this line to the top of your code
on error resume next

Then see if it properly reads the TerminalServicesProfilePath for a user that you KNOW has
a value.

I don't like to leave that in the script because it hurts the debugging process.


How do you Query an OU other than users? Our other OU's are at the same level as users, when I change the LDAP query, I get errors.
Thanks
Never mind, I got it. The LDAP query just needed to be changed to:
LDAP:// OU=Org unit name, DC=domain, dc=com
Thank you for all of your help !
Yeah,

Thanks again mdiglio for all your help! Much appreciated! Yeah, I read that on the ADSI scriptomatic tool, but I hadn't thought it applied to your code. Anways, we got it now. Thanks again!
Congrats....That's Great news!!
I'm glad you got it going.
HI mdiglio

I have been searching for this kind of thing for ages now.

I am trying to use you code for the VB project but I keep getting table does not exist when I debug the code it highlights the row
Set rs = cmd.Execute.

I know I need to change this line LDAP://DC=Yourdomain, DC=COM' WHERE objectCategory='user'"

My question is what does DC=COM need to be ??

Thanks in advance

Hi Matt,

this line.... LDAP://DC=Yourdomain, DC=COM' WHERE objectCategory='user'"
depends upon your domain name.
e.g. microsoft.com >> dc=microsoft,dc=com
e.g. yourSchool.edu >> dc=yourSchool, dc=edu
e.g. state.ny.us>> dc=state, dc=ny, dc=us
Thanks for that it is now working great.

The next problem is I only want users in a particular OU

The line now looks like 'LDAP://pdc.domain/ou=userou,dc=domain' WHERE objectCategory='user'

but i keep getting table does not exist again or am i way off the mark with the above line.

Thanks again
Hello,

In fairness to PonyboyCurtis00 the author of this Q you should open your own question.
OK Sorry will open a question now
Avatar of peh803
mdiglio -- Any chance you could look at the following question (500 points) and provide any comments / suggestions you might have?  It also has to do with winnt / 2k / xp profile management.

https://www.experts-exchange.com/questions/21139567/NT4-2000-XP-User-Profile-Mapping-Utility.html

Thanks in advance!!

peh803