- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试弄清楚如何从我用 CreateProcessW 创建的进程。我看了文档,用谷歌搜索并搜索了这个列表,但我没有找到好的建议/样本然而 :)
这是我到目前为止的想法(它在 Windows 上运行良好,它是我的 java 代码中的相关片段):
Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
Kernel32.StartupInfo startupInfo = new Kernel32.StartupInfo();
Kernel32.ProcessInfo processInformation = new Kernel32.ProcessInfo();
if (!kernel32.CreateProcessW(null, new WString(command), null, null, false,
DETACHED_PROCESS, null, new WString(dir.getAbsolutePath()), startupInfo,
processInformation)) {
throw new IOException("Could not start process. Errno: " +
kernel32.GetLastError());
}
kernel32.CloseHandle(processInformation.hProcess);
kernel32.CloseHandle(processInformation.hThread);
那么...我如何获取该过程的输出?有没有人已经这样做了并且愿意分享示例?
提前感谢大家的帮助。
最佳答案
要为使用 CreateProcess
函数创建的进程写入控制台,MSDN 建议创建子进程并使用匿名管道重定向子进程的标准输入和输出句柄。
Creating a Child Process with Redirected Input and Output
由于JNA 3.3.0平台还没有包含我们需要的所有Kernel32函数,我们需要提供所需的JNA接口(interface)如下:(注意JNA 4.0为您提供了Kernel32)
Kernel32.java:
import java.util.HashMap;
import java.util.Map;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;
import com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES;
import com.sun.jna.platform.win32.WinBase.STARTUPINFO;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinBase.PROCESS_INFORMATION;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public interface Kernel32 extends StdCallLibrary {
final static Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
private static final long serialVersionUID = 1L;
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class, WIN32API_OPTIONS);
/*
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
*/
public boolean CreateProcess(
String lpApplicationName,
String lpCommandLine,
SECURITY_ATTRIBUTES lpProcessAttributes,
SECURITY_ATTRIBUTES lpThreadAttributes,
boolean bInheritHandles,
DWORD dwCreationFlags,
Pointer lpEnvironment,
String lpCurrentDirectory,
STARTUPINFO lpStartupInfo,
PROCESS_INFORMATION lpProcessInformation
);
public HANDLE GetStdHandle(DWORD nStdHandle);
public int GetLastError();
}
然后,主要部分:
RunTest.java:
import java.nio.ByteBuffer;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinBase.PROCESS_INFORMATION;
import com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES;
import com.sun.jna.platform.win32.WinBase.STARTUPINFO;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
import com.sun.jna.ptr.IntByReference;
public class RunTest {
static HANDLEByReference childStdInRead = new HANDLEByReference();
static HANDLEByReference childStdInWrite = new HANDLEByReference();
static HANDLEByReference childStdOutRead = new HANDLEByReference();
static HANDLEByReference childStdOutWrite = new HANDLEByReference();
static final int HANDLE_FLAG_INHERIT = 0x00000001;
static final int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
static final int BUFSIZE = 4096;
static final int GENERIC_READ = 0x80000000;
static final int FILE_ATTRIBUTE_READONLY = 1;
private static final int OPEN_EXISTING = 3;
private static final DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
private static final int STARTF_USESTDHANDLES = 0x00000100;
static HANDLE inputFile = null;
static void createChildProcess(String cmd){
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.
if (!Kernel32.INSTANCE.CreateProcess(
null,
szCmdline,
null,
null,
true,
new DWORD(0x00000020),
null,
null,
startupInfo,
processInformation)){
System.err.println(Kernel32.INSTANCE.GetLastError());
}
else {
com.sun.jna.platform.win32.Kernel32.INSTANCE.WaitForSingleObject(processInformation.hProcess, 0xFFFFFFFF);
com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(processInformation.hProcess);
com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(processInformation.hThread);
}
}
static void WriteToPipe()
// Read from a file and write its contents to the pipe for the child's STDIN.
// Stop when there is no more data.
{
IntByReference dwRead = new IntByReference();
IntByReference dwWritten = new IntByReference();
ByteBuffer buf = ByteBuffer.allocateDirect(BUFSIZE);
Pointer data = Native.getDirectBufferPointer(buf);
boolean bSuccess = true;
for (;;)
{
bSuccess = com.sun.jna.platform.win32.Kernel32.INSTANCE.ReadFile(inputFile, buf, BUFSIZE, dwRead, null);
if ( ! bSuccess || dwRead.getValue() == 0 ) break;
bSuccess = com.sun.jna.platform.win32.Kernel32.INSTANCE.WriteFile(childStdInWrite.getValue(), data.getByteArray(0, BUFSIZE), dwRead.getValue(), dwWritten, null);
if ( ! bSuccess ) break;
}
// Close the pipe handle so the child process stops reading.
if (!com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(childStdInWrite.getValue())){
System.err.println(Kernel32.INSTANCE.GetLastError());
}
}
static void ReadFromPipe()
// Read output from the child process's pipe for STDOUT
// and write to the parent process's pipe for STDOUT.
// Stop when there is no more data.
{
IntByReference dwRead = new IntByReference();
IntByReference dwWritten = new IntByReference();
ByteBuffer buf = ByteBuffer.allocateDirect(BUFSIZE);
Pointer data = Native.getDirectBufferPointer(buf);
boolean bSuccess = true;
HANDLE hParentStdOut = Kernel32.INSTANCE.GetStdHandle(STD_OUTPUT_HANDLE);
// Close the write end of the pipe before reading from the
// read end of the pipe, to control child process execution.
// The pipe is assumed to have enough buffer space to hold the
// data the child process has already written to it.
if (!com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(childStdOutWrite.getValue())){
System.err.println(Kernel32.INSTANCE.GetLastError());
}
for (;;)
{
bSuccess = com.sun.jna.platform.win32.Kernel32.INSTANCE.ReadFile( childStdOutRead.getValue(), buf, BUFSIZE, dwRead, null);
if( ! bSuccess || dwRead.getValue() == 0 ) break;
bSuccess = com.sun.jna.platform.win32.Kernel32.INSTANCE.WriteFile(hParentStdOut, data.getByteArray(0, BUFSIZE), dwRead.getValue(), dwWritten, null);
if (! bSuccess ) break;
}
}
/**
* {@link http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx}
*/
public static void main(String[] args) {
if (args.length < 1) {
System.err.println("Please specify a command.\n");
System.exit(1);
}
if (args.length < 2) {
System.err.println("Please specify an input file.\n");
System.exit(1);
}
SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES();
saAttr.dwLength = new DWORD(saAttr.size());
saAttr.bInheritHandle = true;
saAttr.lpSecurityDescriptor = null;
// Create a pipe for the child process's STDOUT.
if (!com.sun.jna.platform.win32.Kernel32.INSTANCE.CreatePipe(childStdOutRead, childStdOutWrite, saAttr, 0)){
System.err.println(Kernel32.INSTANCE.GetLastError());
}
// Ensure the read handle to the pipe for STDOUT is not inherited.
if (!com.sun.jna.platform.win32.Kernel32.INSTANCE.SetHandleInformation(childStdOutRead.getValue(), HANDLE_FLAG_INHERIT, 0)){
System.err.println(Kernel32.INSTANCE.GetLastError());;
}
// Create a pipe for the child process's STDIN.
if (!com.sun.jna.platform.win32.Kernel32.INSTANCE.CreatePipe(childStdInRead, childStdInWrite, saAttr, 0)){
System.err.println(Kernel32.INSTANCE.GetLastError());
}
// Ensure the write handle to the pipe for STDIN is not inherited.
if (!com.sun.jna.platform.win32.Kernel32.INSTANCE.SetHandleInformation(childStdInWrite.getValue(), HANDLE_FLAG_INHERIT, 0)){
System.err.println(Kernel32.INSTANCE.GetLastError());;
}
createChildProcess(args[0]);
inputFile = com.sun.jna.platform.win32.Kernel32.INSTANCE.CreateFile(
args[1],
GENERIC_READ,
0,
null,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
null);
// Write to the pipe that is the standard input for a child process.
// Data is written to the pipe's buffers, so it is not necessary to wait
// until the child process is running before writing data.
WriteToPipe();
System.out.println( "\n->Contents of \""+args[1]+"\" written to child STDIN pipe.\n");
// Read from pipe that is the standard output for child process.
System.out.println( "\n->Contents of child process STDOUT:\n\n" + args[1]);
ReadFromPipe();
System.out.println("\n->End of parent execution.\n");
// The remaining open handles are cleaned up when this process terminates.
// To avoid resource leaks in a larger application, close handles explicitly.
}
}
最初的 MSDN 程序只要求一个参数。但是,修改后的 Runtest java 程序将需要两个参数: (1) 命令行; (2) 输入文件。
示例用法:
java -jar RunTest.jar "C:\\Program Files\\Java\\jre6\\bin\\java.exe -version" "C:\\Documents and Settings\\Administrator\\Desktop\\test.txt"
程序输出示例:
->Contents of "C:\\Documents and Settings\\Administrator\\Desktop\\test.txt" written to child STDIN pipe.
->Contents of child process STDOUT:
C:\\Documents and Settings\\Administrator\\Desktop\\test.txt
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) Client VM (build 20.4-b02, mixed mode, sharing)
->End of parent execution.
如果你想看详细的版本... WindowsXPProcess.java
关于java - 使用 jna 和 CreateProcessW 时如何获取进程输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8903510/
我是 Linux 的新手,并且继承了保持我们的单一 Linux 服务器运行的职责。这是我们的SVN服务器,所以比较重要。 原来在我之前维护它的人有一个 cron 任务,当有太多 svnserve 进程
Node 虽然自身存在多个线程,但是运行在 v8 上的 JavaScript 是单线程的。Node 的 child_process 模块用于创建子进程,我们可以通过子进程充分利用 CPU。范例:
Jenkins 有这么多进程处于事件状态是否正常? 我检查了我的设置,我只配置了 2 个“执行者”... htop http://d.pr/i/RZzG+ 最佳答案 您不仅要限制 Master 中的执
我正在尝试在 scala 中运行这样的 bash 命令: cat "example file.txt" | grep abc Scala 有一个特殊的流程管道语法,所以这是我的第一个方法: val f
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我需要一些帮助来理解并发编程的基础知识。事实上,我读得越多,就越感到困惑。因此,我理解进程是顺序执行的程序的一个实例,并且它可以由一个或多个线程组成。在单核CPU中,一次只能执行一个线程,而在多核CP
我的问题是在上一次集成测试后服务器进程没有关闭。 在integration.rs中,我有: lazy_static! { static ref SERVER: Arc> = {
我正在使用 Scala scala.sys.process图书馆。 我知道我可以用 ! 捕获退出代码和输出 !!但是如果我想同时捕获两者呢? 我看过这个答案 https://stackoverflow
我正在开发一个C++类(MyClass.cpp),将其编译为动态共享库(MyClass.so)。 同一台Linux计算机上运行的两个不同应用程序将使用此共享库。 它们是两个不同的应用程序。它不是多线程
我在我的 C 程序中使用 recvfrom() 从多个客户端接收 UDP 数据包,这些客户端可以使用自定义用户名登录。一旦他们登录,我希望他们的用户名与唯一的客户端进程配对,这样服务器就可以通过数据包
如何更改程序,以便函数 function_delayed_1 和 function_delayed_2 仅同时执行一次: int main(int argc, char *argv[]) {
考虑这两个程序: //in #define MAX 50 int main(int argc, char* argv[]) { int *count; int fd=shm
请告诉我如何一次打开三个终端,这样我的项目就可以轻松执行,而不必打开三个终端三次然后运行三个exe文件。请问我们如何通过脚本来做到这一点,即打开三个终端并执行三个 exe 文件。 最佳答案 在后台运行
我编写了一个监控服务来跟踪一组进程,并在服务行为异常、内存使用率高、超出 CPU 运行时间等时发出通知。 这在我的本地计算机上运行良好,但我需要它指向远程机器并获取这些机器上的进程信息。 我的方法,在
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 8年前关闭。 Improve this qu
我有一个允许用户上传文件的应用程序。上传完成后,必须在服务器上完成许多处理步骤(解压、存储、验证等...),因此稍后会在一切完成后通过电子邮件通知用户。 我见过很多示例,其中 System.Compo
这个问题对很多人来说可能听起来很愚蠢,但我想对这个话题有一个清晰的理解。例如:当我们在 linux(ubuntu, x86) 上构建一个 C 程序时,它会在成功编译和链接过程后生成 a.out。 a.
ps -eaf | grep java 命令在这里不是识别进程是否是 java 进程的解决方案,因为执行此命令后我的许多 java 进程未在输出中列出。 最佳答案 简答(希望有人写一个更全面的): 获
我有几个与内核态和用户态的 Windows 进程相关的问题。 如果我有一个 hello world 应用程序和一个暴露新系统调用 foo() 的 hello world 驱动程序,我很好奇在内核模式下
我找不到很多关于 Windows 中不受信任的完整性级别的信息,对此有一些疑问: 是否有不受信任的完整性级别进程可以创建命名对象的地方? (互斥锁、事件等) 不受信任的完整性级别进程是否应该能够打开一
我是一名优秀的程序员,十分优秀!