locked
Logon Script call to CSV/TXT file to map drive based on user name RRS feed

  • Question

  • I'll keep this short and to the point.  I wont be checking this during the day, as I'm working in a secure environment and wont have access to this site.
    I'm starting on an AD migration project that's already in progress.  No users or non-AD servers exist in this environment, yet.
    The migration is to a new forest and new domain.  What's described below will be implmented in the "old domain", proven out, and carried over to the new environment.

    I'm looking to supplement a GPO-based logon script with a vb script that references a CSV file and maps additional drives based on username.  The majority of drive mappings happen in the GPO-based script. 

    This supplemental vbscript will replace individual logon scripts, specified per-user, to handle exceptions that the GPO-based script can't handle.  There are several hundred users that require these exceptions and the drive letters are all over the place.   

    I've been able to standardize a portion of the drive mappings, but this is a very sensitive environment and too much change at once is going to be impossible.

    What they have now works but they want to consolidate down to a single supplemental script and get away from having the help desk and techs edit vbscripts.  Something like a CSV, text file, or INI file is easier for the less experienced folks to maintain.... It will also make it easier to write a gui that will automate adding the logon script to the user account and edit but that would come along later.

    I can get what they want working by group name or by distinguished name (DN), but I cannot get it to work using the standard user name (samaccountname).  No matter what I've tried so far, I can only get it working by using the DN of the user.   How can i get the VB script to take a username from the CSV instead of DN?

    I know this is somewhat "old school" and I know the reasons why this isn't ideal, but there are technical and performance limitations that prohibit other options.

    Thanks in advance...

    • Moved by Bill_Stewart Tuesday, August 13, 2013 9:47 PM Abandoned thread
    Friday, March 15, 2013 3:20 AM

Answers

  • Yep you're right about both.  I meant to obscure the domain name.  We used \\domain.name\netlogon\altdrivemap.csv

    On error does exactly what we want.   To keep on going without hanging up the logon process.  Tablets, Kiosks, Citirx, etc...

    On error does not do that.  You need to update you knowledge about how that works.

    I have written Windows logon scripts for almost 20 years.  Believe me you are off her.

    Here is a better approach.  It is close but needs some error handling but only on the file  and the mappings.

    I will post an example of how we do this.  In the meantime look in the script center for examples of how to implement error handling correctly.

    ' this needs to be translated by the shell
    Const strCSV = "%logonserver%\netlogon\altdrivemap.csv"
    
    dtmStartTime = Now
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    set objNetwork = WScript.CreateObject("WScript.Network")
    strUserName = lcase(objNetwork.UserName)
      
    Set objCSVFile = objFSO.OpenTextFile(strCSV)
    Do while NOT objCSVFile.AtEndOfStream
    
     	arr = split(objCSVFile.ReadLine,",") 'Split the values by their delimiter
     	
     	'Match the username
     	If strusername = trim(lcase(arr(0))) then
     	
      		'---------Disconnect any drive letters that will be mapped
      		If (objFSO.DriveExists(arr(1)) = True) Then
       			objNetwork.RemoveNetworkDrive arr(1), True, True
      		End If
      		
      		'Notification of pending drive mapping assignments
       		'Wscript.Echo "Existing Drive Mapping" & arr(1) & arr(2) 
      		objNetwork.MapNetworkDrive arr(1), arr(2), False
      		
     	End If
     
    Loop
     
    objCSVFile.Close
     
    dEndTime = Now
    elapsedTime = DateDiff("s",dStartTime,dEndTime)
    WScript.Echo "Script completed in " & elapsedTime & " seconds"


    ¯\_(ツ)_/¯



    • Edited by jrv Saturday, May 18, 2013 4:14 AM
    • Proposed as answer by jrv Tuesday, August 13, 2013 10:04 PM
    • Marked as answer by Just Karl Friday, October 4, 2013 2:05 AM
    Saturday, May 18, 2013 4:13 AM

All replies

  • In Windows NT 2008 and later domains we use Group Policy preferences to map drives and printers.  It is more reliable and more flexible and less prone to errors.

    To specifically answer yup question; you can read a file with a VBScript. Look in the repository link above and look into the 'Learn' link for how to use VBScript with files.

    Normally separate user mappings are done once and set as 'persistent' in the user profile. This is managed by the users  If you want to help the users get start just give them a link to the file that permanently maps their drives and have tem execute it once.  Just store the script on a public share and reference it by UNC path.


    ¯\_(ツ)_/¯

    • Marked as answer by IamMred Friday, May 17, 2013 2:34 AM
    • Unmarked as answer by Matt Garner Saturday, May 18, 2013 2:42 AM
    Friday, March 15, 2013 3:52 AM
  • Yes GPP's would be ideal and if it would have been an option we would have used them. 

    Here's the script that was implemented:

    on error resume next
    '----------start timer------------------
    dtmStartTime = Timer

    '----------constants and variables --------------------
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    set objNetwork = WScript.CreateObject("WScript.Network")
    Set WSHShell = CreateObject("WScript.Shell")
    Set colDrives = objFSO.Drives
    strUserName = objNetwork.UserName
    strCSV = "%logonserver%\netlogon\altdrivemap.csv"
    Const ForReading = 1

    '----------Read the CSV and look for username------------

    Set objCSVFile = objFSO.OpenTextFile(strCSV,1)
    Do while NOT objCSVFile.AtEndOfStream
     'Split the values by their delimiter
     arr = split(objCSVFile.ReadLine,",")
     'Match the username
     IF lcase(strusername) = trim(lcase(arr(0))) then

      '---------Disconnect any drive letters that will be mapped
      If (objFSO.DriveExists(arr(1)) = True) Then
       objNetwork.RemoveNetworkDrive arr(1), True, True
      End If
      'Notification of pending drive mapping assignments
       'Wscript.Echo "Existing Drive Mapping" & arr(1) & arr(2)

      '----------Map the drives
      objNetwork.MapNetworkDrive arr(1), arr(2), False
     else
     END IF
    Loop
    objCSVFile.Close
    '---------Timer Functions ---------------------------
    'Wscript.Echo "Script completed in " & GetElapsedTime

    Function GetElapsedTime
     
         Const SECONDS_IN_DAY = 86400
         Const SECONDS_IN_HOUR = 3600
         Const SECONDS_IN_MINUTE = 60
         Const SECONDS_IN_WEEK = 604800
      
        dtmEndTime = Timer
     
          seconds = Round(dtmEndTime - dtmStartTime, 2)
         If seconds < SECONDS_IN_MINUTE Then
             GetElapsedTime = seconds & " seconds "
             Exit Function
         End If
         If seconds < SECONDS_IN_HOUR Then
            minutes = seconds / SECONDS_IN_MINUTE
             seconds = seconds MOD SECONDS_IN_MINUTE
             GetElapsedTime = Int(minutes) & " minutes " & seconds & " seconds "
             Exit Function
         End If
         If seconds < SECONDS_IN_DAY Then
             hours = seconds / SECONDS_IN_HOUR
             minutes = (seconds MOD SECONDS_IN_HOUR) / SECONDS_IN_MINUTE
             seconds = (seconds MOD SECONDS_IN_HOUR) MOD SECONDS_IN_MINUTE
             GetElapsedTime = Int(hours) & " hours " & Int(minutes) & " minutes " & seconds & " seconds "
             Exit Function
         End If
         If seconds < SECONDS_IN_WEEK Then
             days = seconds / SECONDS_IN_DAY
             hours = (seconds MOD SECONDS_IN_DAY) / SECONDS_IN_HOUR
             minutes = ((seconds MOD SECONDS_IN_DAY) MOD SECONDS_IN_HOUR) / SECONDS_IN_MINUTE
             seconds = ((seconds MOD SECONDS_IN_DAY) MOD SECONDS_IN_HOUR) MOD SECONDS_IN_MINUTE
             GetElapsedTime = Int(days) & " days " & Int(hours) & " hours " & Int(minutes) & " minutes " & seconds & " seconds "
             Exit Function
         End If
     End Function

    wscript.quit

     

     

    And this is what the altdrivemap.csv file looks like

    edward.user,Z:,\\servername.domain.name\sharename
    sally.uzer,X:,\\servername1.domain.name\sharename3

    etc...

    Some credit goes to Rob Dunn and Dave Rossi on the spiceworks forums for helping with the script.

    http://community.spiceworks.com/topic/313953-vbs-read-csv-and-map-drives-based-on-username

    Saturday, May 18, 2013 3:00 AM
  • You newbie guys seem to always like to do everything the hard way.

    Hey - if it makes you happy go for  it.


    ¯\_(ツ)_/¯

    Saturday, May 18, 2013 3:48 AM
  • This won't work:

    strCSV = "%logonserver%\netlogon\altdrivemap.csv"

    You cannot send an environment variable  to the FSO.  You must translate it first.  Only CMD.EXE understand variables.

    Placing 'On Error' at the beginning of any script is just plain foolish.  See the write up in the script center on how to use error management.


    ¯\_(ツ)_/¯

    Saturday, May 18, 2013 3:57 AM
  • Yep you're right about both.  I meant to obscure the domain name.  We used \\domain.name\netlogon\altdrivemap.csv

    On error does exactly what we want.   To keep on going without hanging up the logon process.  Tablets, Kiosks, Citirx, etc...

    Saturday, May 18, 2013 4:06 AM
  • Yep you're right about both.  I meant to obscure the domain name.  We used \\domain.name\netlogon\altdrivemap.csv

    On error does exactly what we want.   To keep on going without hanging up the logon process.  Tablets, Kiosks, Citirx, etc...

    On error does not do that.  You need to update you knowledge about how that works.

    I have written Windows logon scripts for almost 20 years.  Believe me you are off her.

    Here is a better approach.  It is close but needs some error handling but only on the file  and the mappings.

    I will post an example of how we do this.  In the meantime look in the script center for examples of how to implement error handling correctly.

    ' this needs to be translated by the shell
    Const strCSV = "%logonserver%\netlogon\altdrivemap.csv"
    
    dtmStartTime = Now
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    set objNetwork = WScript.CreateObject("WScript.Network")
    strUserName = lcase(objNetwork.UserName)
      
    Set objCSVFile = objFSO.OpenTextFile(strCSV)
    Do while NOT objCSVFile.AtEndOfStream
    
     	arr = split(objCSVFile.ReadLine,",") 'Split the values by their delimiter
     	
     	'Match the username
     	If strusername = trim(lcase(arr(0))) then
     	
      		'---------Disconnect any drive letters that will be mapped
      		If (objFSO.DriveExists(arr(1)) = True) Then
       			objNetwork.RemoveNetworkDrive arr(1), True, True
      		End If
      		
      		'Notification of pending drive mapping assignments
       		'Wscript.Echo "Existing Drive Mapping" & arr(1) & arr(2) 
      		objNetwork.MapNetworkDrive arr(1), arr(2), False
      		
     	End If
     
    Loop
     
    objCSVFile.Close
     
    dEndTime = Now
    elapsedTime = DateDiff("s",dStartTime,dEndTime)
    WScript.Echo "Script completed in " & elapsedTime & " seconds"


    ¯\_(ツ)_/¯



    • Edited by jrv Saturday, May 18, 2013 4:14 AM
    • Proposed as answer by jrv Tuesday, August 13, 2013 10:04 PM
    • Marked as answer by Just Karl Friday, October 4, 2013 2:05 AM
    Saturday, May 18, 2013 4:13 AM
  • Learn to use white space to make you scripts more understandable.  Use comments to add information and not to repeat the obvious.  If a line of code is OpenTextFile(....) then it does not need a comment that says "Open the text file".  It adds nothing but what we call visual noise to the script.

    ¯\_(ツ)_/¯

    Saturday, May 18, 2013 4:18 AM
  • Here is how to prevent a logon script from hanging a logon. It leaves an exitcode that can be logged by the logon process. We can look in the logs to see why the script failed.  More sophisticated logging can also be used like logging status to a file.

    On Windows Vista and later you can get detailed reports from each logon script about time lapsed and errors generated.

    ' this needs to be translated by the shell
    Const strCSV = "%logonserver%\netlogon\altdrivemap.csv"
    
    dtmStartTime = Now
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    set objNetwork = WScript.CreateObject("WScript.Network")
    strUserName = lcase(objNetwork.UserName)
    
    On Error Resume Next
    Set objCSVFile = objFSO.OpenTextFile(strCSV)
    If Err Then WScript.Quit ' exit with error code 1
    Do while NOT objCSVFile.AtEndOfStream
    
     	arr = split(objCSVFile.ReadLine,",") 'Split the values by their delimiter
     	if Err Then WScript.Quit 2
     	
     	'Match the username
     	If strusername = trim(lcase(arr(0))) then
     	
      		'---------Disconnect any drive letters that will be mapped
      		If (objFSO.DriveExists(arr(1)) = True) Then
       			objNetwork.RemoveNetworkDrive arr(1), True, True
       			If Err Wscript.Quit 3
      		End If
      		
      		'Notification of pending drive mapping assignments
       		'Wscript.Echo "Existing Drive Mapping" & arr(1) & arr(2) 
      		objNetwork.MapNetworkDrive arr(1), arr(2), False
      		If Err Then WScript.Quit 4
      		
     	End If
     
    Loop
     
    objCSVFile.Close
     
    dEndTime = Now
    elapsedTime = DateDiff("s",dStartTime,dEndTime)
    WScript.Echo "Script completed in " & elapsedTime & " seconds"


    ¯\_(ツ)_/¯


    • Edited by jrv Saturday, May 18, 2013 4:25 AM
    Saturday, May 18, 2013 4:24 AM