Page 1 of 1 1
Topic Options
#207576 - 2013-08-09 10:27 AM UDF - Mapping Drive Via INI File
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Guys I'm using the following UDF (I did not create this)

The UDF maps drives out drives from an INI file based on active directory group names.
The UDF is working and mapping the driver correctly , however I have discovered that once it matchs you to 1 group (the first match within the INI file) it exits the script. I need the script to continue checking through the full INI file connecting any drives that you match to. I've looked through the script but I haven't been able to figure out how I can do this. Any help would be great.
 Code:
Function ConnectSpecialShares()
  ;******************************
  ; SpecialShares
  ;******************************
  Dim $ShareEntries
  Dim $numShareEntries
  $numShareEntries = 1
  Progress("Connecting Special Shares")
  DbgMessage("Info", "Connecting Special Shares")
  DbgMessage("Info", "  SpecialSharesinifile = " + $SpecialSharesIniFile)
  If Exist($SpecialSharesIniFile)
  ;Walk through SpecialSharesIniFile and generate array
  $MainGroup = "ALLSTAFF"
  $Handle = FreeFileHandle()
  If $Handle > 0
    If Open($Handle, $SpecialSharesIniFile, 2) = 0
      $line = ReadLine($Handle)
      While @ERROR = 0
        If Left($line, 1) = "["
          $GroupName = SubStr($line, 2, Len($line) - 2)
          If InGroup($GroupName)
            ReDim preserve $ShareEntries[$numShareEntries]
            $ShareEntries[$numShareEntries] = $GroupName
            $numShareEntries = $numShareEntries + 1
          EndIf
        EndIf
        $line = ReadLine($Handle)
      Loop
      Close($Handle)
    EndIf
  EndIf
  For $shares = 1 to UBound($ShareEntries)
    For $x = 1 to 10
      $DriveDefinition = ReadProfileString($SpecialSharesIniFile, $ShareEntries[$shares], "drive" + $x)
      If @ERROR = 0
        If $DriveDefinition <> ""
          ConnectShare($DriveDefinition)
        EndIf
      Else
        Return
      EndIf
    Next
  Next
  EndIf
EndFunction



Here is what the INI file looks like

;================================================================
; GROUP 1
;=Start==========================================================
[AD.GROUP1]
Drive1="P:, \\SERVERA\C$, "
Drive2="R:, \\SERVERB\C$, "
;=End============================================================
;================================================================

;==========================================
;GROUP 2
;=Start====================================
[AD.GROUP2]
Drive1="G:, \\SERVERC\DATA.MS1$, "
Drive2="B:, \\SERVERD\DATA.WTA$, "
;=End======================================


;================================================================
; GROUP 3
;=Start==========================================================
[AD.GROUP3]
Drive1="X:, \\SERVERE\ALLDATA$, HPC Servers"
Drive2="V:, \\SERVERF\ALLDATA$, HPC DR Server"
;=End============================================================
;================================================================







Edited by Glenn Barnas (2013-08-09 12:40 PM)
Edit Reason: Please use CODE tags

Top
#207577 - 2013-08-09 01:00 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
Geez - talk about complicated! ;\)

Untested, but this concept would be much simpler:
 Code:
If Exist($SpecialShareIniFile)
  ; get list of groups (sections) from ini file
  $aGroups = Split(ReadProfileString($SpecialShareIniFile), Chr(10))
  For Each $Group in $aGroups      ; enumerate groups from INI array
    If InGroup($Group)             ; member - process mappings
      $aMappings = Split(ReadProfileString($SpecialShareIniFile, $Group), Chr(10))
      For Each $Mapping in $aMappings
        $aDriveData = Split(ReadProfileString($SpecialShareIniFile, $Group, $Mapping), ',')
        Use $aDriveData[0] $aDriveData[1] ; or pass the raw data read directly to your mapping func
      Next
    EndIf
  Next
EndIf
This could be further simplified by changing your INI format from
DRIVE1=D:,path
to
D:=Path
allowing you to have direct access to the Drive Letter and Path without a subsequent Split().

You'll need to adapt this logic slightly to your specific needs, but eliminate the whole File Open/Read for an INI.. Also look at the EnumINI UDF, which can do most of this work for you, returning an array directly from the INI. Simplify the logic to make it easier to diagnose.

This is a Function, not a Subroutine. Replace the "Return" with an "Exit @ERROR", as Return is used to return from a subroutine.

Finally, you're calling an external function to map the drive - it might be ending there..

Glenn

PS - Gotta hit the road - I'll revisit this and clean it up in a bit...
_________________________
Actually I am a Rocket Scientist! \:D

Top
#207578 - 2013-08-09 01:05 PM Re: UDF - Mapping Drive Via INI File [Re: Glenn Barnas]
BradV Offline
Seasoned Scripter
****

Registered: 2006-08-16
Posts: 687
Loc: Maryland, USA
Glenn beat me to it. I was going to suggested throwing away that script and to re-write it with readprofilestring. No sense using an INI file if you are just going to brute force read it. \:\)
Top
#207579 - 2013-08-09 04:21 PM Re: UDF - Mapping Drive Via INI File [Re: BradV]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
OK - here's a replacement function that I was able to test. I created dummy functions for Progress, DbgMessage, and ConnectShare (as shown below) that perform simple display of the data. I updated your INI file to use two real groups to verify that all will work. I also used the EnumINI UDF (download latest version from the Resources pages on my web site) to simplify working with the INI file. EnumINI performs the following tasks:
  • Called with just the INI file name, it returns an array of section names;
  • Called with the file name AND a section name, it returns an array of value names in that section.


Here's the code to test the replacement function:
 Code:
Call 'K:\KixLib\EnumIni.kxf'

Global $SpecialSharesIniFile
$SpecialSharesIniFile = '.\special.ini'

ConnectSpecialShares(); Call the function being tested & show the error result message
@SERROR ?


; Updated ConnectSpecialShares function:
Function ConnectSpecialShares()

  Progress("Connecting Special Shares")
  DbgMessage("Info", "Connecting Special Shares")
  DbgMessage("Info", "  SpecialSharesinifile = " + $SpecialSharesIniFile)

  ; Exit now if the file doesn't exist
  If Not Exist($SpecialSharesIniFile) Exit 2 EndIf

  ; Get a list of sections from the ini file using the EnumINI UDF
  $aSections = EnumINI($SpecialSharesIniFile)

  ; enumerate the sections (which are AD group names)
  For Each $Group in $aSections

    ; check group membership
    If InGroup($Group)
      ; get the list of drive map definitions
      $aMappings = EnumINI($SpecialSharesIniFile, $Group)

      ; Enumerate the mappings and make the connection using the ConnectShare UDF
      For Each $Share in $aMappings
        $DriveDefinition = ReadProfileString($SpecialSharesIniFile, $Group, $Share)
        ConnectShare($DriveDefinition)
      Next
    EndIf
  Next

  Exit 0

EndFunction



; Dummy support functions follow

Function ConnectShare($Def)
  $aDat = Split($Def, ',')
  'Mapping ' $aDat[0] ' to ' $aDat[1] ?
  Exit 0
EndFunction

Function Progress($Msg)
  'Progress: ' $Msg ?
EndFunction

Function DbgMessage($Lvl, $Msg)
  'Debug: ' $Lvl ' - ' $Msg ?
EndFunction
Here's the result of the test:
 Code:
Progress: Connecting Special Shares
Debug: Info - Connecting Special Shares
Debug: Info -   SpecialSharesinifile = .\special.ini
Mapping P: to  \\SERVERA\C$
Mapping R: to  \\SERVERB\C$
Mapping G: to  \\SERVERC\DATA.MS1$
Mapping B: to  \\SERVERD\DATA.WTA$
The operation completed successfully.
Do not use the CALL statement - copy/paste the EnumINI UDF directly into your script (anywhere, but usually at the end).

Glenn



_________________________
Actually I am a Rocket Scientist! \:D

Top
#207580 - 2013-08-09 05:48 PM Re: UDF - Mapping Drive Via INI File [Re: Glenn Barnas]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Thanks Glenn

I'll have a play with this and see how I go

Should I leave the make up of my INI file the same but remove the apart "drive1="

Top
#207581 - 2013-08-09 05:55 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
No - the UDF I wrote above uses your standard INI file format..

Keep in mind that this (or your old) logic has no method to deal with duplicate mappings. If a User is a member of two or more groups and the groups both have the same drive letter defined, the last one will re-map the first one.

My Universal Login Script uses an ini for management, but uses a single record for each resource. You can specify multiple groups per record. It also handles priority settings to resolve resource definition conflicts.

If you still have problems, you should post your ConnectShare UDF.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#207582 - 2013-08-12 10:25 AM Re: UDF - Mapping Drive Via INI File [Re: Glenn Barnas]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Hi Glenn , where can I see an example of your logon script management ?
Top
#207583 - 2013-08-12 10:39 AM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
HI Glenn

I've setup your script

Its run through and I get an error: array references out of bounds!
Line: 80

Line 80 in my script is : 'Mapping ' $aDat[0] ' to ' $aDat[1] ?

Top
#207584 - 2013-08-12 02:08 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
You can get info about the Universal Login Script from my web site here. The PDF user guide can be downloaded directly from that page, or you can register your email and download the entire package. The script is free for small businesses and reasonably priced for larger enterprises, and both include various levels of support.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#207585 - 2013-08-12 02:13 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
 Originally Posted By: Fergieman
HI Glenn

I've setup your script

Its run through and I get an error: array references out of bounds!
Line: 80

Line 80 in my script is : 'Mapping ' $aDat[0] ' to ' $aDat[1] ?

It looks like you included my dummy functions!! These were included only because you didn't post them, and I needed something to display data.

Only include the main "ConnectSpecialShares" function from my test script, and don't forget to download and insert the EnumINI UDF from my web site's resource pages into your script.

Also, I'd get rid of the quotes in the INI file - there's no need for them, or for the last comma unless there's a third (and optional) parameter used by your mapping UDF.

If you still have problems, post your entire script.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#207586 - 2013-08-12 03:04 PM Re: UDF - Mapping Drive Via INI File [Re: Glenn Barnas]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Hi Glenn

I'm pretty weak at scripting but trying to learn. Let me post up the ConnectDrives part and let you have a look. Again , I didn't create it.

Top
#207587 - 2013-08-12 03:06 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Ok , here is function

 Code:
Function ConnectShare($DriveDefinition)
  $DriveLetter = SubStr($DriveDefinition, 1, InStr($DriveDefinition, ",") - 1)
  $DriveDefinition = LTrim(RTrim(SubStr($DriveDefinition, InStr($DriveDefinition, ",") + 1)))
  $Share = LTrim(RTrim(SubStr($DriveDefinition, 1, InStr($DriveDefinition, ",") - 1)))
  $ShareDesc = LTrim(RTrim(SubStr($DriveDefinition, InStr($DriveDefinition, ",") + 1)))
  
  ;Check Use List ;    $ListOfConnection=USE LIST
  Progress("Connecting " + $DriveLetter + " to " + $Share)
  DbgMessage("Info", "  - Connecting " + $DriveLetter + " on " + $Share)
  Use $DriveLetter $Share
  If @ERROR <> 0
    If @ERROR = 85
      DbgMessage("Info", "  - Disconnecting " + $DriveLetter + " on " + $Share)
      Use $DriveLetter /delete /persistent
      If @ERROR <> 0
        DBGMessage("DisMountError", $DriveLetter)
      EndIf
      If ($NT_mode = "no")
        $returnCode = DelKey("HKEY_CURRENT_USER\Network\Persistent\" + $DriveLetter)
      EndIf
      Sleep $SleepTime
      DbgMessage("Info", "  - ReConnecting " + $DriveLetter + " on " + $Share)
      Use $DriveLetter $Share
      If @ERROR <> 0
        DbgMessage("MountError", "  - Mount Error " + $DriveLetter + " on " + $Share)
        DBGMessage("MountError : ", @ERROR = @SERROR)
        DbgMessage("Info", "  - Mounting on Next Free Letter : " + $Share)
        Use * $Share
      EndIf
    Else
      DBGMessage("MountError : ", $DriveLetter + " on " + $Share)
      DBGMessage("MountError : ", @ERROR = @SERROR)
      DbgMessage("Info", "  - Mounting on Next Free Letter : " + $Share)
      Use * $Share
      If $DebugFlag = 1
        Sleep 3
      Else
        Sleep $SleepTime
      EndIf
    EndIf
  EndIf
EndFunction


Edited by Glenn Barnas (2013-08-12 03:35 PM)
Edit Reason: add code tags

Top
#207593 - 2013-08-13 01:13 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
Not very efficient, and the error handling isn't the best, but I don't see any real logic problem. For diagnosis, you might try simplifying this before adding capabilities back to the function.

The function takes one argument that is then broken into 3 values - the drive letter, the share path, and a description. The description is not used, so can be eliminated from this code and possibly from your INI file (trailing comma). I've simplified the beginning of the function to illustrate what I mean.
 Code:
Function ConnectShare($DriveDefinition)

  Dim $Rc

  ; split string on commas
  $DriveDefinition = Split($DriveDefinition, ',')
  ; assign array elements to working vars
  $DriveLetter = $DriveDefinition[0]
  $Share       = $DriveDefinition[1]

  ;Check Use List ;    $ListOfConnection=USE LIST  <- THIS IS NOT DONE SO REMOVE THIS COMMENT!!!
  Progress("Connecting " + $DriveLetter + " to " + $Share)
  DbgMessage("Info", "  - Connecting " + $DriveLetter + " on " + $Share)
  Use $DriveLetter $Share

  If @ERROR
    If @ERROR = 85
      DbgMessage("Info", "  - Disconnecting " + $DriveLetter + " on " + $Share)
      Use $DriveLetter /delete /persistent
      If @ERROR
        DBGMessage("DisMountError", $DriveLetter)
      EndIf

      If ($NT_mode = "no")
        $Rc = DelKey("HKEY_CURRENT_USER\Network\Persistent\" + $DriveLetter)
      EndIf

      Sleep $SleepTime
      DbgMessage("Info", "  - ReConnecting " + $DriveLetter + " on " + $Share)
      Use $DriveLetter $Share
      If @ERROR <> 0
        DbgMessage("MountError", "  - Mount Error " + $DriveLetter + " on " + $Share)
        DBGMessage("MountError : ", @ERROR = @SERROR)
        DbgMessage("Info", "  - Mounting on Next Free Letter : " + $Share)
        Use * $Share
      EndIf
    Else
      DBGMessage("MountError : ", $DriveLetter + " on " + $Share)
      DBGMessage("MountError : ", @ERROR = @SERROR)
      DbgMessage("Info", "  - Mounting on Next Free Letter : " + $Share)
      Use * $Share
      If $DebugFlag = 1
        Sleep 3
      Else
        Sleep $SleepTime
      EndIf
    EndIf
  EndIf
EndFunction
I have concerns about the use of undeclared variables in functions, which likely means that they are global in your main script. There is no isolation between functions and the main script, resulting in problems that are hard to diagnose. Variables should be declared in the main script, and values passed to the functions. It seems like the person that wrote this simply put a function definition around an old subroutine rather than doing a proper rewrite. Also - what's with all the Sleep commands? Usually, you'd want the login script to run as fast as possible. My ULS can run in as little as 0.875 seconds.

With the global variable issue and without seeing the entire script, there isn't much more we can do to diagnose. Honestly, you should be considering a rewrite of this to improve the reliability.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#207594 - 2013-08-13 01:41 PM Re: UDF - Mapping Drive Via INI File [Re: Glenn Barnas]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Thanks Glenn

A bit of history - there were no login scripts in the company I joined (other than batch files).

I knew kixs was the way forward but I have little or no scripting skills , using this forum and a few others I got a login script and modified to work within my environment.

In terms of the sleep time , no idea what that is in there as I didn't script this but yes I would like it to run "faster".

Ok , Im probably not getting the drives to map based on the fact that other variables are declared elsewhere.

Top
#207595 - 2013-08-13 01:47 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Let me just try and get this working on it's own.

the ini contents look like this
[App.7Zip920]
J:=\\isis\place$

[IT.Dept]
K:=\\isis\it$

Top
#207596 - 2013-08-13 02:02 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Ok , seems that it can't see the drive letter.

Seems to be something within this part I think - the drive letter part is wrong (if I change it to $DriveDefinition[1] it bombs out.

; split string on commas
$DriveDefinition = Split($DriveDefinition, ',')
; assign array elements to working vars
$DriveLetter = $DriveDefinition[0]
$Share = $DriveDefinition[0]

Top
#207598 - 2013-08-13 02:48 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
That's different from your original INI file. While the "D:=Path" is easier to deal with, it requires code changes. Put your INI file back to the original "Drive#=D:,Path" format.

You're getting an error referencing the array element ([1]) that doesn't exist because you changed the data format but not the code.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#207599 - 2013-08-13 05:13 PM Re: UDF - Mapping Drive Via INI File [Re: Glenn Barnas]
Fergieman Offline
Getting the hang of it

Registered: 2010-02-25
Posts: 58
Loc: Ireland
Thanks for your help Glenn

Grand - I might just be best working this back from the ground up.

The current script doesn't map more than one group.

If I took your script and reworked the ini and connectdrives part would there be much work to getting it working do you think ?

Top
#207600 - 2013-08-13 08:00 PM Re: UDF - Mapping Drive Via INI File [Re: Fergieman]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
If you'd like to convert to the ULS, I can certainly help. Given that you have an INI file, I'd bet it could be done in a hour or two.

There's one thing that your script does that mine does not, and it's fairly unusual.. if your script fails to map to a specific drive letter, it tries a random mapping. I'm not sure how important that is, though, as I've never seen random mappings outside of very small environments.

The migration to the ULS is really pretty easy - I create a spreadsheet with 3 columns - Drive, Share, and Group. I review the current configuration and extract the current mappings into this spreadsheet. Once done, I sort by drive, then share. When there are duplicate drive/share lines with unique groups, I consolidate them into a single line with a comma-delimited list of groups. Then, each line becomes a "resource record" that looks like:
 Code:
[MAPPING ID]
CLASS=DISK
TARGET=D:
PATH=\\server\share
GROUPS=group1,group2,group3...
Target, Path, and Groups come directly from the spreadsheet. This is the most basic format to define a resource with group authorization, but there are many more available. If you send me your current INI file via PM, I can return a ready to use config for ULS so you can give it a try.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
Page 1 of 1 1


Moderator:  Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 793 anonymous users online.
Newest Members
M_Moore, BeeEm, min_seow, Audio, Hoschi
17883 Registered Users

Generated in 0.073 seconds in which 0.026 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org