Solved

VBSCript - Error with Login Script

Posted on 2006-07-11
5
1,531 Views
Last Modified: 2010-05-18
This is the deal.  I have this login script running on all my domains in my Windows Server 2003 Active Directory Domain Environment.  I have a single forest multiple domain setup.   I have just added a new Domain (CCD1).   So I have something like this:  
                                                     Main Domain
                                                     /       |        \
                                                  CD1    CD2     CD3
                                                             |
                                                          CCD1

                                CD=Child Domain  CCD=Child Child Domain

The Script runs perfectly fine in all the domains but CCD1.  I get a Permission Denied Error: Code:  800A0046.  Source: Microsoft VBScript runtime error. When it reaches the: objTrans.Init ADS_NAME_INITTYPE_GC, ""  which is line 75

I am at a total lose.  The new Domain Controller is a GC and admins all around the domain have access to each other. Can Anyone Assist?

My Script is as follows:


'
' VBScript logon script program.
'
' ----------------------------------------------------------------------

Option Explicit

Dim objRootDSE, objTrans, strNetBIOSDomain, objNetwork, strNTName
Dim strUserDN, strComputerDN, objGroupList, objUser, strDNSDomain
Dim strComputer, objComputer
Dim strHomeDrive, strHomeShare
Dim objCommand, objConnection, strBase, strAttributes, currentuser
Dim oDrives, oPrinters, i

' Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

Set objNetwork = CreateObject("Wscript.Network")


' Remove all Mapped Drives
On Error Resume Next
objNetwork.RemoveNetworkDrive "f:", true, true
objNetwork.RemoveNetworkDrive "g:", true, true
objNetwork.RemoveNetworkDrive "h:", true, true
objNetwork.RemoveNetworkDrive "i:", true, true
objNetwork.RemoveNetworkDrive "j:", true, true
objNetwork.RemoveNetworkDrive "k:", true, true
objNetwork.RemoveNetworkDrive "l:", true, true
objNetwork.RemoveNetworkDrive "m:", true, true      
objNetwork.RemoveNetworkDrive "n:", true, true      
objNetwork.RemoveNetworkDrive "o:", true, true      
objNetwork.RemoveNetworkDrive "p:", true, true      
objNetwork.RemoveNetworkDrive "q:", true, true
objNetwork.RemoveNetworkDrive "r:", true, true
objNetwork.RemoveNetworkDrive "s:", true, true
objNetwork.RemoveNetworkDrive "t:", true, true
objNetwork.RemoveNetworkDrive "u:", true, true
objNetwork.RemoveNetworkDrive "v:", true, true      
objNetwork.RemoveNetworkDrive "w:", true, true
objNetwork.RemoveNetworkDrive "x:", true, true
objNetwork.RemoveNetworkDrive "y:", true, true      
objNetwork.RemoveNetworkDrive "z:", true, true
On Error GoTo 0

' Remove all Mapped Printers
Set oPrinters = objNetwork.EnumPrinterConnections
For i = 0 to oPrinters.Count - 1 Step 2
    if Left(oPrinters.Item(i+1), 1) = "\" then
      objNetwork.RemovePrinterConnection oPrinters.Item(i+1), true, true
    end if
Next

' Loop required for Win9x clients during logon.
strNTName = ""
On Error Resume Next
Do While strNTName = ""
  strNTName = objNetwork.UserName
  Err.Clear
  If Wscript.Version > 5 Then
    Wscript.Sleep 100
  End If
Loop
On Error GoTo 0

' Determine DNS domain name from RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use the NameTranslate object to find the NetBIOS domain name from the
' DNS domain name.
Set objTrans = CreateObject("NameTranslate")
objTrans.Init ADS_NAME_INITTYPE_GC, ""
objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
' Remove trailing backslash.
strNetBIOSDomain = Left(strNetBIOSDomain, Len(strNetBIOSDomain) - 1)

' Use the NameTranslate object to convert the NT user name to the
' Distinguished Name required for the LDAP provider.
objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain & "\" & strNTName
strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)

' Bind to the user object in Active Directory with the LDAP provider.
Set currentuser = CreateObject("ADSystemInfo")
Set objUser = GetObject("LDAP://" & strUserDN)

' Map user home directory
On Error Resume Next
strHomeShare = objUser.homeDirectory
If strHomeShare <> "" Then
  strHomeDrive = objUser.homeDrive
  If strHomeDrive = "" Then
    strHomeDrive = "P:"
  End If
  objNetwork.MapNetworkDrive strHomeDrive, strHomeShare
End If
On Error Goto 0

' Map a network drive if the user is a member of the group.
If IsMember(objUser, "Applications") Then
  objNetwork.MapNetworkDrive "o:", "\\ccd1srv\Applications"
End If

' Map Share Directory
' Not required for Student Script

' Use the NameTranslate object to convert the NT name of the computer to
' the Distinguished name required for the LDAP provider. Computer names
' must end with "$".
strComputer = objNetwork.computerName
objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain _
  & "\" & strComputer & "$"
strComputerDN = objTrans.Get(ADS_NAME_TYPE_1779)

' Bind to the computer object in Active Directory with the LDAP
' provider.
Set objComputer = GetObject("LDAP://" & strComputerDN)

' Add a printer connection
'  objNetwork.AddPrinterConnection "LPT1:", "\\PrintServer\Printer3"

objNetwork.AddWindowsPrinterConnection "\\ccd1srv\HP LaserJet 5000GN"

' Set Deafult Printer
objNetwork.SetDefaultPrinter "\\ccd1srv\HP LaserJet 5000GN"

' Clean up.
If IsObject(objConnection) Then
  objConnection.Close
  Set objCommand = Nothing
  Set objConnection = Nothing
  Set objGroupList = Nothing
End If
Set objRootDSE = Nothing
Set objTrans = Nothing
Set objNetwork = Nothing
Set objUser = Nothing
Set objComputer = Nothing

Function IsMember(objADObject, strGroupNTName)
' Function to test for group membership.
' objADObject is a user or computer object.
' strGroupNTName is the NT name (sAMAccountName) of the group to test.
' objGroupList is a dictionary object, with global scope.
' Returns True if the user or computer is a member of the group.
' Subroutine LoadGroups is called once for each different objADObject.

' The first time IsMember is called, setup the dictionary object
' and objects required for ADO.
  If IsEmpty(objGroupList) Then
    Set objGroupList = CreateObject("Scripting.Dictionary")
    objGroupList.CompareMode = vbTextCompare

    Set objCommand = CreateObject("ADODB.Command")
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    objCommand.ActiveConnection = objConnection

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

    objCommand.Properties("Page Size") = 100
    objCommand.Properties("Timeout") = 30
    objCommand.Properties("Cache Results") = False

    ' Search entire domain.
    strBase = "<LDAP://" & strDNSDomain & ">"
    ' Retrieve NT name of each group.
    strAttributes = "sAMAccountName"

    ' Load group memberships for this user or computer into dictionary
    ' object.
    Call LoadGroups(objADObject)
  End If
  If Not objGroupList.Exists(objADObject.sAMAccountName & "\") Then
    ' Dictionary object established, but group memberships for this
    ' user or computer must be added.
    Call LoadGroups(objADObject)
  End If
  ' Return True if this user or computer is a member of the group.
  IsMember = objGroupList.Exists(objADObject.sAMAccountName & "\" _
    & strGroupNTName)
End Function

Sub LoadGroups(objADObject)
' Subroutine to populate dictionary object with group memberships.
' objGroupList is a dictionary object, with global scope. It keeps track
' of group memberships for each user or computer separately. ADO is used
' to retrieve the name of the group corresponding to each objectSid in
' the tokenGroup array. Based on an idea by Joe Kaplan.

  Dim arrbytGroups, k, strFilter, objRecordSet, strGroupName, strQuery

  ' Add user name to dictionary object, so LoadGroups need only be
  ' called once for each user or computer.
  objGroupList(objADObject.sAMAccountName & "\") = True

  ' Retrieve tokenGroups array, a calculated attribute.
  objADObject.GetInfoEx Array("tokenGroups"), 0
  arrbytGroups = objADObject.Get("tokenGroups")

  ' Create a filter to search for groups with objectSid equal to each
  ' value in tokenGroups array.
  strFilter = "(|"
  If TypeName(arrbytGroups) = "Byte()" Then
    ' tokenGroups has one entry.
    strFilter = strFilter & "(objectSid=" _
      & OctetToHexStr(arrbytGroups) & ")"
  ElseIf UBound(arrbytGroups) > -1 Then
    ' TokenGroups is an array of two or more objectSid's.
    For k = 0 To UBound(arrbytGroups)
      strFilter = strFilter & "(objectSid=" _
        & OctetToHexStr(arrbytGroups(k)) & ")"
    Next
  Else
    ' tokenGroups has no objectSid's.
    Exit Sub
  End If
  strFilter = strFilter & ")"

  ' Use ADO to search for groups whose objectSid matches any of the
  ' tokenGroups values for this user or computer.
  strQuery = strBase & ";" & strFilter & ";" _
    & strAttributes & ";subtree"
  objCommand.CommandText = strQuery
  Set objRecordSet = objCommand.Execute

  ' Enumerate groups and add NT name to dictionary object.
  Do Until objRecordSet.EOF
    strGroupName = objRecordSet.Fields("sAMAccountName")
    objGroupList(objADObject.sAMAccountName & "\" _
      & strGroupName) = True
    objRecordSet.MoveNext
  Loop

  Set objRecordSet = Nothing
End Sub

Function OctetToHexStr(arrbytOctet)
' Function to convert OctetString (byte array) to Hex string,
' with bytes delimited by \ for an ADO filter.

  Dim k
  OctetToHexStr = ""
  For k = 1 To Lenb(arrbytOctet)
    OctetToHexStr = OctetToHexStr & "\" _
      & Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
  Next
End Function

0
Comment
Question by:sneeri_c
  • 3
  • 2
5 Comments
 
LVL 8

Expert Comment

by:Shakti109
ID: 17087544

This sounds like DCOM is not enabled (or open) on the target domain controller...

Check for / modify the following registry key :

HKLM\SOFTWARE\Microsoft\Ole\EnableDCOM

This should be a reg_sz key.

If it does not exist, create it, and give it a value of "Y".


Let me know what happens after you make this change.
0
 

Author Comment

by:sneeri_c
ID: 17089817
No DCOM was enabled.  Anyother ideas.
0
 
LVL 8

Accepted Solution

by:
Shakti109 earned 500 total points
ID: 17089951

How are the trusts between the new (cdd1) domain and the others?

0
 

Author Comment

by:sneeri_c
ID: 17090008
All Trust are Transative. So they can communicate all around.

Is it poossible to specificy which GC the script goes to?
0
 

Author Comment

by:sneeri_c
ID: 17090212
All is fixed now.  It truely was a permissions problem.  I work at a school and the students in the ccd1 domain do not have accesss to the other domain servers accross the network by GPO.  When the script would run and look for a GC and selected one of the other DCs it would error because they do not have permission to that box.

So I changed: objTrans.Init ADS_NAME_INITTYPE_GC, ""
To: objTrans.Init ADS_NAME_INITTYPE_SERVER, "ccd1srv"

And I added: const ADS_NAME_INITTYPE_SERVER = 2

This forces the script to look at the ccd1 server and get the required info since they have access across the network to that server.

Shakti109's post lead me to this answer so he or she has been awarded the points.
0

Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
VBS file using code from 2nd file (txt or vbs) 4 42
Run code from text file in vb 1 73
Error when passing an argument to a vb6 that contains  '/' 7 40
Help me. 3 60
Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question