使用 lxn/win 在 golang 中处理 LPTSTR

Mar*_*ged 1 windows api go

我有这段代码运行时不返回err,但根本没有完成其工作,因为它没有返回预期值。这个想法是SHGetSpecialFolderPath为了检索 Windows 目录的路径(C:\Windows例如)。此 api 调用具有以下签名:

BOOL SHGetSpecialFolderPath(
        HWND   hwndOwner, 
        _Out_ LPTSTR lpszPath,
        _In_  int    csidl,
        _In_  BOOL   fCreate );
Run Code Online (Sandbox Code Playgroud)

我知道它已被弃用,但即使在当前的 Windows 版本上仍然可用。我必须使用这个 API,因为我需要支持早于 Windows 7 的 Windows 版本(我知道这些版本已经过时,甚至已经停产)

这是一段代码:

target := "XXX...XXX" // hard coded string with more than 600 characters
buffer, err := syscall.UTF16PtrFromString(target)
if err != nil {
        fmt.Println("conversion of string:", err)
}

result := win.SHGetSpecialFolderPath(0, buffer, win.CSIDL_WINDOWS, false)
if err != nil {
    fmt.Println("result of get folder:", err)
}

fmt.Println("folder retrieved ok: ", result)
fmt.Println("folder: ", target)
}
Run Code Online (Sandbox Code Playgroud)

均未设置err,API 调用返回true,但字符串未更改:

folder retrieved ok:  true
folder: XXX...XXX
Run Code Online (Sandbox Code Playgroud)

结果在 Windows 10 x64 和运行 Windows XP SP3 的测试虚拟机上是相同的(我知道 XP 本质上是不安全的)

我已经在 SO和其他网站上看到了如何使用LPTRSTRwithunsafeuintptrhere 的示例,但它们都没有在我的 golang 版本上编译(即,我用 编译)go version go1.10.1 windows/amd64GOARCH=386

pet*_*rSO 5

以逻辑、系统的方式解决问题。


仔细阅读该函数的 Microsoft 文档。

SHGetSpecialFolderPath 函数


仔细阅读lxn/win该函数的包文档。

包赢

import "github.com/lxn/win" 
Run Code Online (Sandbox Code Playgroud)

函数 SHGetSpecialFolderPath

func SHGetSpecialFolderPath(hwndOwner HWND, lpszPath *uint16, csidl CSIDL, fCreate bool) bool
Run Code Online (Sandbox Code Playgroud)

现在,使用文档,在 Go 中实现函数调用。Go Unicode 字符串是 UTF-8 编码的。Windows Unicode 字符串采用 UTF-16 编码。

package main

import (
    "fmt"
    "syscall"

    "github.com/lxn/win"
)

func main() {
    buf := make([]uint16, win.MAX_PATH)
    rv := win.SHGetSpecialFolderPath(win.HWND(0), &buf[0], win.CSIDL_WINDOWS, false)
    fmt.Println(rv)
    path := syscall.UTF16ToString(buf)
    fmt.Println(path)
}
Run Code Online (Sandbox Code Playgroud)

输出:

true
C:\Windows
Run Code Online (Sandbox Code Playgroud)