Redirecting output in JNA and spwaning childprocess Silently (Without Popup command window)

StackOverflow https://stackoverflow.com/questions/19094450

  •  29-06-2022
  •  | 
  •  

Question

I have written a java program to spwan child java process. When it spawns child process it opens up a command prompt window and output is redirect to the command prompt. Can you tell me how to spawn/create child process without extra command window and redirect the output of this process to a file. I am using Java 6 and JNA 3.5.2

Below is the command to create process

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>

Working code with popup command prompt

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>

I tried following code but it didn't work

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;
    }
}

Was it helpful?

Solution 2

I am able to create silent process (without console) using following modification in create process option. But still need your help for redirecting process output

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

OTHER TIPS

On windows, invoke javaw.exe rather than java.exe. That will avoid the "console" window.

As for redirecting to a file, the easiest way would likely be to pass in a parameter to your Java subprocess to indicate the desired file, and then redirect System.out and System.err to write to that file.

System.out and System.err are PrintStreams, so on startup you can simply create your own (mapped to a FileOutputStream) to redirect all console output. See this question on SO for details.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top