VBScript/Login Script

Joined
Dec 10, 2006
Messages
540
I am currently working on an addition to my Login Script for Active Directory. I am working on setting up Backup storage. I have a share on Server02 that is at 'backup_storage'. Each user will have a folder under this share.
So the path will be \\server02\backup_storage\user\%User Name%
The problem is I want that folder to be checked to see if it exists, and if not, have it be created. I am not skilled at VBScript that much, so if someone could lend a hand, I would appreciate it. I would also like to know how to only map it if the member is part of the group "Backup User," could someone explain this, I haven't been able to upturn a defiant way to do this. This is the stuff I have that pertains to this:
Code:
Option Explicit
Dim objNetwork, strUserName
Set objNetwork = CreateObject("WScript.Network")
strUserName = objNetwork.UserName
On Error Resume Next

'-- Remove Drives --'
objNetwork.RemoveNetworkDrive "R:"

'-- Map Drives --'
objNetwork.MapNetworkDrive "R:", "\\server02\backup_storage\user\" & strUserName

Wscript.Quit
 
I've got scripts that do exactly what you're asking... I'll cut and paste some of the logic here for you.

re: Checking Group membership and Mapping Drives

You can pull the groups a user belongs to directly from Active Directory. Once you have the groups, you can loop through each one and see if thats the group you want. If it is, then you can call a function to map a drive. If it isn't a group you want to worry about, you can just ignore it.

Cool thing about doing it this way is you can have multiple drive mappings, and you can even include other goodies like file copies or registry changes if you need to do so. For example, I have a group that needs a certain registry setting defined -- if they log in, no matter what machine, it drops that key into their registry for them and maps some drives.


Code:
Set oSysInfo = CreateObject("ADSystemInfo")
strADSPath   = oSysInfo.Username                ' Get the username from AD
Set oUser    = GetObject("LDAP://" & strADSPath)' then bind an object to the user 

For Each oGroup in oUser.Groups                 ' Loop through each group  
    strGroup = Trim(Right(oGroup.Name,len(oGroup.Name)-3))

    Select Case strGroup
      Case "Marketing"
         MapDrive "Q:\", "\\MyServer\Shares\Marketing"
      Case "Sales"
         MapDrive "Q:\", "\\MyServer\Shares\Sales"
    End Select

MapDrive is a function that just maps a driver.

Code:
 ==============================================================================
' Function: MapDrive (strLetter, strUNC)
'   strLetter : Windows Drive letter to map -- will be removed if exists
'   strUNC    : Path to map the drive to
' ------------------------------------------------------------------------------
  Function MapDrive(strLetter, strUNC)
  Set oNetwork = CreateObject("WScript.Network")      
  On error resume next
    If oFSO.DriveExists(strLetter) then oNetwork.RemoveNetworkDrive(strLetter)
	If oFSO.DriveExists(strLetter) then 
	  Exit Function
	End If
	oNetwork.MapNetworkDrive strLetter, strUNC

  On error goto 0		
  End Function
' ==============================================================================

re: Verifying a directory structure.
This isn't that difficult to do, either. In my scripts, I use a function to validate a directory structure. You pass the function a path, and the path gets turned into an array with the split function. You can split using the "\" character so you know each subdirectory name. So if you passed it C:\Windows\System32 it would give you 3 elements.

Element 1 = C:
Element 2 = Windows
Element 3 = System32

To keep things dynamic you can set up a loop from the lbound and ubound of the array (the lowest element and the highest element). You will want to keep things dynamic because you won't always know the upper bounds of the array.

Now that you've got your loop established, you just check for the existance of each component.

First, Check for element 1: C:\
Second, Check for element 1 & Element 2: C:\Windows
Third, Check for Element 1 & Element 2 & Element 3: C:\Windows\System32

Of course, you will have to manipulate the strings a bit to add in the \ character. Here's the code that I use:

Code:
ValidateDirectory "C:\Temp\1\2\3\"

' ==========================================================================
  Function ValidateDirectory(strDirectory)
  ' strDirectory: The name of the directory to validate.  
  ' ------------------------------------------------------------------------
  ' Define Variables
  ' ----------------
    Dim strBasePath : strBasePath = ""
    Dim iDirectory  : iDirectory  = 0

    Dim oFSO
      Set oFSO = CreateObject("Scripting.FileSystemObject")


  ' Trim the directory of spaces to be safe:
    strDirectory = Trim(strDirectory)

  ' Remove the trailing \ if it exists
    If Right(strDirectory,1) = "\" then
      strDirectory = Left(strDirectory, len(strDirectory) - 1)
    End If

  ' Split the Directory Path into an Array
    arrDirectory = Split(strDirectory, "\")


  ' Loop through each Directory in the Path
    For iDirectory = lbound(arrDirectory) to ubound(arrDirectory)
      strBasePath = strBasePath & arrDirectory(iDirectory) & "\"

      Select Case iDirectory
        Case lbound(arrDirectory) ' First element will be the drive
          If Not oFSO.DriveExists(strBasePath) Then
            ValidateDirectory = False
            Exit Function
          End If

        Case Else
           If Not oFSO.FolderExists(strBasePath) Then
             oFSO.CreateFolder(strBasePath)

             If Not oFSO.FolderExists(strBasePath) Then
               ValidateDirectory = False
               Exit Function
             End If

           End If

      End Select
    Next
   

  End function
' ==========================================================================
 
Demon1000, I was trying to use your MapDrive function, but when I do, I run into the problem of not having oFSO set. Can I see what that variable looks like?

Edit: I believe it is just a Set oFSO = CreateObject("Scripting.FileSystemObject")
 
Demon1000, I was trying to use your MapDrive function, but when I do, I run into the problem of not having oFSO set. Can I see what that variable looks like?
It should just be:
set oFSO=CreateObject("Scripting.FileSystemObject")
 
I can't seem to adapt the folder checking to UNC paths on account of the usage of DriveExists and FolderExists. Anyone have any light to shed?
 
Hrm...FolderExists shouldn't have any problems with a UNC. I bet you're having problems with some of the logic.

The first thing we do is break the path down into certain elements... and it splits the array based on the \ character. So if you have C:\Windows\System32, you get this:

Element 1: C:
Element 2: Windows
Element 3: System32

However, passing that function a UNC would look a little different. Say we passed it, \\MyComputer\C$\Windows\System32

Element 1: (nothing)
Element 2: MyComputer
Element 3: C$
Element 4: Windows
Element 5: System32

You can see the problem when we break it down like that. Element 1 has no value because of the prefix of \\ on the UNC. When the logic checks to existence of the drive, it uses Element 1 for this -- if it's nul, it's going to fail.

Typically, we do want to confirm that the drive exists before we do anything else, but not when dealing with a UNC. In fact, we don't really care about the first element because we can't do much of anything with it. You could ping it and check to see if it is there, but that seems like a waste of time to me.

The best way to deal with the UNC prefix is to strip it off before we split it into it's elements. In the previous code, we did trimmed off the spaces (something I do just in case -- it never hurts!) and stripped off the last character if it was a \. Well, we're going to do the same thing, but in this case, we're going to strip off the front two characters if they match \\. So we have to add something like this before we create our array.

Strip it off...
Code:
  ' Remove the begining \\ if it exists
    If Left(strDirectory,2) = "\\" then
      strDirectory = Right(strDirectory, Len(strDirectory) - 2)
    End If

Then later on in the code, we add it back to the variable that we use to check to see if the folders exist.

Code:
  ' Now we need to fudge the strBasePath variable to contain the
  ' first part of the unc.   
     strBasePath = "\\" & arrDirectory(0) & "\"

Now, when we start looping through the elements in the array, we're going to skip the first one, as it's going to be already added to our variable with the proper elements and we can't really do anything with it.

Code:
    For iDirectory = lbound(arrDirectory)+ 1 to ubound(arrDirectory)
      strBasePath = strBasePath & arrDirectory(iDirectory) & "\"
    .
    .
    .
   Next

(notice the +1 that appears after the lbound(arrDirectory). That skips the first element, and moves right onto the second, which should be our share. It will then tack on the share name to the server and add a trailing \.

Of course, we'll have to take some more considerations for parsing a UNC vs a drive, because there are more rules we have to follow:

1] We need at least two elements: A server and a Share.
2] If we ONLY have 2 elements, we can't create anything, but we can validate it and see if the server has that share.
3] If we have more than 3 elements, we can create directories, ASSUMING we have rights.

I didn't have a lot of time to mess around with it, but all that logic put together should look something like this:

Code:
' ==========================================================================
  Function ValidateUNC(strDirectory)
  ' strDirectory : The UNC to validate
  ' ------------------------------------------------------------------------
  ' Define Variables
  ' ----------------
    Dim strBasePath : strBasePath = ""
    Dim iDirectory  : iDirectory  = 0

    Dim oFSO
      Set oFSO = CreateObject("Scripting.FileSystemObject")


  ' Trim the directory of spaces to be safe:
    strDirectory = Trim(strDirectory)

  ' Remove the trailing \ if it exists
    If Right(strDirectory,1) = "\" then
      strDirectory = Left(strDirectory, len(strDirectory) - 1)
    End If

  ' Remove the begining \\ if it exists
    If Left(strDirectory,2) = "\\" then
      strDirectory = Right(strDirectory, Len(strDirectory) - 2)
    End If

  ' Split the Directory Path into an Array
    arrDirectory = Split(strDirectory, "\")

  ' We need to check and see if we have at least two elements
  ' in our array.  If not, we don't havea proper UNC (\\server\share).
    If Ubound(arrDirectory) + 1 < 2 Then
      ValidateUNC = False
      Exit Function
    End If

  ' Now we need to fudge the strBasePath variable to contain the
  ' first part of the unc.   
     strBasePath = "\\" & arrDirectory(0) & "\"

  ' Loop through each Directory in the Path
    For iDirectory = lbound(arrDirectory)+ 1 to ubound(arrDirectory)
      strBasePath = strBasePath & arrDirectory(iDirectory) & "\"
      
      Select Case iDirectory
        Case lbound(arrDirectory) + 1
          ' First element will be the Server name
          ' We really can't do anything with just the server name,
          ' so we'll ignore it until we get a share name, too.          
        Case lbound(arrDirectory) + 2
          ' We really can't create a share, but we can check
          ' to see if it exists.  At this point, we have the
          ' Server and Share in the form \\Server\Share.  So check
          ' it and see if it exists.  If not, just bail out.
          If Not oFSO.FolderExists(strBasePath) Then
            ValidateUNC = False
          End If

        Case Else
          ' At this point, we should have our path.  It should be in 
          ' the form of \\server\share\path1\path2\path3 etc.  Since
          ' we've already validated the server and share, we can
          ' start creating directories if needed... assuming we have
          ' the proper rights.

           If Not oFSO.FolderExists(strBasePath) Then
             oFSO.CreateFolder(strBasePath)

             If Not oFSO.FolderExists(strBasePath) Then
               ' We tried to created it, and if we made it here
               ' it didn't work.  So just bail out.
               ValidateUNC = False
               Exit Function
             End If

           End If

      End Select	  
    Next
	
	  Select Case oFSO.FolderExists(strBasePath) 
		Case True
		  ValidateUNC = True
		Case Else
		  ValidateUNC = False
	  End Select
   
  End Function
' ==========================================================================

You'll notice that this is pretty close to the previous function. You COULD make one Function to check both a drive and a UNC. It would just require a little more logic and a variable to keep track of what kind of Validation you're doing (drive or unc). I'd trim the spaces off either side then look at the first two characters. If the first two characters are \\, then you're dealing with a UNC. If it's not, then look at the second character and see if it's a :. If it's a : then you're dealing with a drive.

I don't really have the time to throw it all into one function right now, but it would be good practice for you to do.
 
Remind me I owe you a drink sometime. I believe I could have modified it to work, but I haven't programmed anything in sometime, plus I don't know the usage much at all for VBscript. Thanks again mate, I appreciate it, and it works perfectly.
 
Question, why so much code for folder validation? Your map drive function should return an error so you know it's successful instead of ignoring it. If successful then you know the path is there and you would then just check for the user folder 'strBackupPath & strUserName' (assuming you created a strBackupPath variable) using FolderExists.

I could see the usefulness in that routine if you were validating a form input but in this case and even for validation for the most part, about three or so lines of code will tell you if the folder is not valid.

I'm not picking on you, it just looks a bit inefficient. Let me know if I'm missing something here.
 
Question, why so much code for folder validation? Your map drive function should return an error so you know it's successful instead of ignoring it. If successful then you know the path is there and you would then just check for the user folder 'strBackupPath & strUserName' (assuming you created a strBackupPath variable) using FolderExists.

I could see the usefulness in that routine if you were validating a form input but in this case and even for validation for the most part, about three or so lines of code will tell you if the folder is not valid.

I'm not picking on you, it just looks a bit inefficient. Let me know if I'm missing something here.
Your method wouldn't work well if you had something like \\Server\Share\Dir1\Dir2\Dir3\Dir4 to check, because if Dir2 didn't exist your method wouldn't know that was the fault in the execution. It would believe it would be Dir4 that didn't exist. So it would try to create that but couldn't because Dir3 doesn't exist, which wouldn't be created because Dir2 didn't exist. So to boil down to it, your method would end up to be able the same exact length.
 
Question, why so much code for folder validation? Your map drive function should return an error so you know it's successful instead of ignoring it. If successful then you know the path is there and you would then just check for the user folder 'strBackupPath & strUserName' (assuming you created a strBackupPath variable) using FolderExists.

I could see the usefulness in that routine if you were validating a form input but in this case and even for validation for the most part, about three or so lines of code will tell you if the folder is not valid.

I'm not picking on you, it just looks a bit inefficient. Let me know if I'm missing something here.

The routine is very dynamic. It doesn't care how many sub directories you throw at it. Because of this, we need to validate each element of the UNC starting from the Share and moving to the final directory in the path we want to validate. If we didn't do this, we wouldn't know why we had an error (specifically, which directory didn't exist in the path?).

Using your method, you would map the drive. If the function returned false, you would need to know why, so you would then pass it to an error handling routine. The error handling routine would have to walk through the UNC and validate each part of it. It would have to determine if the Share existed on the Computer, then it would have to verify each directory after the share, and create them if possible. Then it would have to call the map drive function again to establish the drive.

I choose to include all that error checking right in the first call and not worry about creating an error handling routine. It makes the code a little more stand-alone.

We can't create multiple directories at a time. If we did something like this:

CreateFolder "C:\1\2\3\4\5\6"

We would need to make be certain that C:\1\2\3\4\5 already existed, or CreateFolder would fail. Whether you put the verification logic in the creation routine, or in the error handler, it's going to be a bit more than 3 lines of code. I just think it makes a little more sense to have the validation right in the creation routine.






Besides... if we look at what the OP wanted, he asked for a way to see if a UNC path existed, and if it didn't to created it. Then later on, he inquired about a way to map a drive with VB script. He's copying files from one location to this specified backup directory -- no need to actually map a drive to do that, so I took the question as two different requests:

1] How do I validate a UNC?
2] How do I map a drive based on group membership?
 
Sorry, been busy at work trying to get things in order so I don't receive any calls while on vacation. I get what you were trying to accomplish. I was in solve a problem mode when I was posting so I commented based on the OP's original question which at the time didn't indicate to me that there would be a need to validate more than one level of subfolders. Your code makes total sense for the scenario he pointed out later on in response to my post and of course it doesn't hurt even if it's one level of subfolders. I didn't think it was wrong just a bit much for checking for the existence of a subfolder within a known and pre-existing location (my assumption that it's pre-existing).

Each user will have a folder under this share.
So the path will be \\server02\backup_storage\user\%User Name%"

Going by that, \\server02\backup_storage\user should already exist unless user is dynamic but I don't see a reason why it would be. That leaves the %UserName%" subfolder as the only one to check.

I was just curious, that's all.
 
Back
Top