重定向JNA中的输出并生成子进程静默(没有弹出命令窗口)

时间:2013-09-30 12:35:51

标签: java jna

我已经编写了一个java程序来spwan child java进程。当它生成子进程时,它会打开一个命令提示符窗口,输出将重定向到命令提示符。你能告诉我如何在没有额外命令窗口的情况下生成/创建子进程,并将此进程的输出重定向到文件。我使用的是Java 6和JNA 3.5.2

以下是创建流程的命令

cmd = "c:\\jdk1.6.0_30\\bin\\java.exe -Xmx256m -Xss1024k  -cp <classpath jars>; 
-Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB com.xyz.test.MainProgram <program arguments>

使用弹出命令提示符工作代码

private boolean createChildProcess(ProcessData processData,String cmd,String appName){ HANDLEByReference childStdInRead = new HANDLEByReference(); HANDLEByReference childStdOutWrite = new HANDLEByReference();

    int STARTF_USESTDHANDLES = 0x00000100;

    WinBase.PROCESS_INFORMATION.ByReference processInformation = new WinBase.PROCESS_INFORMATION.ByReference();
    STARTUPINFO startupInfo = new STARTUPINFO();

    // Create the child process. 
    if (!Kernel32.INSTANCE.CreateProcess(
            null, 
            cmd, 
            null, 
            null, 
            true, 
            new DWORD(0x00000020), //new DWORD(0x00000001)
            null, 
            null, 
            startupInfo, 
            processInformation)){
        System.err.println(Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE.GetLastError()));
        return false;

    }else {
        System.out.println("Created Process :"+processInformation.dwProcessId.intValue());
        processData.setProcessId(processInformation.dwProcessId.intValue());
        //processData.sethProcess(processInformation.hProcess);
        //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);
        return true;
    }
} </pre>

int STARTF_USESTDHANDLES = 0x00000100; WinBase.PROCESS_INFORMATION.ByReference processInformation = new WinBase.PROCESS_INFORMATION.ByReference(); STARTUPINFO startupInfo = new STARTUPINFO(); // Create the child process. if (!Kernel32.INSTANCE.CreateProcess( null, cmd, null, null, true, new DWORD(0x00000020), //new DWORD(0x00000001) null, null, startupInfo, processInformation)){ System.err.println(Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE.GetLastError())); return false; }else { System.out.println("Created Process :"+processInformation.dwProcessId.intValue()); processData.setProcessId(processInformation.dwProcessId.intValue()); //processData.sethProcess(processInformation.hProcess); //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); return true; } } </pre>

我尝试了以下代码,但它无效

private boolean createChildProcess(ProcessData processData,String cmd,String appName){

    //Tried with Output to file
    HANDLEByReference childStdInRead = new HANDLEByReference();
    HANDLEByReference childStdInWrite = new HANDLEByReference();
    HANDLEByReference childStdOutRead = new HANDLEByReference();
    HANDLEByReference childStdOutWrite = new HANDLEByReference();

    int STARTF_USESTDHANDLES = 0x00000100;

    WinBase.PROCESS_INFORMATION.ByReference processInformation = new WinBase.PROCESS_INFORMATION.ByReference();
    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;

    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 the child process. 
    if (!Kernel32.INSTANCE.CreateProcess(
            null, 
            cmd, 
            null, 
            null, 
            true, 
            new DWORD(0x00000020), //new DWORD(0x00000001)
            null, 
            null, 
            startupInfo, 
            processInformation)){
        System.err.println(Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE.GetLastError()));
        return false;

    }else {
        System.out.println("Created Process :"+processInformation.dwProcessId.intValue());
        processData.setProcessId(processInformation.dwProcessId.intValue());
        //processData.sethProcess(processInformation.hProcess);
        //com.sun.jna.platform.win32.Kernel32.INSTANCE.WaitForSingleObject(processInformation.hProcess, 0xFFFFFFFF);

        HANDLE inputFile = com.sun.jna.platform.win32.Kernel32.INSTANCE.CreateFile(
                "c:\\"+processInformation.dwProcessId.intValue()+".txt", 
                GENERIC_READ, 
                0, 
                null, 
                OPEN_EXISTING, 
                FILE_ATTRIBUTE_READONLY, 
                null);
        //ReadFromPipe(childStdOutRead,childStdOutWrite);
        com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(processInformation.hProcess);
        com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(processInformation.hThread);
        return true;
    }
}

2 个答案:

答案 0 :(得分:1)

在Windows上,调用javaw.exe而不是java.exe。这将避免“控制台”窗口。

至于重定向到文件,最简单的方法可能是将参数传递给Java子进程以指示所需的文件,然后重定向System.outSystem.err以写入该文件

System.outSystem.errPrintStream,因此在启动时您只需创建自己的(映射到FileOutputStream)即可重定向所有控制台输出。有关详细信息,请参阅this question on SO

答案 1 :(得分:0)

我可以在create process选项中使用以下修改来创建静默进程(不使用控制台)。 但仍需要您帮助重定向流程输出

Kernel32.INSTANCE.CreateProcess(
            null, 
            cmd, 
            null, 
            null, 
            true, 
            new DWORD(WinBase.CREATE_NO_WINDOW),
            null, 
            null, 
            startupInfo, 
            processInformation)