我使用 Java JNA 来执行 Windows API 命令。
我有一个作为本地系统运行的后台服务。 从这个后台服务中,我想在当前活动的桌面和用户上生成一个新进程,例如记事本.exe。新进程不应以提升方式运行,而应具有活动的登录用户权限。
我使用
- WTSGetActiveConsoleSessionId 获取活动会话
- WTSQueryUserToken获取相关令牌
- 创建进程为用户以启动进程
如果我构建一个 jar 并从本地系统帐户使用 java -jar my.jar 启动 jar,这工作正常。
但是,我从 Install4j 安装程序运行代码,它或多或少是包装在 exe 中的 JVM。相同的代码现在失败,并且 CreateProcessAsUser 导致错误代码 5(无访问权限)
- 我比较了令牌,找不到任何区别。相同的用户、所有者、组和权限。
- 我尝试使用进程监视器来查找任何特别的东西:没有什么
- 我尝试使用CreateProcessWithTokenW而不是CreateProcessAsUser。进程启动但立即退出(可能是窗口站/桌面问题)
预期结果:"子"进程启动并在当前活动的桌面上显示 UI。
实际结果:创建进程为用户上的错误代码 5
final PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
final int activeConsoleSessionId = Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId();
final PointerByReference userPrimaryProcessToken = new PointerByReference();
if (!Wtsapi32Ext.INSTANCE.WTSQueryUserToken(activeConsoleSessionId, userPrimaryProcessToken)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
final STARTUPINFO startupInfo = new STARTUPINFO();
startupInfo.clear();
startupInfo.lpDesktop = "winsta0\default";
startupInfo.wShowWindow = new WORD(1);
startupInfo.cb = new DWORD(processInformation.size());
final String cmdString = "C:\Windows\System32\notepad.exe";
if (!AdvapiExt.INSTANCE.CreateProcessAsUser(new HANDLE(userPrimaryProcessToken.getValue()), null, cmdString, null, null, true, Kernel32.CREATE_UNICODE_ENVIRONMENT, null, "c:\", startupInfo, processInformation)) {
final int error = Kernel32.INSTANCE.GetLastError();
throw new Win32Exception(error);
}
这不是一个真正的答案,但是在系统重新启动和Windows更新后,我无法再重现该问题。如果我设法再次重现它,我将继续调查。
在问题"消失"之前注意到的几件事:
1. 在更新窗口之前,我启用了程序执行审计(本地安全策略),并在 Windows 日志中看到,根据日志,应用程序启动了,即使没有窗口或正在运行的进程,并且 CreateProcessAsUser 返回了一个错误......
阿拉伯数字。 只有当服务.exe在调用链中时,问题才会发生。如果我直接通过 psexe 作为本地系统进程启动应用程序,则一切正常。