[CLASS] DriveMap - map network shares to local drives

Post your working scripts, libraries and tools
just me
Posts: 6548
Joined: 02 Oct 2013, 08:51
Location: Germany

[CLASS] DriveMap - map network shares to local drives

03 Nov 2013, 01:58

:arrow: Update on 2013-11-04

This class provides three methods to add, delete and query network shares mapped to local drives (similar to the AutoIt functions DriveMapAdd(), etc):
  • Add(Drive, Share, User := "", Pass := "")

    Code: Select all

       ; -------------------------------------------------------------------------------------------------------------------
       ; Method:         Add      -  Makes a connection to a network resource and redirects a local device to the resource.
       ; Parameter:      Drive    -  Drive letter to be mapped to the share followed by a colon (e.g. "Z:")
       ;                             or "*" to map an unused drive letter.
       ;                 Share    -  A null-terminated string that specifies the remote network name.
       ;                 Optional ------------------------------------------------------------------------------------------
       ;                 User     -  A string that specifies a user name for making the connection.
       ;                             If omitted or explicitely set empty, the function uses the name of the user running
       ;                             the current process.
       ;                 Pass     -  A string that specifies a password for making the connection.
       ;                             If omitted or explicitely set to "`n", the function uses the current default password
       ;                             associated with the user specified by the User parameter.
       ;                             If Pass is an empty string, the function does not use a password.
       ; Return Values:  Drive letter followed by a colon on success, otherwise an empty string.
       ;                 ErrorLevel contains the system error code, if any.
       ; MSDN:           WNetAddConnection2 -> http://msdn.microsoft.com/en-us/library/aa385413%28v=vs.85%29.aspx
       ;                 NETRESOURCE        -> http://msdn.microsoft.com/en-us/library/aa385353%28v=vs.85%29.aspx
       ; -------------------------------------------------------------------------------------------------------------------
    
  • Del(Drive)

    Code: Select all

       ; -------------------------------------------------------------------------------------------------------------------
       ; Method:         Del      -  removes an existing drive mapping to a network share.
       ; Parameter:      Drive    -  drive letter of the mapped local drive followed by a colon (e.g. "Z:").
       ;                 Optional ------------------------------------------------------------------------------------------
       ;                 Force    -  specifies whether the disconnection should occur if there are open files or jobs
       ;                             on the connection. Values: True/False
       ; Return Values:  True on success, otherwise False (ErrorLevel contains the system error code, if any).
       ; MSDN:           WNetCancelConnection2 -> http://msdn.microsoft.com/en-us/library/aa385427%28v=vs.85%29.aspx
       ; -------------------------------------------------------------------------------------------------------------------
    
  • Get(Drive)

    Code: Select all

       ; -------------------------------------------------------------------------------------------------------------------
       ; Method:         Get      -  retrieves the name of the network share associated with the local drive.
       ; Parameter:      Drive    -  drive letter to get the network name for followed by a colon (e.g. "Z:").
       ; Return Values:  The name of the share on success, otherwise an empty string.
       ;                 ErrorLevel contains the system error code, if any.
       ; MSDN:           WNetGetConnection() -> http://msdn.microsoft.com/en-us/library/aa385453%28v=vs.85%29.aspx
       ; -------------------------------------------------------------------------------------------------------------------
    
I could test this on Win XP only, because it's my only environment with available network shares. That's why the script has 'RC1' state.

Connections to a network share without mapping to a drive letter isn't supported yet, but feasible.

Some testing on newer Windows versions would be appreciated.

Code: Select all

#NoEnv
MsgBox, % (Share := DriveMap.Get("F:")) . " - " . ErrorLevel
MsgBox, % DriveMap.Del("F:")
MsgBox, % DriveMap.Add("F:", Share)
ExitApp
; ======================================================================================================================
; Namespace:      DriveMap
; Function:       Add, delete, or query network shares mapped to local drives.
; AHK version:    AHK 1.1.13.01
; Tested on:      Win XP SP3 - AHK A32/U32 (Win 7 - AHK A32/U32 by HotKeyIt, THX)
; Version:        1.0.00.00/2013-11-04/just me
; ======================================================================================================================
Class DriveMap {
   ;--------------------------------------------------------------------------------------------------------------------
   Static MinDL := "D"              ; minimum drive letter
   Static MaxDL := "Z"              ; maximum drive letter
   Static ERROR_BAD_DEVICE := 1200  ; system error code
   ;--------------------------------------------------------------------------------------------------------------------
   __New(P*) {
      Return ""
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; Method:         Add      -  Makes a connection to a network resource and redirects a local device to the resource.
   ; Parameter:      Drive    -  Drive letter to be mapped to the share followed by a colon (e.g. "Z:")
   ;                             or "*" to map an unused drive letter.
   ;                 Share    -  A null-terminated string that specifies the remote network name.
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 User     -  A string that specifies a user name for making the connection.
   ;                             If omitted or explicitely set empty, the function uses the name of the user running
   ;                             the current process.
   ;                 Pass     -  A string that specifies a password for making the connection.
   ;                             If omitted or explicitely set to "`n", the function uses the current default password
   ;                             associated with the user specified by the User parameter.
   ;                             If Pass is an empty string, the function does not use a password.
   ; Return Values:  Drive letter followed by a colon on success, otherwise an empty string.
   ;                 ErrorLevel contains the system error code, if any.
   ; MSDN:           WNetAddConnection2 -> http://msdn.microsoft.com/en-us/library/aa385413%28v=vs.85%29.aspx
   ;                 NETRESOURCE        -> http://msdn.microsoft.com/en-us/library/aa385353%28v=vs.85%29.aspx
   ; -------------------------------------------------------------------------------------------------------------------
   Add(Drive, Share, User := "", Pass := "`n") {
      Static RESOURCETYPE_DISK := 0x00000001
      Static Flags := 0x04 ; CONNECT_TEMPORARY
      Static offType := 4, offLocal := 16, offRemote := offLocal + A_PtrSize ; NETRESOURCE offsets
      ErrorLevel := 0
      If (Drive <> "*") && !RegExMatch(Drive, "i)^[" . This.MinDL . "-" . This.MaxDL . "]:$") { ; invalid drive
         ErrorLevel := This.ERROR_BAD_DEVICE
         Return ""
      }
      DriveGet, DriveList, List
      Loop, % StrLen(DriveList) { ; check whether the share is already mapped
         DL := SubStr(DriveList, A_Index, 1) . ":"
         If (This.Get(DL) = Share)
            Return DL
      }
      ; Automatic drive mapping by leaving drive empty doesn't work on Win XP, so we have to use the asterisk
      ; and do it manually
      If (Drive = "*") { ; try to find an unused drive letter
         DL := Asc(This.MaxDL)
         While (DL >= Asc(This.MinDL)) {
            If !InStr(DriveList, Chr(DL)) {
               Drive := Chr(DL) . ":"
               Break
            }
            DL--
         }
         If (Drive = "*") { ; drive is still '*', i.e. the share cannot be mapped to a drive letter
            ErrorLevel := This.ERROR_BAD_DEVICE
            Return ""
         }
      }
      VarSetCapacity(NR, (4 * 4) + (A_PtrSize * 4), 0) ; NETRESOURCE structure
      NumPut(RESOURCETYPE_DISK, NR, offType, "UInt")
      NumPut(&Drive, NR, offLocal, "Ptr")
      NumPut(&Share, NR, offRemote, "Ptr")
      PtrPass := Pass = "`n" ? 0 : &Pass
      PtrUser := User = "" ? 0 : &User
      If (Result := DllCall("Mpr.dll\WNetAddConnection2", "Ptr", &NR, "Ptr", PtrPass, "Ptr", PtrUser
                                                        , "UInt", Flags, "UInt")) {
         ErrorLevel := Result
         Return ""
      }
      Return Drive
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; Method:         Del      -  removes an existing drive mapping to a network share.
   ; Parameter:      Drive    -  drive letter of the mapped local drive followed by a colon (e.g. "Z:").
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 Force    -  specifies whether the disconnection should occur if there are open files or jobs
   ;                             on the connection. Values: True/False
   ; Return Values:  True on success, otherwise False.
   ;                 ErrorLevel contains the system error code, if any.
   ; MSDN:           WNetCancelConnection2 -> http://msdn.microsoft.com/en-us/library/aa385427%28v=vs.85%29.aspx
   ; -------------------------------------------------------------------------------------------------------------------
   Del(Drive, Force := False) {
      ErrorLevel := 0
      If !RegExMatch(Drive, "i)^[" . This.MinDL . "-" . This.MaxDL . "]:$") { ; invalid drive
         ErrorLevel := This.ERROR_BAD_DEVICE
         Return False
      }
      If (Result := DllCall("Mpr.dll\WNetCancelConnection2", "Str", Drive, "UInt", 0, "UInt", !!Force, "UInt")) {
         ErrorLevel := Result
         Return False
      }
      Return True
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; Method:         Get      -  retrieves the name of the network share associated with the local drive.
   ; Parameter:      Drive    -  drive letter to get the network name for followed by a colon (e.g. "Z:").
   ; Return Values:  The name of the share on success, otherwise an empty string.
   ;                 ErrorLevel contains the system error code, if any.
   ; MSDN:           WNetGetConnection() -> http://msdn.microsoft.com/en-us/library/aa385453%28v=vs.85%29.aspx
   ; -------------------------------------------------------------------------------------------------------------------
   Get(Drive) {
      Static Length := 512
      ErrorLevel := 0
      If !RegExMatch(Drive, "i)^[" . This.MinDL . "-" . This.MaxDL . "]:$") { ; invalid drive
         ErrorLevel := This.ERROR_BAD_DEVICE
         Return ""
      }
      VarSetCapacity(Share, Length * 2, 0)
      If (Result := DllCall("Mpr.dll\WNetGetConnection", "Str", Drive, "Str", Share, "UIntP", Length, "UInt")) {
         ErrorLevel := Result
         Return ""
      }
      Return Share
   }
}
:arrow: StdLib compatible functions by HotKeyIt
Last edited by just me on 04 Nov 2013, 08:42, edited 2 times in total.
HotKeyIt
Posts: 1886
Joined: 29 Sep 2013, 18:35
Contact:

Re: [CLASS] DriveMap - map network shares to local drives (R

03 Nov 2013, 05:14

Tested on Win7, after fixing User parameter all working as expected.
MSDN says If lpUserName is NULL, the function uses the default user name, so we can't use empty string.

Code: Select all

If (Result := DllCall("Mpr.dll\WNetAddConnection2", "Ptr", &NR, "Str", Pass, "Ptr", User=""?0:&User, "UInt", Flags, "UInt")) {
Btw. why did you put that in a class, it does really make no sense here.
Here are stdlib compatible functions: DriveMap_Add(share,drive,user,pass), DriveMap_Del(drive,force), DriveMap_Get(drive)
I have swaped share and drive parameters so drive can be omitted too.

Code: Select all

; ======================================================================================================================
; Library:        DriveMap
; Functions:      Add, delete, or query network shares mapped to local drives.
; AHK version:    AHK 1.1.13.01
; Tested on:      Win XP SP3 / Win 7 - AHK A32/U32
; Version:        0.9.00.00/2013-11-03/just me (RC1)
; ======================================================================================================================

; -------------------------------------------------------------------------------------------------------------------
; Function:       DriveMap_Add      -  makes a connection to a network resource and redirects a local device to the resource.
; Parameter:      Share    -  a null-terminated string that specifies the remote network name.
;                 Optional ------------------------------------------------------------------------------------------
;                 Drive    -  drive letter to be mapped to the share followed by a colon (e.g. "Z:")
;                             or "*" (default) to map an unused drive letter.
;                 User     -  a string that specifies a user name for making the connection.
;                 Pass     -  a string that specifies a password for making the connection.
; Return Values:  Drive letter followed by a colon on success, otherwise an empty string.
;                 ErrorLevel contains the system error code, if any.
; MSDN:           WNetAddConnection2 -> http://msdn.microsoft.com/en-us/library/aa385413%28v=vs.85%29.aspx
;                 NETRESOURCE        -> http://msdn.microsoft.com/en-us/library/aa385353%28v=vs.85%29.aspx
; -------------------------------------------------------------------------------------------------------------------
DriveMap_Add(Share, Drive:="*", User := "", Pass := "") {
	Static MinDL := "D"  ; minimum drive letter
	Static MaxDL := "Z"  ; maximum drive letter
	Static RESOURCETYPE_DISK := 0x00000001
	Static Flags := 0x04 ; CONNECT_TEMPORARY
	Static offType := 4, offLocal := 16, offRemote := offLocal + A_PtrSize ; NETRESOURCE offsets
	ErrorLevel := 0
	If (Drive <> "*") && !RegExMatch(Drive, "i)^[" . MinDL . "-" . MaxDL . "]:$") ; invalid drive
		 Return ""
	DriveGet, DriveList, List
	Loop, % StrLen(DriveList) { ; check whether the share is already mapped
		 DL := SubStr(DriveList, A_Index, 1) . ":"
		 If (DriveMap_Get(DL) = Share)
				Return DL
	}
	; Automatic drive mapping by leaving drive empty doesn't work on Win XP, so we have to use the asterisk
	; and do it manually
	If (Drive = "*") { ; try to find an unused drive letter
		 DL := Asc(MinDL)
		 While (DL <= Asc(MaxDL)) {
				If !InStr(DriveList, Chr(DL)) {
					 Drive := Chr(DL) . ":"
					 Break
				}
				DL++
		 }
		 If (Drive = "*") ; drive is still '*', i.e. the share cannot be mapped to a drive letter
				Return ""
	}
	VarSetCapacity(NR, (4 * 4) + (A_PtrSize * 4), 0) ; NETRESOURCE structure
	NumPut(RESOURCETYPE_DISK, NR, offType, "UInt")
	NumPut(&Drive, NR, offLocal, "Ptr")
	NumPut(&Share, NR, offRemote, "Ptr")
	If (Result := DllCall("Mpr.dll\WNetAddConnection2", "Ptr", &NR, "Ptr", Pass=""?0:&Pass, "Ptr", User=""?0:&User, "UInt", Flags, "UInt")) {
		 ErrorLevel := Result
		 Return ""
	}
	Return Drive
}
; -------------------------------------------------------------------------------------------------------------------
; Function:       DriveMap_Del      -  removes an existing drive mapping to a network share.
; Parameter:      Drive    -  drive letter of the mapped local drive followed by a colon (e.g. "Z:").
;                 Optional ------------------------------------------------------------------------------------------
;                 Force    -  specifies whether the disconnection should occur if there are open files or jobs
;                             on the connection. Values: True/False
; Return Values:  True on success, otherwise False (ErrorLevel contains the system error code, if any).
; MSDN:           WNetCancelConnection2 -> http://msdn.microsoft.com/en-us/library/aa385427%28v=vs.85%29.aspx
; -------------------------------------------------------------------------------------------------------------------
DriveMap_Del(Drive, Force := False) {
	Static MinDL := "D"  ; minimum drive letter
	Static MaxDL := "Z"  ; maximum drive letter
	ErrorLevel := 0
	If !RegExMatch(Drive, "i)^[" . MinDL . "-" . MaxDL . "]:$") ; invalid drive
		 Return False
	If (Result := DllCall("Mpr.dll\WNetCancelConnection2", "Str", Drive, "UInt", 0, "UInt", !!Force, "UInt")) {
		 ErrorLevel := Result
		 Return False
	}
	Return True
}
; -------------------------------------------------------------------------------------------------------------------
; Function:       DriveMap_Get      -  retrieves the name of the network share associated with the local drive.
; Parameter:      Drive    -  drive letter to get the network name for followed by a colon (e.g. "Z:").
; Return Values:  The name of the share on success, otherwise an empty string.
;                 ErrorLevel contains the system error code, if any.
; MSDN:           WNetGetConnection() -> http://msdn.microsoft.com/en-us/library/aa385453%28v=vs.85%29.aspx
; -------------------------------------------------------------------------------------------------------------------
DriveMap_Get(Drive) {
	Static Length := 512
	Static MinDL := "D"  ; minimum drive letter
	Static MaxDL := "Z"  ; maximum drive letter
	ErrorLevel := 0
	If !RegExMatch(Drive, "i)^[" . MinDL . "-" . MaxDL . "]:$") ; invalid drive
		 Return ""
	VarSetCapacity(Share, Length * 2, 0)
	If (Result := DllCall("Mpr.dll\WNetGetConnection", "Str", Drive, "Str", Share, "UIntP", Length, "UInt")) {
		 ErrorLevel := Result
		 Return ""
	}
	Return Share
}
just me
Posts: 6548
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [CLASS] DriveMap - map network shares to local drives

04 Nov 2013, 08:36

Thanks for testing, HotKeyIt. Your notes relating to lpUserName are correct. Additionally I changed the handling of lpPassword, too. I updated the script and the description off the Add() method in the O.P.

Why it is a class? Actually, I firstly made three functions DriveMapAdd(), DriveMapDel(), and DriveMapGet(), like AutoIt. Then I thought about making them StdLib compatible by inserting the underlign sign. But I'm somewhat old-fashioned and prefer to #Include all additional stuff I need explicitely. That's why it became a class. One slight advantage is, that the user may easyly adjust the range of drive letters.
Guest

Re: [CLASS] DriveMap - map network shares to local drives

16 Aug 2016, 11:49

"Connections to a network share without mapping to a drive letter isn't supported yet, but feasible."

How?

Please provide some hint

Thanks
just me
Posts: 6548
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [CLASS] DriveMap - map network shares to local drives

17 Aug 2016, 02:11

WNetAddConnection2 wrote:lpLocalName
...
If the string is empty, or if lpLocalName is NULL, the function makes a connection to the network resource without redirecting a local device.

Source
Whatever it's worth.
wildjoker788

Re: [CLASS] DriveMap - map network shares to local drives

24 Feb 2017, 17:19

I know this thread is pretty old, but if someome could be post an example of this adding a drive.

what i have:

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#include DriveMap.ahk

DriveMap_ADD("\\192.168.74.254\Updates",X,remote,password)
IfExist, x:\regfix.reg
MsgBox PC is online
Else
MsgBox PC is offline

Thanks in advance.
just me
Posts: 6548
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [CLASS] DriveMap - map network shares to local drives

25 Feb 2017, 03:04

You are using HotKeyIt's function version.

Code: Select all

; -------------------------------------------------------------------------------------------------------------------
; Function:       DriveMap_Add      -  makes a connection to a network resource and redirects a local device to the resource.
; Parameter:      Share    -  a null-terminated string that specifies the remote network name.
;                 Optional ------------------------------------------------------------------------------------------
;                 Drive    -  drive letter to be mapped to the share followed by a colon (e.g. "Z:")
;                             or "*" (default) to map an unused drive letter.
;                 User     -  a string that specifies a user name for making the connection.
;                 Pass     -  a string that specifies a password for making the connection.
; Return Values:  Drive letter followed by a colon on success, otherwise an empty string.
;                 ErrorLevel contains the system error code, if any.
; MSDN:           WNetAddConnection2 -> http://msdn.microsoft.com/en-us/library/aa385413%28v=vs.85%29.aspx
;                 NETRESOURCE        -> http://msdn.microsoft.com/en-us/library/aa385353%28v=vs.85%29.aspx
; -------------------------------------------------------------------------------------------------------------------
All parameters are strings, so you might try:

Code: Select all

DriveMap_ADD("\\192.168.74.254\Updates", "X:", "UserName" ,"Password")

Return to “Scripts and Functions”

Who is online

Users browsing this forum: clarc, Google [Bot], SirSocks and 60 guests