¿Cuál es la mejor manera de asignar unidades de Windows usando Python?

¿Cuál es la mejor manera de asignar un recurso compartido de red a una unidad de Windows usando Python? Este recurso compartido también requiere un nombre de usuario y contraseña.

Iría con IronPython y este artículo: Mapeo de una letra de unidad programáticamente . O podrías usar la API de Win32 directamente.

Aprovechando la sugerencia de @Anon:

# Drive letter: M # Shared drive path: \\shared\folder # Username: user123 # Password: password import subprocess # Disconnect anything on M subprocess.call(r'net use m: /del', shell=True) # Connect to shared drive, use drive letter M subprocess.call(r'net use m: \\shared\folder /user:user123 password', shell=True) 

Prefiero este enfoque simple, especialmente si toda la información es estática.

Bueno, aquí hay otro método …

Este fue después de pasar por Win32wnet. Déjame saber lo que piensas…

 def mapDrive(drive, networkPath, user, password, force=0): print networkPath if (os.path.exists(drive)): print drive, " Drive in use, trying to unmap..." if force: try: win32wnet.WNetCancelConnection2(drive, 1, 1) print drive, "successfully unmapped..." except: print drive, "Unmap failed, This might not be a network drive..." return -1 else: print "Non-forcing call. Will not unmap..." return -1 else: print drive, " drive is free..." if (os.path.exists(networkPath)): print networkPath, " is found..." print "Trying to map ", networkPath, " on to ", drive, " ....." try: win32wnet.WNetAddConnection2(win32netcon.RESOURCETYPE_DISK, drive, networkPath, None, user, password) except: print "Unexpected error..." return -1 print "Mapping successful" return 1 else: print "Network path unreachable..." return -1 

Y para desasignar, solo usa …

 def unmapDrive(drive, force=0): #Check if the drive is in use if (os.path.exists(drive)): print "drive in use, trying to unmap..." if force == 0: print "Executing un-forced call..." try: win32wnet.WNetCancelConnection2(drive, 1, force) print drive, "successfully unmapped..." return 1 except: print "Unmap failed, try again..." return -1 else: print drive, " Drive is already free..." return -1 

Aquí hay un par de enlaces que muestran el uso del módulo win32net que debe proporcionar la funcionalidad que necesita.

http://docs.activestate.com/activepython/2.4/pywin32/html/win32/help/win32net.html http://www.blog.pythonlibrary.org/?p=20

Suponiendo que importa las bibliotecas necesarias, esto formaba parte de un servidor RPC en el que el cliente solicitó al servidor que asignara una unidad localmente …

 #Small function to check the availability of network resource. def isAvailable(path): winCMD = 'IF EXIST ' + path + ' echo YES' cmdOutPut = subprocess.Popen(winCMD, stdout=subprocess.PIPE, shell=True).communicate() return string.find(str(cmdOutPut), 'YES',) #Small function to check if the mention location is a directory def isDirectory(path): winCMD = 'dir ' + path + ' | FIND ".."' cmdOutPut = subprocess.Popen(winCMD, stdout=subprocess.PIPE, shell=True).communicate() return string.find(str(cmdOutPut), 'DIR',) 

================ Compruebe los espacios en blanco desde aquí, estos eran parte de una función ============

 def mapNetworkDrive(self, drive, networkPath, user, password): #Check for drive availability if isAvailable(drive) > -1: #Drive letter is already in use return -1 #Check for network resource availability if isAvailable(networkPath) == -1: print "Path not accessible: ", networkPath #Network path is not reachable return -1 #Prepare 'NET USE' commands winCMD1 = 'NET USE ' + drive + ' ' + networkPath winCMD2 = winCMD1 + ' ' + password + ' /User' + user print "winCMD1 = ", winCMD1 print "winCMD2 = ", winCMD2 #Execute 'NET USE' command with authentication winCMD = winCMD2 cmdOutPut = subprocess.Popen(winCMD, stdout=subprocess.PIPE, shell=True).communicate() print "Executed: ", winCMD if string.find(str(cmdOutPut), 'successfully',) == -1: print winCMD, " FAILED" winCMD = winCMD1 #Execute 'NET USE' command without authentication, incase session already open cmdOutPut = subprocess.Popen(winCMD, stdout=subprocess.PIPE, shell=True).communicate() print "Executed: ", winCMD if string.find(str(cmdOutPut), 'successfully',) == -1: print winCMD, " FAILED" return -1 #Mapped on second try return 1 #Mapped with first try return 1 def unmapNetworkDrive(self, drive): #Check if the drive is in use if isAvailable(drive) == -1: #Drive is not in use return -1 #Prepare 'NET USE' command winCMD = 'net use ' + drive + ' /DELETE' cmdOutPut = subprocess.Popen(winCMD, stdout=subprocess.PIPE, shell=True).communicate() if string.find(str(cmdOutPut), 'successfully',) == -1: #Could not UN-MAP, this might be a physical drive return -1 #UN-MAP successful return 1 

No tengo un servidor con el que probar aquí en casa, pero ¿quizás podría simplemente usar el módulo de subproceso de la biblioteca estándar para ejecutar el comando NET USE apropiado?

Mirando a NET HELP USE desde un indicador de comandos de Windows, parece que debería poder ingresar tanto la contraseña como la identificación del usuario en el comando net use para asignar la unidad.

Una prueba rápida en el intérprete de un comando de uso de net bare sin el material de mapeo:

 >>> import subprocess >>> subprocess.check_call(['net', 'use']) New connections will be remembered. There are no entries in the list. 0 >>> 

Tuve problemas para hacer funcionar esta línea:

win32wnet.WNetAddConnection2 (win32netcon.RESOURCETYPE_DISK, unidad, networkPath, ninguna, usuario, contraseña)

Pero fue exitoso con esto:

win32wnet.WNetAddConnection2 (1, ‘Z:’, r ‘\ UNCpath \ share’, Ninguno, ‘inicio de sesión’, ‘contraseña’)

Si desea asignar el usuario de inicio de sesión actual, creo que el subproceso resuelve su problema. Pero es que desea controlar diferentes asignaciones para diferentes usuarios, desde una sola cuenta maestra. Podrías hacer esto desde el registro de windows.

La idea es cargar el perfil de un usuario determinado.

 import win32api import win32security import win32profile import win32netcon import win32net import win32netcon import win32con il = 'G' m = '\\\\192.168.1.16\\my_share_folder' usu = 'my_user' cla = 'passwd' #login the user hUser = win32security.LogonUser( usu, None, cla, win32security.LOGON32_LOGON_NETWORK, win32security.LOGON32_PROVIDER_DEFAULT ) #load the profile hReg = win32profile.LoadUserProfile ( hUser, {"UserName" : usu} ) #alter the regedit entries of usu win32api.RegCreateKey(hReg, "Network") hkey = win32api.RegOpenKey(hReg, "Network\\", 0, win32con.KEY_ALL_ACCESS) win32api.RegCreateKey(hkey, il) hkey = win32api.RegOpenKey(hReg, "Network\\%s" % il, 0, win32con.KEY_ALL_ACCESS) win32api.RegSetValueEx(hkey, "ConnectionType", 0, win32con.REG_DWORD, 1) win32api.RegSetValueEx(hkey, "DeferFlags", 0, win32con.REG_DWORD, 4) win32api.RegSetValueEx(hkey, "ProviderName", 0, win32con.REG_SZ, "Red de Microsoft Windows") win32api.RegSetValueEx(hkey, "ProviderType", 0, win32con.REG_DWORD, 131072) win32api.RegSetValueEx(hkey, "RemotePath", 0, win32con.REG_SZ, m) win32api.RegSetValueEx(hkey, "UserName", 0, win32con.REG_DWORD, 0) 

Una alternativa al subproceso:

 import os os.system("net use m: \\\\shared\folder") 

O

 import os cmd = "net use m: \\\\shared\folder" os.system(cmd)