【问题标题】:Call windows function (getting the font directory)调用windows函数(获取字体目录)
【发布时间】:2013-07-30 11:50:44
【问题描述】:

我尝试在 Windows 安装中找出字体文件夹。 AFAICS 建议的方法是在Shell32.dll 中调用SHGetKnownFolderPath,并将KNOWNFOLDERID 设置为FOLDERID_Fonts

我不知道在下面的代码中将什么传递给Call 函数:

package main

import (
    "syscall"
)

func main() {
    // HRESULT SHGetKnownFolderPath(
    //   _In_      REFKNOWNFOLDERID rfid,
    //   _In_      DWORD dwFlags,
    //   _In_opt_  HANDLE hToken,
    //   _Out_     PWSTR *ppszPath
    // );

    var (
        shell32             = syscall.NewLazyDLL("Shell32.dll")
        shGetKnowFolderPath = shell32.NewProc("SHGetKnownFolderPath")

        // Doesn't work, of course:
        folderId int
        flags    int
        handle   int
        retval   int
    )

    shGetKnowFolderPath.Call(uintptr(folderId), uintptr(flags), uintptr(handle), uintptr(retval))
}

有什么想法吗? (我想现在的解决方法是坚持%windir%\Fonts,但我想得到一个合适的解决方案)。

参考资料:

【问题讨论】:

  • 为什么投反对票?我可以做些什么来改善这个问题?

标签: winapi go


【解决方案1】:

例如,

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

type GUID struct {
    Data1 uint32
    Data2 uint16
    Data3 uint16
    Data4 [8]byte
}

var (
    FOLDERID_Fonts = GUID{0xFD228CB7, 0xAE11, 0x4AE3, [8]byte{0x86, 0x4C, 0x16, 0xF3, 0x91, 0x0A, 0xB8, 0xFE}}
)

var (
    modShell32               = syscall.NewLazyDLL("Shell32.dll")
    modOle32                 = syscall.NewLazyDLL("Ole32.dll")
    procSHGetKnownFolderPath = modShell32.NewProc("SHGetKnownFolderPath")
    procCoTaskMemFree        = modOle32.NewProc("CoTaskMemFree")
)

func SHGetKnownFolderPath(rfid *GUID, dwFlags uint32, hToken syscall.Handle, pszPath *uintptr) (retval error) {
    r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(rfid)), uintptr(dwFlags), uintptr(hToken), uintptr(unsafe.Pointer(pszPath)), 0, 0)
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func CoTaskMemFree(pv uintptr) {
    syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(pv), 0, 0)
    return
}

func FontFolder() (string, error) {
    var path uintptr
    err := SHGetKnownFolderPath(&FOLDERID_Fonts, 0, 0, &path)
    if err != nil {
        return "", err
    }
    defer CoTaskMemFree(path)
    folder := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(path))[:])
    return folder, nil
}

func main() {
    folder, err := FontFolder()
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("Font Folder:", folder)
}

输出:

Font Folder: C:\Windows\Fonts

【讨论】:

  • 太棒了,谢谢!仍在努力理解这一点。给我一天:)
  • 不错的答案...仅添加代码对新开发人员没有帮助...如果您添加流程的详细信息会很好
【解决方案2】:

golang.org/x/sys/windows 现在有一个 SHGetKnownFolderPath 的包装器,所以这更容易:

package main

import (
    "fmt"

    "golang.org/x/sys/windows"
)

func main() {
    path, err := windows.KnownFolderPath(windows.FOLDERID_Fonts, 0)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(path)
}

【讨论】:

    【解决方案3】:

    以防万一有人需要 golang 格式文档的文件夹 ID:

    在peterSO的代码示例中替换这个:

    FOLDERID_Documents = GUID{0xFDD39AD0, 0x238F, 0x46AF, [8]byte{0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7}}
    
    FOLDERID_PublicDocuments = GUID{0xED4824AF, 0xDCE4, 0x45A8, [8]byte{0x81, 0xE2, 0xFC, 0x79, 0x65, 0x08, 0x36, 0x34}}
    

    https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

    【讨论】:

      【解决方案4】:

      folderId 的字体目录是{FD228CB7-AE11-4AE3-864C-16F3910AB8FE}

      flags 可能是SHGFP_TYPE_DEFAULT

      handle 可能是NULL

      retval 我认为应该是bool,但我不确定。

      所有答案均来自您之前链接的SHGetFolderPath function

      【讨论】:

      • 返回值为HRESULT类型。可以使用宏 SUCCEEDED( hr )FAILED( hr ) 将其转换为布尔成功代码。
      • @Tim 谢谢,这是有道理的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      相关资源
      最近更新 更多