Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I check to see if a user exists in an NT 4 domain?

-- PA

SpacerHey, Scripting Guy! AnswerScript Center

Hey, PA. You know, if you were to ask us, “How do you back your car out of your driveway?” we’d probably tell you that - after checking all the mirrors - we turn so that we’re facing directly out the back window of the car and then slowly and cautiously begin backing out of the driveway. Now, that’s what we’d tell you. Is that the way we really back the car out of the driveway, or do we just kind of glance in the rear view mirror while we’re pulling out? Hey, we don’t have to answer questions like that; after all, isn’t this supposed to be a column about scripting?

Besides, we never even came close to hitting that Chevy.

Believe it or not, we actually had a good reason for bringing up the subject of backing out of the driveway: for some of us, at least, there’s a difference between how we should do it and how we actually do it. The same thing is true for checking to see if a user exists in a Windows NT 4 domain (or on a local computer, seeing as how the approach is exactly the same). There’s a way that you should make this check, but there’s at least one other way that you can make this check. We’ll show you both approaches, then leave it up to you to decide how you should do it. (Hmmm, We Report, You Decide. Wonder if anyone else is using that slogan?)

If we were dealing with Active Directory there’d be no question how to do this: we’d just run an ADO (ActiveX Data Objects) search and be done with it. Unfortunately, though, the WinNT provider - the scripting technology for working with NT 4 domains and with local user accounts - doesn’t support ADO; thus we can’t do a search against those user accounts. Instead, the “official” way to check for the existence of a user account in an NT 4 domain (or on a local computer) is to use a script similar to this:

Set objDomain = GetObject("WinNT://fabrikam")
objDomain.Filter = Array("User")

blnFound = FALSE

For Each objUser in objDomain
    If objUser.Name = "kenmyer" Then
        blnFound = TRUE
        Exit For
    End If 
Next

If blnFound = TRUE Then
    Wscript.Echo "The user account exists in the domain."
Else
    Wscript.Echo "The user account does not exist in the domain."
End If

The script begins by binding to the fabrikam domain, then creates a Filter that limits the returned objects to user accounts. That’s what these two lines of code do:

Set objDomain = GetObject("WinNT://fabrikam")
objDomain.Filter = Array("User")

Next we create a variable named blnFound and set the value to False. We’ll use blnFound to keep track of whether or not we can find the user account in question. If we find the account, we’ll change blnFound to True; if we don’t find the account, then blnFound will stay False.

We then set up a For Each loop to loop through the list of user accounts. For each account in the collection we check to see if the Name property is equal to kenmyer. If it is, we set the value of blnFound to True, then use the Exit For statement to exit the For Each loop. (Having already found the name there’s no reason to cycle through the rest of the collection.) If the Name is not equal to kenmyer then we simply loop around and check the next account in the collection.

At the end of the script we check the value of blnFound and then echo back the appropriate message (that is, whether or not the user account exists in the domain).

All that works just fine, but if you have 15-20,000 users in your domain it could take a couple minutes for the script to cycle through all the user accounts. So is there a faster way to check for the existence of a user account in an NT 4 domain or a local computer? Yes, there is:

On Error Resume Next

Set objUser = GetObject("WinNT://fabrikam/kenmyer")

If Err.Number = 0 Then
    Wscript.Echo "The user account exists in the domain."
ElseIf Err.Number = -2147022676 Then
    Wscript.Echo "The user account does not exist in the domain."
Else
    Wscript.Echo "The user account status could not be determined."
End If

This script starts off with the On Error Resume Next statement. That’s important, because we aren’t going to retrieve a list of all the user accounts and then methodically check each one to see if the Name equals kenmyer. Instead, we’re going to try to bind directly to the account in question:

Set objUser = GetObject("WinNT://fabrikam/kenmyer")

If we’re able to bind to the account (that is, if the account exists), then the value of the Err object will be equal to 0. We check the value of Err.Number and, if it equals 0, we report back that the user account exists in the domain. If Err.Number is equal to -2147022676 we report back that the account does not exist in the domain. And if Err.Number is equal to something else we report that the account status could not be determined.

As we said, this approach is faster and requires less code. So then why don’t we “officially” recommend it? Well, the truth is, a lot of things can potentially go wrong with a script; because of that you hate to rely on the error number as the only way of determining whether an object exists or not. This script should work just fine, but we don’t recommend making a habit of using shortcuts like this. If anyone ever asks you, “Do the Scripting Guys recommend that you rely on error number as the only way to determine whether or not an object exists?”, make sure you tell them “No, they don’t.” That doesn’t mean we won’t do that from time-to-time, just that we don’t recommend it.

Now, did you say you had a question about cars and about driving? Well, what we Scripting Guys always recommend is - you still there? Hello? Come on: we know as much as those Car Talk guys do.

Well, not about cars, of course, but ….