CreateProcessAsUser 函数 运行 来自服务的 GUI 程序
CreateProcessAsUser function to run a GUI program from a service
下面是我用于 运行 来自服务应用程序的 GUI 应用程序的代码。我正在传递命令字符串“C:\Windows\notepad.exe”。
它没有打开记事本,甚至没有给出任何错误。即使在使用 WTSQueryUserToken 之后,hToken 仍为空。
这是以用户身份创建过程的文档 link:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera
private void cpasUser(String cmd) {
HANDLE h = null;
final HANDLEByReference childStdInRead = new HANDLEByReference();
final HANDLEByReference childStdInWrite = new HANDLEByReference();
final HANDLEByReference childStdOutRead = new HANDLEByReference();
final HANDLEByReference childStdOutWrite = new HANDLEByReference();
final int HANDLE_FLAG_INHERIT = 0x00000001;
final int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
final int BUFSIZE = 4096;
final int GENERIC_READ = 0x80000000;
final int FILE_ATTRIBUTE_READONLY = 1;
final int OPEN_EXISTING = 3;
final DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
final int STARTF_USESTDHANDLES = 0x00000100;
String szCmdline = cmd;
PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
STARTUPINFO startupInfo = new STARTUPINFO();
startupInfo.cb = new DWORD(processInformation.size());
startupInfo.hStdError = childStdOutWrite.getValue();
startupInfo.hStdOutput = childStdOutWrite.getValue();
startupInfo.hStdInput = childStdInRead.getValue();
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
HANDLE hToken = null;
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), hToken) ;
//be sure that the handle is correct ! (can be the issue)
if (hToken == null) logger.info("Token error.");
if (!Advapi32.INSTANCE.CreateProcessAsUser(
hToken,
szCmdline,
null,
null,
null,
true,
32,
null,
null,
startupInfo,
processInformation)){
// System.err.println(Advapi32.INSTANCE.GetLastError());
logger.error("Cannot create process as User ");
logger.error("error code "+Native.getLastError());
}
MyWtsApi32.java
public interface MyWtsapi32 extends Wtsapi32 {
// Your own instance to access your functions
MyWtsapi32 INSTANCE = Native.load("Wtsapi32", MyWtsapi32.class, W32APIOptions.DEFAULT_OPTIONS);
// From https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
int MB_OK = 0;
// The function to send the message
boolean WTSSendMessageW(HANDLE hServer, int SessionId,
LPWSTR pTitle, int TitleLength,
LPWSTR pMessage, int MessageLength,
int Style, int Timeout, IntByReference pResponse, boolean bWait);
boolean WTSQueryUserToken(long SessionId,HANDLE hServer);
}
Kernel32Ext.java
public interface Kernel32Ext extends Kernel32{
Kernel32Ext INSTANCE = Native.load("Kernel32",Kernel32Ext.class,W32APIOptions.DEFAULT_OPTIONS);
int WTSGetActiveConsoleSessionId();
}
当您的 JNA 函数映射不起作用时,第一个调试步骤应该是检查您的函数映射。
WTSQueryUserToken
定义为:
BOOL WTSQueryUserToken(
ULONG SessionId,
PHANDLE phToken
);
Windows类型ULONG
是an unsigned 32-bit integer;它应该映射为 int
,而不是 long
。
PHANDLE
是指向 HANDLE
的指针,而不是句柄本身。正确的 JNA 映射是 HANDLEByReference
.
所以你的接口函数映射应该是:
boolean WTSQueryUserToken(int SessionId, HANDLEByReference hServer);
调用它的代码应该是:
HANDLEByReference phToken = new HANDLEByReference();
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
// you should probably check the return value here
// on failure throw LastErrorException
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), phToken);
// Extract the HANDLE for use in later code
HANDLE hToken = phToken.getValue();
下面是我用于 运行 来自服务应用程序的 GUI 应用程序的代码。我正在传递命令字符串“C:\Windows\notepad.exe”。
它没有打开记事本,甚至没有给出任何错误。即使在使用 WTSQueryUserToken 之后,hToken 仍为空。 这是以用户身份创建过程的文档 link:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera
private void cpasUser(String cmd) {
HANDLE h = null;
final HANDLEByReference childStdInRead = new HANDLEByReference();
final HANDLEByReference childStdInWrite = new HANDLEByReference();
final HANDLEByReference childStdOutRead = new HANDLEByReference();
final HANDLEByReference childStdOutWrite = new HANDLEByReference();
final int HANDLE_FLAG_INHERIT = 0x00000001;
final int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
final int BUFSIZE = 4096;
final int GENERIC_READ = 0x80000000;
final int FILE_ATTRIBUTE_READONLY = 1;
final int OPEN_EXISTING = 3;
final DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
final int STARTF_USESTDHANDLES = 0x00000100;
String szCmdline = cmd;
PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
STARTUPINFO startupInfo = new STARTUPINFO();
startupInfo.cb = new DWORD(processInformation.size());
startupInfo.hStdError = childStdOutWrite.getValue();
startupInfo.hStdOutput = childStdOutWrite.getValue();
startupInfo.hStdInput = childStdInRead.getValue();
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
HANDLE hToken = null;
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), hToken) ;
//be sure that the handle is correct ! (can be the issue)
if (hToken == null) logger.info("Token error.");
if (!Advapi32.INSTANCE.CreateProcessAsUser(
hToken,
szCmdline,
null,
null,
null,
true,
32,
null,
null,
startupInfo,
processInformation)){
// System.err.println(Advapi32.INSTANCE.GetLastError());
logger.error("Cannot create process as User ");
logger.error("error code "+Native.getLastError());
}
MyWtsApi32.java
public interface MyWtsapi32 extends Wtsapi32 {
// Your own instance to access your functions
MyWtsapi32 INSTANCE = Native.load("Wtsapi32", MyWtsapi32.class, W32APIOptions.DEFAULT_OPTIONS);
// From https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
int MB_OK = 0;
// The function to send the message
boolean WTSSendMessageW(HANDLE hServer, int SessionId,
LPWSTR pTitle, int TitleLength,
LPWSTR pMessage, int MessageLength,
int Style, int Timeout, IntByReference pResponse, boolean bWait);
boolean WTSQueryUserToken(long SessionId,HANDLE hServer);
}
Kernel32Ext.java
public interface Kernel32Ext extends Kernel32{
Kernel32Ext INSTANCE = Native.load("Kernel32",Kernel32Ext.class,W32APIOptions.DEFAULT_OPTIONS);
int WTSGetActiveConsoleSessionId();
}
当您的 JNA 函数映射不起作用时,第一个调试步骤应该是检查您的函数映射。
WTSQueryUserToken
定义为:
BOOL WTSQueryUserToken(
ULONG SessionId,
PHANDLE phToken
);
Windows类型ULONG
是an unsigned 32-bit integer;它应该映射为 int
,而不是 long
。
PHANDLE
是指向 HANDLE
的指针,而不是句柄本身。正确的 JNA 映射是 HANDLEByReference
.
所以你的接口函数映射应该是:
boolean WTSQueryUserToken(int SessionId, HANDLEByReference hServer);
调用它的代码应该是:
HANDLEByReference phToken = new HANDLEByReference();
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
// you should probably check the return value here
// on failure throw LastErrorException
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), phToken);
// Extract the HANDLE for use in later code
HANDLE hToken = phToken.getValue();