在 Go 中呼叫 GetVolumeInformation WinAPI 函數
本文詳細介紹了使用 Go 中的 GetVolumeInformation WinAPI 函數檢索磁碟區名稱的嘗試。然而,最初的努力卻遇到了意外的錯誤。
問題陳述
嘗試將字串緩衝區作為 lpVolumeNameBuffer 參數傳遞時出現問題。程式碼失敗,錯誤「意外的錯誤位址0xffffffffffffffff。」
分析
使用unsafe.Pointer 將Go 字串轉換為指向uint16 陣列的指標被確定為錯誤的指標的原因。在 Go 中,在沒有很好地理解後果的情況下,通常不應直接操作指標。
解決方案
為了解決此問題,重寫了程式碼以建立一個固定的-uint16 字元的緩衝區大小,並將指向緩衝區第一個元素的指標會以lpVolumeNameBuffer 參數傳遞。這種方法可確保緩衝區正確對齊,並避免使用 unsafe.Pointer。
這裡是修正後的程式碼:
<code class="go">package main import ( "fmt" "syscall" ) func main() { const RootPathName = `C:\` var VolumeNameBuffer = make([]uint16, syscall.MAX_PATH+1) var nVolumeNameSize = uint32(len(VolumeNameBuffer)) var VolumeSerialNumber uint32 var MaximumComponentLength uint32 var FileSystemFlags uint32 var FileSystemNameBuffer = make([]uint16, 255) var nFileSystemNameSize uint32 = syscall.MAX_PATH + 1 kernel32, err := syscall.LoadLibrary("kernel32.dll") if err != nil { fmt.Println("Error loading kernel32: ", err) return } getVolume, err := syscall.GetProcAddress(kernel32, "GetVolumeInformationW") if err != nil { fmt.Println("Error getting GetVolumeInformation address: ", err) return } var nargs uintptr = 8 ret, _, callErr := syscall.Syscall9(uintptr(getVolume), nargs, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(RootPathName))), uintptr(unsafe.Pointer(&VolumeNameBuffer[0])), uintptr(nVolumeNameSize), uintptr(unsafe.Pointer(&VolumeSerialNumber)), uintptr(unsafe.Pointer(&MaximumComponentLength)), uintptr(unsafe.Pointer(&FileSystemFlags)), uintptr(unsafe.Pointer(&FileSystemNameBuffer[0])), uintptr(nFileSystemNameSize), 0) if ret != 0 { fmt.Println("Call succeeded: ", syscall.UTF16ToString(VolumeNameBuffer)) } else { fmt.Println("Call failed: ", callErr) } }</code>
此修改後的程式碼應該會成功擷取並列印名稱指定體積。
以上是如何在Go中正確呼叫GetVolumeInformation WinAPI函數,並避免意外錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!