Go で GetVolumeInformation WinAPI 関数を正しく呼び出し、予期しないエラーを回避するにはどうすればよいですか?

Susan Sarandon
リリース: 2024-10-25 08:17:28
オリジナル
397 人が閲覧しました

How to correctly invoke the GetVolumeInformation WinAPI function in Go, and avoid unexpected errors?

Go での Get VolumeInformation WinAPI 関数の呼び出し

この記事では、Go から Get VolumeInformation WinAPI 関数を使用してボリュームの名前を取得する試みについて詳しく説明します。ただし、最初の作業で予期しないエラーが発生しました。

問題ステートメント

この問題は、文字列バッファを lpVolumeNameBuffer パラメータとして渡そうとしたときに発生しました。コードは、「予期しない障害アドレス 0xffffffffffffffff」というエラーで失敗しました。

分析

Go 文字列を uint16 配列へのポインターに変換するための unsafe.Pointer の使用がエラーの原因として特定されました。 Go では、一般に、結果をよく理解せずにポインタを直接操作しないでください。

解決策

この問題を解決するために、コードが書き直されて修正コードが作成されました。 -size バッファを 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 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!