Solved

VBSCript - Error with Login Script

Posted on 2006-07-11
5
1,517 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
Comment Utility

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
Comment Utility
No DCOM was enabled.  Anyother ideas.
0
 
LVL 8

Accepted Solution

by:
Shakti109 earned 500 total points
Comment Utility

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

0
 

Author Comment

by:sneeri_c
Comment Utility
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
Comment Utility
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
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 utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

771 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now