我正在尝试打开一个 Windows 资源管理器窗口,其中选择了特定文件夹中的指定项目。
我尝试使用 SHOpenFolderAndSelectItems Win32 API 和 C# 来实现该程序。按照此处的答案:https://stackoverflow.com/a/12262552
using System.Runtime.InteropServices;
SelectInFileExplorer("C:\\Users");
void SelectInFileExplorer(string fullPath)
{
if (string.IsNullOrEmpty(fullPath))
throw new ArgumentNullException("fullPath");
fullPath = Path.GetFullPath(fullPath);
IntPtr pidlList = NativeMethods.ILCreateFromPathW(fullPath);
if (pidlList != IntPtr.Zero)
try
{
// Open parent folder and select item
Marshal.ThrowExceptionForHR(NativeMethods.SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0));
}
finally
{
NativeMethods.ILFree(pidlList);
}
}
static class NativeMethods
{
[DllImport("shell32.dll", ExactSpelling = true)]
public static extern void ILFree(IntPtr pidlList);
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern IntPtr ILCreateFromPathW(string pszPath);
[DllImport("shell32.dll", ExactSpelling = true)]
public static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags);
}
它有效,但现在我想使用 Go 实现同样的事情。
这是我的代码:
package main
import (
"fmt"
"path/filepath"
"syscall"
"unsafe"
)
func main() {
SelectInFileExplorer("C:\\Users")
fmt.Println("Hello, World!")
}
func SelectInFileExplorer(fullPath string) {
if fullPath == "" {
panic("fullPath cannot be empty")
}
fullPath, _ = filepath.Abs(fullPath)
pidlList, err := ILCreateFromPathW(fullPath)
if err != nil {
panic(err)
}
defer ILFree(pidlList)
// Open parent folder and select item
err = SHOpenFolderAndSelectItems(pidlList, 0, 0)
if err != nil {
panic(err)
}
}
func ILFree(pidlList uintptr) {
shell32 := syscall.NewLazyDLL("shell32.dll")
proc := shell32.NewProc("ILFree")
proc.Call(pidlList)
}
func ILCreateFromPathW(pszPath string) (uintptr, error) {
shell32 := syscall.NewLazyDLL("shell32.dll")
proc := shell32.NewProc("ILCreateFromPathW")
pszPathPtr, err := syscall.UTF16PtrFromString(pszPath)
if err != nil {
return 0, err
}
ret, _, err := proc.Call(uintptr(unsafe.Pointer(pszPathPtr)))
if ret == 0 {
return 0, err
}
return ret, nil
}
func SHOpenFolderAndSelectItems(pidlList uintptr, cild uint32, children uintptr) error {
shell32 := syscall.NewLazyDLL("shell32.dll")
proc := shell32.NewProc("SHOpenFolderAndSelectItems")
ret, _, err := proc.Call(pidlList, uintptr(cild), children, 0)
if ret != 0 && err.Error() != "The operation completed successfully." {
return err
}
return nil
}
它不起作用,因为我执行代码后没有任何反应。探索者没有出现。
我阅读了一些有关API使用的文档:https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shopenfolderandselectitems
还是不知道发生了什么。也许不是因为编程语言本身。我认为在 GO 中调用 DLL 函数有点复杂,而且我可能在函数调用方面做错了什么。
如官方
SHOpenFolderAndSelectItems
文档中所述备注:
使用前必须调用CoInitialize或CoInitializeEx SHOpenFolderAndSelectItems。不这样做会导致 SHOpenFolderAndSelectItems 失败。
因此,您必须在 main 中添加类似的内容,例如:
ole32 := syscall.NewLazyDLL("ole32.dll")
proc := ole32.NewProc("CoInitialize")
proc.Call(0)
它可以在 .NET 中工作,因为 .NET 自动执行此操作