问题描述
如何才能仅获取实体驱动器的所有装入点的列表?我看到这里有类似的答案,但它列出了包括网络共享在内的所有装入点。How can I get a listing of all drives on Windows using golang?
推荐答案
好了,我已决定重拾Win32API编程技能并准备解决方案。
基于the thread you referred to中的LAME方法的解决方案如下:
package main
import (
"errors"
"fmt"
"log"
"syscall"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
getDriveTypeWProc = kernel32.NewProc("GetDriveTypeW")
)
func getDriveType(rootPathName []uint16) (int, error) {
rc, _, _ := getDriveTypeWProc.Call(
uintptr(unsafe.Pointer(&rootPathName[0])),
)
dt := int(rc)
if dt == driveUnknown || dt == driveNoRootDir {
return -1, driveTypeErrors[dt]
}
return dt, nil
}
var (
errUnknownDriveType = errors.New("unknown drive type")
errNoRootDir = errors.New("invalid root drive path")
driveTypeErrors = [...]error{
0: errUnknownDriveType,
1: errNoRootDir,
}
)
const (
driveUnknown = iota
driveNoRootDir
driveRemovable
driveFixed
driveRemote
driveCDROM
driveRamdisk
)
func getFixedDOSDrives() ([]string, error) {
var drive = [4]uint16{
1: ':',
2: '\',
}
var drives []string
for c := 'A'; c <= 'Z'; c++ {
drive[0] = uint16(c)
dt, err := getDriveType(drive[:])
if err != nil {
if err == errNoRootDir {
continue
}
return nil, fmt.Errorf("error getting type of: %s: %s",
syscall.UTF16ToString(drive[:]), err)
}
if dt != driveFixed {
continue
}
drives = append(drives, syscall.UTF16ToString(drive[:]))
}
return drives, nil
}
func main() {
drives, err := getFixedDOSDrives()
if err != nil {
log.Fatal(err)
}
for _, drive := range drives {
log.Println(drive)
}
}
运行By Box(在Wine 4.0下)我得到:
tmp$ GOOS=windows go build drvs.go
tmp$ wine64 ./drvs.exe
0009:fixme:process:SetProcessPriorityBoost (0xffffffffffffffff,1): stub
2020/07/06 21:06:02 C:
2020/07/06 21:06:02 D:
2020/07/06 21:06:02 X:
2020/07/06 21:06:02 Z:
(使用winecfg
映射所有驱动器。)
此方法的问题是:
即使系统中存在的DOS驱动器数量远远少于ASCII大写字母的数量,它也会执行26个系统调用。
在今天的Windows系统上,驱动器可以映射到常规目录下--这与POSIX系统非常相似,因此它根本没有DOS驱动器号。
Eryk Sun准确地暗示了应该对此做些什么。 我将尝试提出一个适当的(尽管更复杂的)解决方案,将这些考虑因素考虑在内。
以下是gist及其代码。
GetDriveTypeW
docs。
希望这将使您对Win32 API的工作原理以及如何在Go中使用它感兴趣。尝试查看Go安装中的syscall
包的源代码--再加上MSDN文档,这应该很有启发性。