From 014567f15b695428dba95c38c122ddda64819f52 Mon Sep 17 00:00:00 2001 From: thex Date: Thu, 30 Nov 2017 20:57:45 +0100 Subject: [PATCH] UNC vs. URI, authentication, pathing, debug --- README.md | 20 +- build/build.bat | 2 +- src/share_reconnect.vbs | 494 ++++++++++++++++++++++++++-------------- 3 files changed, 340 insertions(+), 176 deletions(-) diff --git a/README.md b/README.md index 6dad098..8a1c95c 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ Many claim that the reconnect problem leads back to a timing problem during logi * little knowledge on Windows Task Scheduling ## Download / Installation -1. [Download v1.2.5](https://github.com/thexmanxyz/network-share-reconnecter/releases/download/v1.2.5/nsr.v1.2.5.zip) of the Network Share Reconnecter Package. +1. [Download v1.3.0](https://github.com/thexmanxyz/network-share-reconnecter/releases/download/v1.3.0/nsr.v1.3.0.zip) of the Network Share Reconnecter Package. 2. Extract the files. 3. Modify the sample configuration in the **share_reconnect.vbs** script file. - * At least modify `hostname`, `sharePaths` and `shareLetters` (see also the [configuration section](https://github.com/thexmanxyz/network-share-reconnecter/blob/master/src/share_reconnect.vbs#L35-L36) and [Issue #1](https://github.com/thexmanxyz/network-share-reconnecter/issues/1)). + * At least modify `hostname`, `sharePaths` and `shareLetters` (see also the [configuration section](https://github.com/thexmanxyz/network-share-reconnecter/blob/master/src/share_reconnect.vbs#L41-L43) and [Issue #1](https://github.com/thexmanxyz/network-share-reconnecter/issues/1)). * Multiple servers can be easily added and configured. 4. Copy **share_reconnect.vbs** to a self defined directory. 5. Start Windows Task Scheduler - manually or with **taskschd.msc**. @@ -30,7 +30,10 @@ Here a short description of the available parameters which can be configured: * `hostname` - IP or hostname of the remote server **(must be modified)** * `sharePaths` - all share paths on the server **(must be modified)** * `shareLetters` - the share / drive letters for the defined paths **(must be modified)** - * `netUsePersistent` - should *net use* create a persistent share **(yes/no)** + * `persistent` - should *net use* create a persistent share **(yes/no)** + * `user` - username for net use authentication if required **(optional)** + * `password` - password for net use authentication if required **(optional)** + * `secure` - defines whether the HTTP or HTTPS protocol should be used **(URI only)** * Global Script Configuration * `pingWait` - wait time after failed server ping @@ -42,6 +45,17 @@ Here a short description of the available parameters which can be configured: * `pingTimeout` - how many milliseconds pass before the ping is canceled * `debug` - enable or disable debug messages on current reconnection state +### UNC Example Configuration +If your share is accessible over an UNC path like `\\\192.168.1.1\path\to\share` use this configuration. + +`Set srvCfgUnc = createUncSrvConfig("192.168.1.1", Array("path\to\share"), Array("Z:"), "yes")` + + +### URI Example Configuration +If you share needs to be accessed over HTTP(s) like `http://my.webserver.com/path/to/share` use this configuration. + +`Set srvCfgUri = createUncSrvConfig("my.webserver.com", Array("path/to/share"), Array("Z:"), "yes", true)` + ## Features * Automatic reconnection of network drives and shares on logon or unlock of the workstation. * Stealth script execution (operates without exposing any prompts or windows - except when debug is enabled :P). diff --git a/build/build.bat b/build/build.bat index c1535b1..c21a86c 100644 --- a/build/build.bat +++ b/build/build.bat @@ -20,7 +20,7 @@ set log_files=0 REM --- Packaging Variables -- set prj_id=nsr -set prj_rev=v1.2.5 +set prj_rev=v1.3.0 set prj_fullname=Network Share Reconnecter REM --- File Variables --- diff --git a/src/share_reconnect.vbs b/src/share_reconnect.vbs index 63136c7..d19a8a0 100644 --- a/src/share_reconnect.vbs +++ b/src/share_reconnect.vbs @@ -20,23 +20,30 @@ ' share(s). If you want to use this script in your topology it's MANDATORY to ' ' change the values below APPROPRIATELY. ' ' ' -' hostname - IP or hostname of the remote server (must be modified) ' +' hostname - IP, hostname or URI of the remote server (must be modified) ' ' sharePaths - all share paths on the server (must be modified) ' ' shareLetters - the share / drive letters for the defined paths (must be modified) ' -' netUsePersistent - should net use create a persistent share (yes/no) ' +' persistent - should net use create a persistent share (yes/no) ' +' user - username for net use authentication if required (optional) ' +' password - password for net use authentication if required (optional) ' +' secure - defines whether the HTTP or HTTPS protocol should be used (URI only) ' '-------------------------------------------------------------------------------------' Dim srvConfigs -'Server Configuration explanation with parameters and variable names' -'set srvCfgX = createSrvConfig(hostname, sharePaths, shareLetters, netUsePersistent) +'Server Configuration (UNC)' +'Set srvCfgX = createUncSrvConfig(hostname, sharePaths, shareLetters, persistent, username, password) -'Multi Server Configuration - two servers with two shares for each endpoint (please remove unnecessary lines)' -Set srvCfg1 = createSrvConfig("192.168.1.1", Array("path\to\share1", "path\to\share2"), Array("Z:", "Y:"), "yes") -Set srvCfg2 = createSrvConfig("192.168.1.2", Array("path\to\share3", "path\to\share4"), Array("X:", "W:"), "yes") +'Server Configuration (URI)' +'Set srvCfgY = createUriSrvConfig(hostname, sharePaths, shareLetters, persistent, username, password, secure) -'add more server configurations here or remove them if needed (remove "srvCfg2" for single server configuration)' -srvConfigs = Array(srvCfg1, srvCfg2) +'Multi Server Configuration - three servers with two shares for each endpoint [remove unnecessary lines]' +Set srvCfg1 = createUncSrvConfig("192.168.1.1", Array("path\to\share1", "path\to\share2"), Array("Z:", "Y:"), "yes", "", "") +Set srvCfg2 = createUncSrvConfig("192.168.1.2", Array("path\to\share3", "path\to\share4"), Array("X:", "W:"), "yes", "", "") +Set srvCfg3 = createUriSrvConfig("my.web.server", Array("path/to/share5", "path/to/share6"), Array("X:", "W:"), "yes", "", "", true) + +'add more server configurations here or remove them if needed [remove srvCfg2 and srvCfg3 for single server configuration]' +srvConfigs = Array(srvCfg1, srvCfg2, srvCfg3) '-------------------------------------------------------------------------------------' ' ' @@ -79,10 +86,14 @@ Class ServerConfiguration Public hostname Public sharePaths Public shareLetters - Public netUsePersistent - Public hPath + Public persistent + Public user + Public password + Public isUri + Public secure Public online Public connected + Public fsTestPath End Class '--------------------------------------------' @@ -103,6 +114,268 @@ Class ScriptConfiguration Public debug End Class +'----------------------------------------------------------------------------' +' Routine to handle the connectivity of multiple servers and their shares. ' +' ' +' scriptConfig - object for the global script configuration ' +' srvConfigs - array of server configuration objects ' +'-----------------------------------------------------------------------------' + +Sub waitOnServersConnect(scriptConfig, srvConfigs) + Dim i, wait, offSrvs, onSrvs + + i = 0 + initConfig scriptConfig + initSrvs scriptConfig, srvConfigs + While ((i <= scriptConfig.serverRetryCtn - 1 And isSrvOffline(srvConfigs)) Or (i = 0 And isSrvOnline(srvConfigs))) + offSrvs = "" + onSrvs = "" + wait = true + i = i + 1 + + For j = 0 to uBound(srvConfigs) + If srvConfigs(j).online And Not srvConfigs(j).connected Then + checkNconnect scriptConfig, srvConfigs(j) + End If + If srvConfigs(j).online Then + onSrvs = getSrvDebug(onSrvs, srvConfigs(j)) + End If + Next + + For j = 0 to uBound(srvConfigs) + If Not srvConfigs(j).online Then + If wait Then + WScript.Sleep getReconWaitTime(scriptConfig, i) + wait = false + End If + setSrvState scriptConfig, srvConfigs(j) + If srvConfigs(j).online Then + checkNconnect scriptConfig, srvConfigs(j) + onSrvs = getSrvDebug(onSrvs, srvConfigs(j)) + Else + offSrvs = getSrvDebug(offSrvs, srvConfigs(j)) + End If + End If + Next + printDebug scriptConfig, onSrvs, offSrvs + Wend +End Sub + +'-------------------------------------------------------------------' +' Routine that checks server connectivity and tries to reconnect ' +' shares if the server is online. ' +' ' +' scriptConfig - object for the global script configuration ' +' srvConfig - configuration object of the server ' +'-------------------------------------------------------------------' + +Sub checkNconnect(ByVal scriptConfig, ByRef srvConfig) + If Not retryPingServer(scriptConfig, srvConfig, true) Then + netUseServerShares scriptConfig, srvConfig + End If +End Sub + +'--------------------------------------------------------------------' +' Routine that creates a new UNC server object. ' +' ' +' hostname - IP or human readable hostname ' +' sharePaths - array that contains share paths ' +' shareLetters - array that contains share letters ' +' persistent - "yes" or "no" for the net use persistent state ' +' user - the username applied in the net use command ' +' password - the password applied in the net use command ' +'--------------------------------------------------------------------' + +Function createUncSrvConfig(hostname, sharePaths, shareLetters, persistent, user, password) + Set createUncSrvConfig = createSrvConfig(hostname, sharePaths, shareLetters, persistent, user, password, false, false) +End Function + +'--------------------------------------------------------------------' +' Routine that creates a new URI server object. ' +' ' +' hostname - IP or URI ' +' sharePaths - array that contains share paths ' +' shareLetters - array that contains share letters ' +' persistent - "yes" or "no" for the net use persistent state ' +' user - the username applied in the net use command ' +' password - the password applied in the net use command ' +' secure - true or false to use HTTP or HTTPS ' +'--------------------------------------------------------------------' + +Function createUriSrvConfig(hostname, sharePaths, shareLetters, persistent, user, password, secure) + Set createUriSrvConfig = createSrvConfig(hostname, sharePaths, shareLetters, persistent, user, password, true, secure) +End Function + +'--------------------------------------------------------------------' +' Routine that creates a new server object. ' +' ' +' hostname - IP or URI ' +' sharePaths - array that contains share paths ' +' shareLetters - array that contains share letters ' +' persistent - "yes" or "no" for the net use persistent state ' +' isUri - is server accessible over UNC or URI ' +' user - the username applied in the net use command ' +' password - the password applied in the net use command ' +' secure - true or false to use HTTP or HTTPS ' +'--------------------------------------------------------------------' + +Function createSrvConfig(hostname, sharePaths, shareLetters, persistent, user, password, isUri, secure) + Set srvCfg = New ServerConfiguration + + 'trim share paths if necessary (remove leading and trailing slash) + trimSharePaths sharePaths, isUri + + 'create server configuration + srvCfg.hostname = hostname + srvCfg.sharePaths = sharePaths + srvCfg.shareLetters = shareLetters + srvCfg.persistent = persistent + srvCfg.user = user + srvCfg.password = password + srvCfg.isUri = isUri + srvCfg.secure = secure + Set createSrvConfig = srvCfg +End Function + +'------------------------------------------------------------------------' +' Routine to initialize the script config with objects that are reused. ' +' ' +' scriptConfig - object for the global script configuration ' +'------------------------------------------------------------------------' + +Sub initConfig(ByRef scriptConfig) + Set scriptConfig.winMgmts = GetObject("winmgmts:{impersonationLevel=impersonate}") + Set scriptConfig.fso = CreateObject("Scripting.FileSystemObject") + Set scriptConfig.shell = CreateObject("WScript.Shell") +End Sub + +'------------------------------------------------------------' +' Routine to initialize an array of server objects. ' +' ' +' scriptConfig - object for the global script configuration ' +' srvConfigs - array of server configurations ' +'------------------------------------------------------------' + +Sub initSrvs(ByVal scriptConfig, ByRef srvConfigs) + For i = 0 to uBound(srvConfigs) + initSrv scriptConfig, srvConfigs(i) + Next +End Sub + +'------------------------------------------------------------' +' Routine to initialize a server object. ' +' ' +' scriptConfig - object for the global script configuration ' +' srvConfig - configuration object of the server ' +'------------------------------------------------------------' + +Sub initSrv(ByVal scriptConfig, ByRef srvConfig) + setSrvPath srvConfig + setSrvState scriptConfig, srvConfig + srvConfig.connected = false +End Sub + +'-----------------------------------------------------' +' Routine to set an absolute help server share path. ' +' ' +' srvConfig - configuration object of the server ' +'-----------------------------------------------------' + +Sub setSrvPath(ByRef srvConfig) + Dim testPath, hPath + hPath = trimSharePath(srvConfig.sharePaths(0), srvConfig.isUri) + If(srvConfig.isUri) Then + testPath = createUriPath(srvConfig.hostname, hPath, srvConfig.secure) + Else + testPath = createUncPath(srvConfig.hostname, hPath) + End If + srvConfig.fsTestPath = testPath +End Sub + +'--------------------------------------------------------------------' +' Routine to create a UNC server address ' +' ' +' host - the servers hostname or IP ' +' path - the path to the share ' +'--------------------------------------------------------------------' + +Function createUncPath(host, path) + createUncPath = "\\" & host & "\" & path +End Function + +'--------------------------------------------------------------------' +' Routine to create a URI server address ' +' ' +' host - the servers URI or IP ' +' path - the path to the share ' +' secure - true or false to use HTTP or HTTPS ' +'--------------------------------------------------------------------' + +Function createUriPath(host, path, secure) + Dim protocol, hPath + If secure Then + protocol = "https" + Else + protocol = "http" + End If + + If Len(path) > 0 Then + hPath = "/" & path + Else + hPath = path + End If + + createUriPath = protocol & "://" & host & hPath +End Function + +'--------------------------------------------------------------------' +' Trims leading and Trailing slash from share paths if necessary. ' +' ' +' sharePaths - array that contains share paths ' +' isUri - are UNC or URI paths passed ' +'--------------------------------------------------------------------' + +Function trimSharePaths(ByRef sharePaths, isUri) + For j = 0 to uBound(sharePaths) + sharePaths(j) = trimSharePath(sharePaths(j), isUri) + Next +End Function + +'--------------------------------------------------------------------' +' Trims leading and trailing slash from path if necessary. ' +' ' +' sharePath - single path to share ' +' isUri - is a URI or UNC path passed ' +'--------------------------------------------------------------------' + +Function trimSharePath(sharePath, isUri) + Dim hPath, hLen, slash + + If isUri Then + slash = "/" + Else + slash = "\" + End If + + 'remove leading slash + hPath = sharePath + hLen = Len(hPath) + If hLen > 0 Then + If InStr(1, hPath, slash) = 1 Then + hPath = Mid(hPath, 2, hLen - 1) + End If + End If + + 'remove trailing slash only if UNC + hLen = Len(hPath) + If Not isUri And hLen > 0 Then + If InStr(hLen, hPath, slash) = hLen Then + hPath = Mid(hPath, 1, hLen - 1) + End If + End If + trimSharePath = hPath +End Function + '------------------------------------------------------------------' ' Routine to shell ping a server with a predefined configuration. ' ' (not used because ping does not return correct status) ' @@ -153,6 +426,7 @@ End Function ' ' ' scriptConfig - object for the global script configuration ' ' srvConfig - configuration object of the server ' +' icmp - use icmp ping instead of shell ping ' '-----------------------------------------------------------------' Function retryPingServer(scriptConfig, srvConfig, icmp) @@ -182,8 +456,22 @@ End Function '------------------------------------------------------------' Function getNetUseCmd(srvConfig, pos) - getNetUseCmd = "net use " & srvConfig.shareLetters(pos) & " " & chr(34) & "\\" & srvConfig.hostname _ - & "\" & srvConfig.sharePaths(pos) & chr(34) & " /persistent:" & srvConfig.netUsePersistent + Dim address, user + + If srvConfig.isUri Then + address = createUriPath(srvConfig.hostname, srvConfig.sharePaths(pos), srvConfig.secure) + Else + address = createUncPath(srvConfig.hostname, srvConfig.sharePaths(pos)) + End If + + If Len(srvConfig.user) > 0 Then + user = " /user:" & srvConfig.user & " " & srvConfig.password + else + user = "" + End If + + getNetUseCmd = "net use " & srvConfig.shareLetters(pos) & " " & chr(34) & address _ + & chr(34) & user & " /persistent:" & srvConfig.persistent End Function '----------------------------------------------------------------------' @@ -216,93 +504,6 @@ Sub netUseServerShares(ByVal scriptConfig, ByRef srvConfig) srvConfig.connected = true End Sub -'------------------------------------------------------------------------' -' Routine to initialize the script config with objects that are reused. ' -' ' -' scriptConfig - object for the global script configuration ' -'------------------------------------------------------------------------' - -Sub initConfig(ByRef scriptConfig) - Set scriptConfig.winMgmts = GetObject("winmgmts:{impersonationLevel=impersonate}") - Set scriptConfig.fso = CreateObject("Scripting.FileSystemObject") - Set scriptConfig.shell = CreateObject("WScript.Shell") -End Sub - -'--------------------------------------------------------------------' -' Routine that creates a new server object. ' -' ' -' hostname - IP or human readable hostname ' -' sharePaths - array that contains share paths ' -' shareLetters - array that contains share letters ' -' netUsePersistent - "yes" or "no" for the net use persistent state ' -'--------------------------------------------------------------------' - -Function createSrvConfig(hostname, sharePaths, shareLetters, netUsePersistent) - Set srvCfg = New ServerConfiguration - - 'trim share paths if necessary (remove leading '\') - trimSharePaths sharePaths - - 'create server configuration - srvCfg.hostname = hostname - srvCfg.sharePaths = sharePaths - srvCfg.shareLetters = shareLetters - srvCfg.netUsePersistent = netUsePersistent - Set createSrvConfig = srvCfg - -End Function - - -'--------------------------------------------------------------------' -' Trims leading '\' from share paths if exist. ' -' ' -' sharePaths - array that contains share paths ' -'--------------------------------------------------------------------' - -Function trimSharePaths(ByRef sharePaths) - For j = 0 to uBound(sharePaths) - If Len(sharePaths(j)) > 0 And InStr(1, sharePaths(j), "\") = 1 Then - sharePaths(j) = Mid(sharePaths(j), 2, Len(sharePaths(j))-1) - End If - Next -End Function - -'------------------------------------------------------------' -' Routine to initialize an array of server objects. ' -' ' -' scriptConfig - object for the global script configuration ' -' srvConfigs - array of server configurations ' -'------------------------------------------------------------' - -Sub initSrvs(ByVal scriptConfig, ByRef srvConfigs) - For i = 0 to uBound(srvConfigs) - initSrv scriptConfig, srvConfigs(i) - Next -End Sub - -'------------------------------------------------------------' -' Routine to initialize a server object. ' -' ' -' scriptConfig - object for the global script configuration ' -' srvConfig - configuration object of the server ' -'------------------------------------------------------------' - -Sub initSrv(ByVal scriptConfig, ByRef srvConfig) - setSrvPath srvConfig - setSrvState scriptConfig, srvConfig - srvConfig.connected = false -End Sub - -'-----------------------------------------------------' -' Routine to set an absolute help server share path. ' -' ' -' srvConfig - configuration object of the server ' -'-----------------------------------------------------' - -Sub setSrvPath(ByRef srvConfig) - srvConfig.hPath = "\\" & srvConfig.hostname & "\" & srvConfig.sharePaths(0) -End Sub - '--------------------------------------------------------------------' ' Routine to set server state by ping and share (FS) connectivity. ' ' ' @@ -312,7 +513,11 @@ End Sub Sub setSrvState(ByVal scriptConfig, ByRef srvConfig) If Not retryPingServer(scriptConfig, srvConfig, true) Then - srvConfig.online = scriptConfig.fso.FolderExists(srvConfig.hPath) + If srvConfig.isUri Then + srvConfig.online = true + Else + srvConfig.online = scriptConfig.fso.FolderExists(srvConfig.fsTestPath) + End If Else srvConfig.online = false End If @@ -325,7 +530,7 @@ End Sub '-------------------------------------------------------------------' Function isSrvOffline(srvConfigs) - dim offline + Dim offline offline = false For i = 0 to uBound(srvConfigs) If Not srvConfigs(i).online Then @@ -343,7 +548,7 @@ End Function '------------------------------------------------------------------' Function isSrvOnline(srvConfigs) - dim online + Dim online online = false For i = 0 to uBound(srvConfigs) If srvConfigs(i).online Then @@ -386,17 +591,21 @@ End Function '-------------------------------------------------------------------------' Sub printDebug(scriptConfig, onSrvs, offSrvs) - Dim debugOut + Dim debugOut, onLen, offLen + If scriptConfig.debug Then - debugOut = "" - If Not (Len(onSrvs) = 0) Then - debugOut = "Server(s) online:" & Mid(onSrvs, 3, Len(onSrvs)-1) + onLen = Len(onSrvs) + offLen = Len(offSrvs) + debugOut = "" + + If Not (onLen = 0) Then + debugOut = "Server(s) online:" & Mid(onSrvs, 3, onLen - 1) End If - If Not (Len(onSrvs) = 0) And Not (Len(offSrvs) = 0) Then + If Not (onLen = 0) And Not (offLen = 0) Then debugOut = debugOut & vbNewLine End If - If Not (Len(offSrvs) = 0) Then - debugOut = debugOut & "Server(s) offline:" & Mid(offSrvs, 3, Len(offSrvs)-1) + If Not (offLen = 0) Then + debugOut = debugOut & "Server(s) offline:" & Mid(offSrvs, 3, offLen - 1) End If MsgBox(debugOut) End If @@ -409,65 +618,6 @@ End Sub ' part - string on which the concat will be applied ' '---------------------------------------------------------------' -Function getSrvDebugUnit(part, srvConfig) - getSrvDebugUnit = part & " | " & srvConfig.hostname -End Function - -'-------------------------------------------------------------------' -' Routine that checks server connectivity and tries to reconnect. ' -' shares if the server is online. ' -' ' -' scriptConfig - object for the global script configuration ' -' srvConfig - configuration object of the server ' -'-------------------------------------------------------------------' - -Sub checkNconnect(ByVal scriptConfig, ByRef srvConfig) - If Not retryPingServer(scriptConfig, srvConfig, true) Then - netUseServerShares scriptConfig, srvConfig - End If -End Sub - -'----------------------------------------------------------------------------' -' Routine to handle the connectivity of multiple servers and their shares. ' -' ' -' scriptConfig - object for the global script configuration ' -' srvConfigs - array of server configuration objects ' -'-----------------------------------------------------------------------------' - -Sub waitOnServersConnect(scriptConfig, srvConfigs) - Dim i, wait, offSrvs, onSrvs - - i = 0 - initConfig scriptConfig - initSrvs scriptConfig, srvConfigs - While ((i <= scriptConfig.serverRetryCtn - 1 And isSrvOffline(srvConfigs)) Or (i = 0 And isSrvOnline(srvConfigs))) - offSrvs = "" - onSrvs = "" - wait = true - i = i + 1 - - For j = 0 to uBound(srvConfigs) - If srvConfigs(j).online And Not srvConfigs(j).connected Then - checkNconnect scriptConfig, srvConfigs(j) - onSrvs = getSrvDebugUnit(onSrvs, srvConfigs(j)) - End If - Next - - For j = 0 to uBound(srvConfigs) - If Not srvConfigs(j).online Then - If wait Then - WScript.Sleep getReconWaitTime(scriptConfig, i) - wait = false - End If - setSrvState scriptConfig, srvConfigs(j) - If srvConfigs(j).online Then - checkNconnect scriptConfig, srvConfigs(j) - onSrvs = getSrvDebugUnit(onSrvs, srvConfigs(j)) - Else - offSrvs = getSrvDebugUnit(offSrvs, srvConfigs(j)) - End If - End If - Next - printDebug scriptConfig, onSrvs, offSrvs - Wend -End Sub \ No newline at end of file +Function getSrvDebug(part, srvConfig) + getSrvDebug = part & " | " & srvConfig.hostname +End Function \ No newline at end of file