Friday, August 8, 2008

Function: getLDAPPath()

You're wondering, "Where the hell has that guy been?".  More than likely you're not actually thinking that but my blog has. So while I don't have anything super great to post, I dug through my archive of functions and found one to post. 

This neat little function will let you pass some info and return to you the full LDAP path to the object.  Some of you veteran scripters out there might ask, "Why not use the built in Wscript call?".  Well you could, but that only returns the user account.  This nifty function will let you query AD to get the LDAP path for computer objects as well.

So lets get to it.  The function has for input parameters. 

Object name = name of the object in AD.  Be sure to use the samAccount name.

Object type = type of object.  User or Computer

Server = The domain server to query

Domain = The domain to query in.  ex. na.fabrikam.com

 

Here's the function first for you to absorb (ahem, copy) and then we'll discuss:

Function getLDAPPath(sstrCN, sstrType, sstrServer, sstrDomain)
'Input: sstrCN = Name of the object to look For
'Input: sstrType = Type of object: "User" or "Computer"
'Input: sstrServer = DC to query On
'Input: sstrDomain = Domain to query: Example: "na.fabrikam.com"
'Output: String = LDAP path to object
    
    Set sCon = CreateObject("ADODB.Connection")
    Set sCom = CreateObject("ADODB.Command")
    sCon.Provider = "ADsDSOObject"
    sCon.Open "Active Directory Provider"
    Set sCom.ActiveConnection = sCon
    
    sstrDomain = "DC=" & Replace(sstrDomain,".",",DC=")
 
    sstrType = UCase(sstrType)
    
    Select Case sstrType
    
        Case "USER"
            sstrQueryField = "samAccountName"
            sstrQueryObject = "USER"
        Case "COMPUTER"
            sstrQueryField = "Name"
            sstrQueryObject = "COMPUTER"        
    End Select
    
    sCom.CommandText = "select adspath from 'LDAP://" & sstrServer &  _
    "/" & sstrDomain & "' WHERE " & sstrQueryField & _
    " = '" & sstrCN & "' and objectclass = '" & sstrQueryObject & "'"
 
    Set sRs = sCom.Execute
    Do While Not sRs.EOF
        sPath = sRs("adspath")
        sRs.movenext
    Loop
 
    getLDAPPath = sPath
 
 
    sCon.Close
    Set sCon = Nothing
    Set sCom = Nothing
    
End Function
Note: If you are copying and pasting, be sure to restore the proper line breaks... Also, I don't typically like using an underscore to break the lines since it's hard to read.  But it helps for copying from this blog.

There.  To break it down, the function first sets up the necessary connections. Next, it reformats the domain to an AD query friendly format.  Then we build a search command and execute.  The results come back as a recordset. We iterate through the recordset to get the "adspath" field.  Set the path to the function name and close out the connections to complete this bad boy.

It's an easy function and doesn't do a whole lot, but if you need to find the LDAP path for a machine name, then this will work for you. 

Also note that if you have multiple domains, you may need to enter in the server name as a fully qualified domain name (FQDN) if you don't have the DNS suffix for that domain setup on the computer. 

Maybe I should add domain variable to the end of the server?  Maybe.  But that could cause problems if a server handled multiple domains.  (If that's even possible, I don't know).

 

That's it for now.  I'll try to dig up more stuff or post new and exciting subs/functions as I get them (and not slack off again).

If you have any questions or suggestions, feel free to leave a comment and I'll be happy to reply!

 

-Corey Thomas

Your humble vbscripting blogger

Monday, June 16, 2008

Twitter? No, it's not porn.

You can now follow me at Twitter.com! Visit my page at http://www.twitter.com/coreytech

If I can find a good app for Twitter on my blackberry, I'll update more often. (Update: found a decent app... so follow me on Twitter!) I have a Facebook page as well. Feel free to add me there at: http://www.facebook.com/profile.php?ID=1022118181

See ya online!

-Corey

Start a process remotely

I'm back with another script fresh from the oven.  This time we're going to create a function that will connect to a machine and create a process.  Before you say "why would I want to create a process, we've got too many processes around here", think of it like this:  Say you have a computer somewhere that you want to run a command like ipconfig /flushdns on.  Well, ipconfig doesn't have a way of doing it remotely.  Now you are stuck with writing out some code to do it via WMI.   While that's great, sometimes it's just easier to type in "ipconfig /flushdns" and you wish you could just tell the dang computer to run it.

Well you can and it turns out, it's pretty simple too.   First, we'll connect to the computer.  Next, we'll create a new process (in this case, ipconfig.exe).  Then we'll pass some switches to it ("/flushdns").  Lastly, we'll run the command and capture the return code to try and determine if the process started successfully.

Before you plop this code into your script, here's a tip.  The function returns a boolean value based on the return code from the OS.  I did my best job trying to interpret the codes into a True/False return code but you may need to modify it for your script.  Also, the function stores the return type (string) so you can get a nice status of the return code.  To use this, declare startExeStatus globally (in the main part of your script).  Then call the function.  It will set the variable to the status.

So here's the code:

Function startExe(sstrComputer,sstrEXE)
'Starts a process on a machine
'Input: sstrComputer = machine name (use "." for local)
'Input: sstrExe = Exe or command to execute (can pass full command line)
'Output: boolean
'Optional: Declare startExeStatus as a global variable to get status text
 
    
    startExe = False 
    Set sobjWMIService = GetObject("winmgmts:\\" & sstrComputer & "\root\cimv2:Win32_Process")
    
    sintReturn = sobjWMIService.Create(sstrEXE, null, null, sintProcessID)
    
    Select Case sintReturn
 
        Case 0 'Successful Completion
            startExe = True
            startExeStatus = "Successful Completion"
            
        Case 2 'Access Denied
            startExe = False
            startExeStatus = "Access Denied"
            
        Case 3 'Insufficient Privilege
            startExe = False
            startExeStatus = "Insufficient Privilege"
            
        Case 8 'Unknown Failure
            startExe = False
            startExeStatus = "Unknown Failure"
            
            
        Case 9 'Path not found
            startExe = False
            startExeStatus = "Path not found"
            
        Case 21 'Invalid Parameter
            startExe = False
            startExeStatus = "Invalid Parameter"
            
        Case Else 
            startExe = False
            startExeStatus = "Error code " & sintReturn & " not found"
            
    End Select 
 
 
End Function 

 

Here's the background on why I created this function.  We have a need to create a scheduled task on a lot (and I mean a LOT) of machines.  We were using schtasks.exe and for the most part it worked fine.  However, one day we found several hundreds of machines that weren't scheduling the tasks.  After some investigation, the machines were returning back as not being NT or higher even though they were on XP SP2.  The need to create the task was great so we worked around it.

I found that creating the task locally worked like a charm.  So the function was born.  It's been used for all kinds of stuff since like ipconfig /flushdns.  Use wisely.  :)

As always, these scripts are free to use and at your own caution.  So don't hold me responsible for any crashes or other bad things you do with it.

-Corey