如何使用 python 在 windows 上查找未分配的驱动器号

How to find a unassigned drive letter on windows with python

我需要从 python 脚本中找到 windows 上的可用盘符。 Free 表示未分配给任何物理或远程设备。

我做了一些研究并在 Whosebug 上找到了解决方案(不记得确切的 link):

# for python 2.7
import string
import win32api

def getfreedriveletter():
    """ Find first free drive letter """
    assigneddrives = win32api.GetLogicalDriveStrings().split('[=12=]0')[:-1]
    assigneddrives = [item.rstrip(':\').lower() for item in assigneddrives]
    for driveletter in list(string.ascii_lowercase[2:]):
        if not driveletter in assigneddrives:
            return driveletter.upper() + ':'

这适用于所有物理驱动器和连接的网络驱动器。但不适用于当前断开连接的驱动器。 如何获取所有使用过的盘符,以及临时未使用的盘符?

因为我会将找到的字母传递给外部脚本,该脚本将 运行 Winshell 命令 'subst /d letter'。我不能传递当前未安装的驱动器,因为它会删除网络驱动器映射。

我找到的唯一方法是 winshellcmd 'net use' 查找不可用驱动器的结果。

这是我的解决方案,如果你有更好的方法,请与我分享:

# for python 2.7
import string
import win32api
from subprocess import Popen, PIPE

def _getnetdrives():
""" As _getfreedriveletter can not find unconnected network drives
    get these drives with shell cmd 'net use' """
    callstr = 'net use'
    phandle = Popen(callstr, stdout=PIPE)
    presult = phandle.communicate()
    stdout = presult[0]
    # _stderr = presult[1]
    networkdriveletters = []
    for line in stdout.split('\n'):
        if ':        ' in line:
             networkdriveletters.append(line.split()[1] + '\')
    return networkdriveletters

def getfreedriveletter():
    """ Find first free drive letter """
    assigneddrives = win32api.GetLogicalDriveStrings().split('[=10=]0')[:-1]
    assigneddrives = assigneddrives + _getnetdrives()
    assigneddrives = [item.rstrip(':\').lower() for item in assigneddrives]
    for driveletter in list(string.ascii_lowercase[2:]): #array starts from 'c' as i dont want a and b drive
        if not driveletter in assigneddrives:
        return driveletter.upper() + ':'

创建子进程的成本相对较高,解析自由格式文本输出并不是最可靠的技术。您可以改用 PyWin32 来调用 net use 调用的相同 API 函数。

import string
import win32api
import win32wnet
import win32netcon

def get_free_drive():
    drives = set(string.ascii_uppercase[2:])
    for d in win32api.GetLogicalDriveStrings().split(':\\x00'):
        drives.discard(d)
    # Discard persistent network drives, even if not connected.
    henum = win32wnet.WNetOpenEnum(win32netcon.RESOURCE_REMEMBERED, 
        win32netcon.RESOURCETYPE_DISK, 0, None)
    while True:
        result = win32wnet.WNetEnumResource(henum)
        if not result:
            break
        for r in result:
            if len(r.lpLocalName) == 2 and r.lpLocalName[1] == ':':
                drives.discard(r.lpLocalName[0])
    if drives:
        return sorted(drives)[-1] + ':'

注意这个函数returns最后一个可用的驱动器号。通常的做法是从列表末尾分配映射驱动器和替代驱动器(例如从 net.exe 和 subst.exe),从开头分配本地系统驱动器。