gpt4 book ai didi

c# - 使用 JNA 在 Windows 资源管理器中获取选定的文件项

转载 作者:可可西里 更新时间:2023-11-01 11:54:24 26 4
gpt4 key购买 nike

我正在使用 Java 为 Windows 编写 OSX Quick-look 替代方案,但在如何在 Activity 资源管理器窗口中获取 Activity 文件选择方面遇到了问题,以下是我的尝试:

    @Override
public void nativeKeyReleased(NativeKeyEvent e) {
System.out.println("key up:"
+ NativeKeyEvent.getKeyText(e.getKeyCode()));
if (e.getKeyCode() == NativeKeyEvent.VK_SPACE) {
System.out.println("Space detected! intercept active window");
char[] buffer = new char[MSWindowConstants.MAX_TITLE_LENGTH * 2];
User32DLL.GetWindowTextW(User32DLL.GetForegroundWindow(),
buffer, MSWindowConstants.MAX_TITLE_LENGTH);
System.out.println("Active window title: "
+ Native.toString(buffer));

PointerByReference pointer = new PointerByReference();
User32DLL.GetWindowThreadProcessId(
User32DLL.GetForegroundWindow(), pointer);
Pointer process = Kernel32.OpenProcess(
Kernel32.PROCESS_QUERY_INFORMATION
| Kernel32.PROCESS_VM_READ, false,
pointer.getValue());
Psapi.GetModuleBaseNameW(process, null, buffer,
MSWindowConstants.MAX_TITLE_LENGTH);
System.out.println("Active window process: "
+ Native.toString(buffer));

if(MSWindowConstants.SHELL_PROCESS_NAME.equals(Native.toString(buffer))){
System.out.println("shell focused! intercept selection");
// retrieve selected FileItems and get the path ...

//Ole32.INSTANCE

}



}

MSEnumeration 类:

public class MSEnumeration {



public static class Psapi {
static {
Native.register("psapi");
}

public static native int GetModuleBaseNameW(Pointer hProcess,
Pointer hmodule, char[] lpBaseName, int size);
}

public static class Kernel32 {
static {
Native.register("kernel32");
}
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_READ = 0x0010;

public static native int GetLastError();

public static native Pointer OpenProcess(int dwDesiredAccess,
boolean bInheritHandle, Pointer pointer);
}

public static class User32DLL {
static {
Native.register("user32");
}

public static native int GetWindowThreadProcessId(HWND hWnd,
PointerByReference pref);

public static native HWND GetForegroundWindow();

public static native int GetWindowTextW(HWND hWnd, char[] lpString,
int nMaxCount);
}

// public static class Shell32DLL{
// static {
// Native.register("shell32");
// }
//
// public static native Shell32 Windows();
// }
//
// public static class SHDocVwDLL{
// static {
// Native.register("shdocvw");
// }
//
// public static native ShellWindows ShellWindows();
//
// }

}

我对如何在 JNA 中实现以下内容感到困惑:

Get current selection in WindowsExplorer from a C# application?

IntPtr handle = GetForegroundWindow();

List<string> selected = new List<string>();
var shell = new Shell32.Shell();
foreach(SHDocVw.InternetExplorer window in shell.Windows())
{
if (window.HWND == (int)handle)
{
Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems();
foreach(Shell32.FolderItem item in items)
{
selected.Add(item.Path);
}
}
}

如何将其转换为 JNA 调用?

我查看了 JNA 的 Shell32 类和 COM(Ole32 类),但仍然没有找到任何结果。

我现在能想到的唯一解决方法是将给定的 C# 编译成一个单独的可执行文件,它接受参数并返回文件的路径,但我不太喜欢在 java 中嵌入另一个可执行文件的想法。

编辑:

一些进展:

public static final String CLSID_ShellWindows = "9BA05972-F6A8-11CF-A442-00A0C90A8F39";

public static final String IID_IShellWindows = "85CB6900-4D95-11CF-960C-0080C7F4EE85";

HRESULT hr = Ole32.INSTANCE
.CoCreateInstance(
GUID.fromString(CLSID_ShellWindows),
null,
WTypes.CLSCTX_ALL,
GUID.fromString(IID_IShellWindows),
p);

System.out.println("result:" + W32Errors.SUCCEEDED(hr)
+ "raw:" + hr.toString());

但由于某种原因结果永远不会是真的......

最佳答案

我放弃了 JNA(好吧,为了这个特定任务)并使用了 com4j (用优秀的 documentations )代替。

您首先要为所需的 dll 生成代码,在本例中为 shell32.dll,使用来自 com4j 的 tlbimp.jar

这个例子可能有点过时了,但我还是把它放在这里

if (isExplorer(getHWNDProcessName(hwnd))) {
IWebBrowser2 browser = getIWebBrowser2(hwnd);
IShellFolderViewDual3 view = getIShellFolderViewDual3(browser);
if (view != null && browser.visible()) {

lastHWND = hwnd;
FolderItems items = view.selectedItems();
ArrayList<Path> paths = new ArrayList<>(items.count());
for (Com4jObject object : items) {
FolderItem item = object.queryInterface(FolderItem.class);
if (item != null) {
paths.add(Paths.get(item.path()));
// this is for example only, do not create a new File just to get length
System.out.println("file: " + item.path() + " length: "
+ new File(item.path()).length() + " type:" + item.type());
}
}
}
}


// some methods used in the example...

public static IWebBrowser2 getIWebBrowser2(HWND hWnd) {
// TODO this can be potentially optimized
IShellWindows windows = ClassFactory.createShell().windows()
.queryInterface(IShellWindows.class);
for (Com4jObject window : windows) {
IWebBrowser2 browser = window.queryInterface(IWebBrowser2.class);
if (browser.hwnd() == getHWNDValue(hWnd))
return browser;
}
return null;
}

public static IShellFolderViewDual3 getIShellFolderViewDual3(IWebBrowser2 browser) {
if (browser == null)
return null;
return browser.document().queryInterface(IShellFolderViewDual3.class);
}

注意:可能缺少一些方法调用,我只发布了有关如何获取所选项目的重要部分。

重要

为此,您需要 Shell32.dllShdocvw.dll,因此您要做的是使用不同的 dll 生成两次代码

java -jar tlbimp.jar -o wsh -p test.wsh %WINDIR%\system32\Shell32.dll
java -jar tlbimp.jar -o wsh -p test.wsh %WINDIR%\system32\Shdocvw.dll

这样我们就可以使用 IWebBrowser2 和其他不错的东西,有关您可以使用该类执行的操作的列表,请参阅 docs

关于c# - 使用 JNA 在 Windows 资源管理器中获取选定的文件项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20968920/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com