#207576 - 2013-08-09 10:27 AM
UDF - Mapping Drive Via INI File
|
Fergieman
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.
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
KiX Supporter
   
Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
|
Geez - talk about complicated! 
Untested, but this concept would be much simpler: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!
|
|
Top
|
|
|
|
#207578 - 2013-08-09 01:05 PM
Re: UDF - Mapping Drive Via INI File
[Re: Glenn Barnas]
|
BradV
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
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: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: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!
|
|
Top
|
|
|
|
#207580 - 2013-08-09 05:48 PM
Re: UDF - Mapping Drive Via INI File
[Re: Glenn Barnas]
|
Fergieman
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
|
|
|
|
#207582 - 2013-08-12 10:25 AM
Re: UDF - Mapping Drive Via INI File
[Re: Glenn Barnas]
|
Fergieman
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
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
|
|
|
|
#207586 - 2013-08-12 03:04 PM
Re: UDF - Mapping Drive Via INI File
[Re: Glenn Barnas]
|
Fergieman
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
Getting the hang of it
Registered: 2010-02-25
Posts: 58
Loc: Ireland
|
Ok , here is function
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
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.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!
|
|
Top
|
|
|
|
#207594 - 2013-08-13 01:41 PM
Re: UDF - Mapping Drive Via INI File
[Re: Glenn Barnas]
|
Fergieman
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
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
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
|
|
|
|
#207599 - 2013-08-13 05:13 PM
Re: UDF - Mapping Drive Via INI File
[Re: Glenn Barnas]
|
Fergieman
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
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:[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!
|
|
Top
|
|
|
|
Moderator: Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart
|
0 registered
and 360 anonymous users online.
|
|
|