Link to home
Start Free TrialLog in
Avatar of resourcepc
resourcepc

asked on

Newbie with VBScript, need more info please

I started my current job about six months ago and they're using Kixtart for mapping drives, etc.  Users are always complaining about how slow it takes to map drives, etc before they can actually start working.  I want to convert over to VBScript to speed up the process.  I've checked out a site that showed how to map a drive, but I need to do more.  I need to map drives based on group memberships, another thing I did with Kixtart was create a log for when users log off and on and from what workstation.  I will need to be able to do this with VBscript as well.  

Kixtart script to create log:

$logfile = Open(1, "\\server\sharename$\%username%.log", 5)
$logfile = WriteLine(1, "LOGGED ON:  "+@MonthNo+"/"+@MDayNo+"/"+@Year+"  "+@TIME+"  "+%username%+"  "+@WKSTA+@CRLF)
Avatar of JesterToo
JesterToo
Flag of United States of America image

Try the following script to see if it addresses your needs.  I've not tested it after I made some modifications to the original (which works very well).  You probably will need to edit some strings to conform to your network environment before using it.  There may be a feature or two you don't need in it.  Mr. Mueller is quite well known for his scripting skills.

' Logon6.vbs
' VBScript logon script program.
'
' ----------------------------------------------------------------------
' Copyright (c) 2004 Richard L. Mueller
' Hilltop Lab web site - http://www.rlmueller.net
' Version 1.0 - March 28, 2004
'
' You have a royalty-free right to use, modify, reproduce, and
' distribute this script file in any way you find useful, provided that
' you agree that the copyright owner above has no warranty, obligations,
' or liability for such use.
'
' Minor modifications made from author's original code
' by Lynn Ransdell 2006-02-12
'

Option Explicit

Const ForAppending = 8
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

Dim objRootDSE, objTrans, strNetBIOSDomain, objNetwork, strNTName
Dim strUserDN, strComputerDN, objGroupList, objUser, strDNSDomain
Dim strComputer, objComputer
Dim strHomeDrive, strHomeShare
Dim objCommand, objConnection, strBase, strAttributes
Dim oFSO, oTS

Set oFSO = CreateObject("Scripting.FileSystemObject")
Set objNetwork = CreateObject("Wscript.Network")
strComputer = objNetwork.computerName

' 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 objUser = GetObject("LDAP://" & strUserDN)



'-- This is code logs the login.

Set oTS = oFSO.OpenTextFile("\\server\sharename$\" & strNTName & ".log", ForAppending, True) 'For Append or Create
oTS.Write "LOGGED ON:  " & Now & "  " & strNTName & "  " & srComputer
oTS.Close
Set oTS = Nothing
Set oFSo = Nothing



'-- begin your modifications for drive/printer mapping here


' Map user home directory.
strHomeShare = objUser.homeDirectory
If strHomeShare <> "" Then
  strHomeDrive = objUser.homeDrive
  If strHomeDrive = "" Then
    strHomeDrive = "H:"
  End If
  On Error Resume Next
  objNetwork.MapNetworkDrive strHomeDrive, strHomeShare
  If Err.Number <> 0 Then
    On Error GoTo 0
    objNetwork.RemoveNetworkDrive strHomeDrive, True, True
    objNetwork.MapNetworkDrive strHomeDrive, strHomeShare
  End If
  On Error GoTo 0
End If

' Map a network drive if the user is a member of the group.
If IsMember(objUser, "Domain Admin") Then
  On Error Resume Next
  objNetwork.MapNetworkDrive "M:", "\\filesrv01\admin"
  If Err.Number <> 0 Then
    On Error GoTo 0
    objNetwork.RemoveNetworkDrive "M:", True, True
    objNetwork.MapNetworkDrive "M:", "\\filesrv01\admin"
  End If
  On Error GoTo 0
End If

' 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 "$".
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 if the computer is a member of the group.
If IsMember(objComputer, "Room 231") Then
  objNetwork.AddPrinterConnection "LPT1:", "\\PrintServer\Printer3"
End If


'-- end your modifications for drive/printer mapping here



' 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


HTH,
Lynn
Avatar of resourcepc
resourcepc

ASKER

So it looks like this is the only part I need to create my log file for each user correct?

Set oFSO = CreateObject("Scripting.FileSystemObject")
Set objNetwork = CreateObject("Wscript.Network")
strComputer = objNetwork.computerName
strNTName = objNetwork.UserName
Set oTS = oFSO.OpenTextFile("\\server\sharename$\" & strNTName & ".log", ForAppending, True) 'For Append or Create
oTS.Write "LOGGED ON:  " & Now & "  " & strNTName & "  " & srComputer
oTS.Close
Set oTS = Nothing
Set oFSo = Nothing

I saw a script that looks like they're getting the username with this code:
Set ADSysInfo = CreateObject("ADSystemInfo")

Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)

Which way is better?

Also, how would I map a drive then based on their userID?  Like this kixtart script....

IF @USERID = "JAK" OR @USERID = "MAW" OR @USERID = "KJD"

  use h: "\\diesel\oitest"

ENDIF

Avatar of herreruud
Hi,

In VB you can execute code with the 'shell'-keyword.

You can use:

if ADSysInfo.UserName = "JAK" Or ADSysInfo.UserName = "MAW" or ADSysInfo.UserName = "KJD" Then
       Shell "NET USE x: \\diesel\oitest"
End If

OR:

Select case ADSysInfo.UserName
    Case "JAK", "MAW", "KJD"
           Shell "NET USE x: \\diesel\oitest"
End Select




>>> So it looks like this is the only part I need to create my log file for each user correct? <<<
Yes.


>>> Which way is better? <<<
There are multiple ways to obtain the current username and computer name... no one way is any "better" than another.  You should use whichever technique is simpler (fits in with the code you're already using... no need to complicate things by using different classes/objects just for the sake of doing it a particular way).

>>> Also, how would I map a drive then based on their userID?  <<<
You oroginally asked for mapping based on group membership (which this script does)... if you don't need that then the script could be greatly simplified (obtaining group membership takes up a significant amount of this script).  You just need to edit it to specify your groups or userid's and drive mappings.  Look for the section just below this comment:  >>> Map a network drive if the user is a member of the group. <<< and modify accordingly... this is a template for what you need.

Repeat that pattern for as many uisers as you want... however, using group membership to determine drive mappings is probably a lot less coding (don't forget everything you have a new user, or one leaves, or needs access to different data because his job changes will require editing of this script... far easier to control these things with groups than users!)

Here is an example to base drive mapping on username:

If areNTName = "someuserid" Then
  On Error Resume Next
  objNetwork.MapNetworkDrive "M:", "\\filesrv01\admin"
  If Err.Number <> 0 Then
    On Error GoTo 0
    objNetwork.RemoveNetworkDrive "M:", True, True
    objNetwork.MapNetworkDrive "M:", "\\filesrv01\admin"
  End If
  On Error GoTo 0
End If

Regards,
Lynn
what is this part needed for?

If Err.Number <> 0 Then
    On Error GoTo 0
    objNetwork.RemoveNetworkDrive "M:", True, True
    objNetwork.MapNetworkDrive "M:", "\\filesrv01\admin"
  End If
You'll notice that the statement immediately above this fragment issues a MapNetworkDrive call... if it is successful, then this code fragment does not run at all.  However, if the prior statement gets an error (usually because the drive letter is already mapped) then this fragment removes the current mapping and re-issues the MapNetworkDrive call.

Have you tried modifying the script to suit your environment and testing it yet?

I'm still having problems creating my log file.  

Set wshNetwork = CreateObject("WScript.Network")
On Error Resume Next
Set ADSysInfo = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
strGroups = LCase(Join(CurrentUser.MemberOf))
strComputer = objNetwork.computerName

Wscript.echo "Login Script is now running"

'Dim oFSO

'**** Log when a user logs onto Domain****
Set oTS = oFSO.OpenTextFile("\\homer\userlogoffs$\test\" & CurrentUser & ".log", ForAppending, True)
oTS.Write "LOGGED ON:  " & Now & "  " & CurrentUser & "  " & strComputer
oTS.Close
Set oTS = Nothing
Set oFSo = Nothing

Also, with my drive mapping it doesn't seem to map H: and N: when the user is a member of the Orbit Group, and it's mapping H: based on username when this user I'm testing with does not match the accounts listed.  See code below:

If Instr(strGroups, Marketing) Then
wshNetwork.MapNetworkDrive "j:", "\\share\8701\act2005"
End If

If Instr(strGroups, "cn=ftp users") Then
wshNetwork.MapNetworkDrive "u:", "\\share\8701\ftproot"
End If
If Instr(strGroups, "cn=Orbit Group") Then
wshNetwork.MapNetworkDrive "h:", "\\share\oitest"
wshNetwork.MapNetworkDrive "n:", "\\share\openinsight"
End If
If CurrentUser = "ToddL" Or CurrentUser = "MarkW" or CurrentUser = "JillP" Then
wshNetwork.MapNetworkDrive "h:", "\\share\oitest"
wscript.echo "Display only if a user listed above"
End If

Not sure what I'm doing wrong here... Thanks for the help!
Could you please post the entire script you're using?  I cannot tell what the error is from just this fragment (you're obviously using a different technique than the one in the script I posted.)

Regards,
Lynn
I have the drive mapping figured out, but I don't have the log file thing down.

Set wshNetwork = CreateObject("WScript.Network")
Set oFSO = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set ADSysInfo = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
strGroups = LCase(Join(CurrentUser.MemberOf))
strComputer = objNetwork.computerName

Dim oFSO

'**** Log when a user logs onto Domain****
Set oTS = oFSO.OpenTextFile("\\homer\userlogoffs$\test\" & CurrentUser & ".log", ForAppending, True)
oTS.Write "LOGGED ON:  " & Now & "  " & ADSysInfo.UserName & "  " & strComputer
oTS.Close
Set oTS = Nothing
Set oFSo = Nothing

When running cscript from the command line, I get "Wrong number of arguments or invalid property assignment"
Here is my whole login script....

'************************************
'*      Test OU Logon Script            *
'************************************

Set wshNetwork = CreateObject("WScript.Network")
Set oFSO = CreateObject("Scripting.FileSystemObject")
'On Error Resume Next
Set ADSysInfo = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
strGroups = LCase(Join(CurrentUser.MemberOf))
strComputer = objNetwork.computerName


Wscript.echo "Login Script is now running"

'Dim oFSO

'**** Log when a user logs onto Domain****
Set oTS = oFSO.OpenTextFile("\\server\userlogoffs$\test\" & CurrentUser & ".log", ForAppending, True)
oTS.Write "LOGGED ON:  " & Now & "  " & ADSysInfo.UserName & "  " & strComputer
oTS.Close
Set oTS = Nothing
Set oFSo = Nothing

'**** Remove Mapped Drives****
'wshNetwork.RemoveNetworkDrive "g:"
'wshNetwork.RemoveNetworkDrive "t:"
'wshNetwork.RemoveNetworkDrive "h:"
'wshNetwork.RemoveNetworkDrive "m:"
'wshNetwork.RemoveNetworkDrive "w:"
'wshNetwork.RemoveNetworkDrive "u:"
'wshNetwork.RemoveNetworkDrive "j:"
'wshNetwork.RemoveNetworkDrive "h:"
'wshNetwork.RemoveNetworkDrive "n:"
'wshNetwork.RemoveNetworkDrive "l:"
'wshNetwork.RemoveNetworkDrive "o:"

Wscript.echo "Mapped Drives are now removed"


'**** Map Drives based on membership***
wscript.echo "In groups:", strGroups
wscript.echo "mapping drives"

If Instr(strGroups, Marketing) Then
'wshNetwork.MapNetworkDrive "j:", "\\server\8701\act2005"
End If
If Instr(strGroups, "cn=ftp users") Then
wshNetwork.MapNetworkDrive "u:", "\\server\8701\ftproot"
End If
If Instr(strGroups, "cn=Orbit Group") Then
wshNetwork.MapNetworkDrive "h:", "\\server\oitest"
wshNetwork.MapNetworkDrive "n:", "\\server\openinsight"
End If
If ADSysInfo.UserName = "ToddL" Or ADSysInfo.UserName = "MarkW" or ADSysInfo.UserName = "JillP" Then
wshNetwork.MapNetworkDrive "h:", "\\server\oitest"
End If

'**** Copy Orbit Link to Desktop****
'sDestinationOrbitLnk = "c:\Documents and Settings\" & ADSysInfo.UserName  & "\Desktop\"
'oFSO.CopyFile "\\diesel\oi32\shortcut\orbit.lnk", sDestinationOrbitLnk
Set oFSO = Nothing
Set wshNetwork = Nothing
Set ADSysinfo = Nothing
Set CurrentUser = Nothing
Ok, I figured out part of my problem with the log file.  if the log file doesn't exist, then I need this statement to create it:

Set oTS = oFSO.CreateTextFile("\\server\userlogoffs$\test\" & WshNetwork.UserName & ".log", ForAppending, True)

Is there  a command I can use that will create the file if it doesn't exist, and if it does exist it will just write to the file?
ASKER CERTIFIED SOLUTION
Avatar of JesterToo
JesterToo
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 have it all working now.  I notice that it is still slow to map the drives where I checking for group memberships.  Is there anyway to speed up the script processing?  It takes about a minute until all the drives are mapped.