mirror of
https://github.com/corda/corda.git
synced 2025-06-14 13:18:18 +00:00
Implemented native Process.exitValue and Process.waitFor on windows
This commit is contained in:
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include "windows.h"
|
# include "windows.h"
|
||||||
|
# include "winbase.h"
|
||||||
# include "io.h"
|
# include "io.h"
|
||||||
# include "tchar.h"
|
# include "tchar.h"
|
||||||
# define SO_PREFIX ""
|
# define SO_PREFIX ""
|
||||||
@ -28,6 +29,25 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
char* getErrorStr(DWORD err){
|
||||||
|
// The poor man's error string, just print the error code
|
||||||
|
char * errStr = (char*) malloc(9 * sizeof(char));
|
||||||
|
snprintf(errStr, 9, "%d", (int) err);
|
||||||
|
return errStr;
|
||||||
|
|
||||||
|
// The better way to do this, if I could figure out how to convert LPTSTR to char*
|
||||||
|
//char* errStr;
|
||||||
|
//LPTSTR s;
|
||||||
|
//if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
// FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, &s, 0, NULL) == 0)
|
||||||
|
//{
|
||||||
|
// errStr.Format("Unknown error occurred (%08x)", err);
|
||||||
|
//} else {
|
||||||
|
// errStr = s;
|
||||||
|
//}
|
||||||
|
//return errStr;
|
||||||
|
}
|
||||||
|
|
||||||
void makePipe(JNIEnv* e, HANDLE p[2])
|
void makePipe(JNIEnv* e, HANDLE p[2])
|
||||||
{
|
{
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
@ -37,9 +57,7 @@ namespace {
|
|||||||
|
|
||||||
BOOL success = CreatePipe(p, p + 1, &sa, 0);
|
BOOL success = CreatePipe(p, p + 1, &sa, 0);
|
||||||
if (not success) {
|
if (not success) {
|
||||||
char* errStr = (char*) malloc(9 * sizeof(char));
|
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
||||||
snprintf(errStr, 9, "%d", (int) GetLastError());
|
|
||||||
throwNew(e, "java/io/IOException", errStr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +73,10 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
extern "C" JNIEXPORT void JNICALL
|
||||||
jobjectArray command, jintArray process)
|
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
||||||
|
jobjectArray command, jlongArray process)
|
||||||
{
|
{
|
||||||
//const char* line = e->GetStringUTFChars(command, 0);
|
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (int i = 0; i < e->GetArrayLength(command); ++i){
|
for (int i = 0; i < e->GetArrayLength(command); ++i){
|
||||||
@ -73,31 +91,30 @@ extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
jstring element = (jstring) e->GetObjectArrayElement(command, i);
|
jstring element = (jstring) e->GetObjectArrayElement(command, i);
|
||||||
const char* s = e->GetStringUTFChars(element, 0);
|
const char* s = e->GetStringUTFChars(element, 0);
|
||||||
_tcscpy(linep, s);
|
_tcscpy(linep, s);
|
||||||
|
e->ReleaseStringUTFChars(element, s);
|
||||||
linep += e->GetStringUTFLength(element);
|
linep += e->GetStringUTFLength(element);
|
||||||
}
|
}
|
||||||
*(linep++) = _T('\0');
|
*(linep++) = _T('\0');
|
||||||
|
|
||||||
printf("command: %s\n", _T(line));
|
|
||||||
|
|
||||||
HANDLE in[] = { 0, 0 };
|
HANDLE in[] = { 0, 0 };
|
||||||
HANDLE out[] = { 0, 0 };
|
HANDLE out[] = { 0, 0 };
|
||||||
HANDLE err[] = { 0, 0 };
|
HANDLE err[] = { 0, 0 };
|
||||||
|
|
||||||
makePipe(e, in);
|
makePipe(e, in);
|
||||||
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
|
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
|
||||||
jint inDescriptor = descriptor(e, in[0]);
|
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
|
||||||
if(e->ExceptionOccurred()) return;
|
if(e->ExceptionOccurred()) return;
|
||||||
e->SetIntArrayRegion(process, 1, 1, &inDescriptor);
|
e->SetLongArrayRegion(process, 1, 1, &inDescriptor);
|
||||||
makePipe(e, out);
|
makePipe(e, out);
|
||||||
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
||||||
jint outDescriptor = descriptor(e, out[1]);
|
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
|
||||||
if(e->ExceptionOccurred()) return;
|
if(e->ExceptionOccurred()) return;
|
||||||
e->SetIntArrayRegion(process, 2, 1, &outDescriptor);
|
e->SetLongArrayRegion(process, 2, 1, &outDescriptor);
|
||||||
makePipe(e, err);
|
makePipe(e, err);
|
||||||
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
||||||
jint errDescriptor = descriptor(e, err[0]);
|
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
|
||||||
if(e->ExceptionOccurred()) return;
|
if(e->ExceptionOccurred()) return;
|
||||||
e->SetIntArrayRegion(process, 3, 1, &errDescriptor);
|
e->SetLongArrayRegion(process, 3, 1, &errDescriptor);
|
||||||
|
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
ZeroMemory(&pi, sizeof(pi));
|
||||||
@ -113,20 +130,41 @@ extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|||||||
BOOL success = CreateProcess(0, (LPSTR) line, 0, 0, 1,
|
BOOL success = CreateProcess(0, (LPSTR) line, 0, 0, 1,
|
||||||
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
||||||
0, 0, &si, &pi);
|
0, 0, &si, &pi);
|
||||||
|
|
||||||
//e->ReleaseStringUTFChars(command, line);
|
|
||||||
|
|
||||||
if (not success) {
|
if (not success) {
|
||||||
char* errStr = (char*) malloc(9 * sizeof(char));
|
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
||||||
snprintf(errStr, 9, "%d", (int) GetLastError());
|
|
||||||
throwNew(e, "java/io/IOException", errStr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jint pid = reinterpret_cast<jlong>(pi.hProcess);
|
jlong pid = reinterpret_cast<jlong>(pi.hProcess);
|
||||||
e->SetIntArrayRegion(process, 0, 1, &pid);
|
e->SetLongArrayRegion(process, 0, 1, &pid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
|
Java_java_lang_Runtime_exitValue(JNIEnv* e, jclass, jlong pid)
|
||||||
|
{
|
||||||
|
DWORD exitCode;
|
||||||
|
BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode);
|
||||||
|
if(not success){
|
||||||
|
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
||||||
|
} else if(exitCode == STILL_ACTIVE){
|
||||||
|
throwNew(e, "java/lang/IllegalThreadStateException", "Process is still active");
|
||||||
|
}
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
|
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid)
|
||||||
|
{
|
||||||
|
DWORD exitCode;
|
||||||
|
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
||||||
|
BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode);
|
||||||
|
if(not success){
|
||||||
|
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
||||||
|
}
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
|
@ -34,28 +34,28 @@ public class Runtime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Process exec(String command) throws IOException {
|
public Process exec(String command) throws IOException {
|
||||||
int[] process = new int[4];
|
long[] process = new long[4];
|
||||||
StringTokenizer t = new StringTokenizer(command);
|
StringTokenizer t = new StringTokenizer(command);
|
||||||
String[] cmd = new String[t.countTokens()];
|
String[] cmd = new String[t.countTokens()];
|
||||||
for (int i = 0; i < cmd.length; i++)
|
for (int i = 0; i < cmd.length; i++)
|
||||||
cmd[i] = t.nextToken();
|
cmd[i] = t.nextToken();
|
||||||
exec(cmd, process);
|
exec(cmd, process);
|
||||||
return new MyProcess(process[0], process[1], process[2], process[3]);
|
return new MyProcess(process[0], (int) process[1], (int) process[2], (int) process[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Process exec(String[] command) {
|
public Process exec(String[] command) {
|
||||||
int[] process = new int[4];
|
long[] process = new long[4];
|
||||||
exec(command, process);
|
exec(command, process);
|
||||||
return new MyProcess(process[0], process[1], process[2], process[3]);
|
return new MyProcess(process[0], (int) process[1], (int) process[2], (int) process[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//private static native void exec(String command, int[] process);
|
//private static native void exec(String command, int[] process);
|
||||||
|
|
||||||
private static native void exec(String[] command, int[] process);
|
private static native void exec(String[] command, long[] process);
|
||||||
|
|
||||||
private static native int exitValue(int pid);
|
private static native int exitValue(long pid);
|
||||||
|
|
||||||
private static native int waitFor(int pid);
|
private static native int waitFor(long pid);
|
||||||
|
|
||||||
private static native void load(String name, boolean mapName);
|
private static native void load(String name, boolean mapName);
|
||||||
|
|
||||||
@ -68,13 +68,13 @@ public class Runtime {
|
|||||||
public native long totalMemory();
|
public native long totalMemory();
|
||||||
|
|
||||||
private static class MyProcess extends Process {
|
private static class MyProcess extends Process {
|
||||||
private int pid;
|
private long pid;
|
||||||
private final int in;
|
private final int in;
|
||||||
private final int out;
|
private final int out;
|
||||||
private final int err;
|
private final int err;
|
||||||
private int exitCode;
|
private int exitCode;
|
||||||
|
|
||||||
public MyProcess(int pid, int in, int out, int err) {
|
public MyProcess(long pid, int in, int out, int err) {
|
||||||
this.pid = pid;
|
this.pid = pid;
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.out = out;
|
this.out = out;
|
||||||
|
@ -1,13 +1,40 @@
|
|||||||
import java.lang.Runtime;
|
import java.lang.Runtime;
|
||||||
|
import java.lang.Process;
|
||||||
|
|
||||||
public class RuntimeExec {
|
public class RuntimeExec {
|
||||||
public static void main(String[] args) throws java.io.IOException {
|
public static void main(String[] args) throws java.io.IOException, java.lang.InterruptedException {
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
|
||||||
System.out.println("Executing internet explorer");
|
System.out.println("Executing internet explorer");
|
||||||
Runtime.getRuntime().exec("\"c:\\program files\\internet explorer\\iexplore.exe\" http://www.google.com");
|
String ieStr = "\"c:\\program files\\internet explorer\\iexplore.exe\" http://www.google.com";
|
||||||
|
Process ie = runtime.exec(ieStr);
|
||||||
|
|
||||||
System.out.println("Executing firefox");
|
System.out.println("Executing firefox");
|
||||||
String[] firefox = new String[2];
|
String[] firefox = new String[2];
|
||||||
firefox[0] = "c:\\program files\\mozilla firefox\\firefox.exe";
|
firefox[0] = "c:\\program files\\mozilla firefox\\firefox.exe";
|
||||||
firefox[1] = "http://www.google.com";
|
firefox[1] = "http://www.google.com";
|
||||||
Runtime.getRuntime().exec(firefox);
|
Process ff = runtime.exec(firefox);
|
||||||
|
|
||||||
|
boolean ffSuccess = false;
|
||||||
|
boolean ieSuccess = false;
|
||||||
|
while(!(ieSuccess && ffSuccess)){
|
||||||
|
if(!ffSuccess){
|
||||||
|
try{
|
||||||
|
System.out.println("Firefox exit value: " + ff.exitValue());
|
||||||
|
ffSuccess = true;
|
||||||
|
} catch(IllegalThreadStateException e) {}
|
||||||
|
}
|
||||||
|
if(!ieSuccess){
|
||||||
|
try{
|
||||||
|
System.out.println("Internet Explorer exit value: " + ie.exitValue());
|
||||||
|
ieSuccess = true;
|
||||||
|
} catch(IllegalThreadStateException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Executing and waiting for charmap");
|
||||||
|
String charmapStr = "c:\\windows\\system32\\charmap.exe";
|
||||||
|
Process cm = runtime.exec(charmapStr);
|
||||||
|
System.out.println("Charmap exit value: " + cm.waitFor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user