Allocate Console in java applet? - java

I have a dll written in C++ which I am injecting to java.exe
I'd like to spawn/allocate a console that I can watch.
I have used this code before I know it works when injecting the dll into win32 applications. But why not work when loaded by java.exe or injected into java.exe?
Here is the console spawning/redirection of std in/out.
void InitDebugConsole() {
int hCrtIn, hCrtOut;
FILE *conIn, *conOut;
AllocConsole();
hCrtIn = _open_osfhandle ((int) GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
hCrtOut = _open_osfhandle ((int) GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
conIn = _fdopen( hCrtIn, "r" );
conOut = _fdopen( hCrtOut, "w" );
*stdin = *conIn;
*stdout = *conOut;
}
Pretty much my problem is java.exe is somehow blocking the allocation of console.

Related

Execute command from Java code deployed on Apache Tomcat

I was trying to convert a DOCX file to PDF file, found this vb script code which perfectly converts DOCX to PDF file, it uses .bat file for file generation. The code can be executed through java.
I am facing a strange problem, when I execute the code on my local machine, the file is generated, but when I deployed the app on Server , the code executes with no errors but the file is not generated.
Do we need any permission to execute commands through java?
Following is the details:
Server Operating system : Windows Server 2012 R2 Standard
Application server :Apache Tomcat 7.0.75
Code:
1)Java
public static void generatePDF() {
try {
File file = new File("C:\\Docx_To_Pdf_Converter\\errorLog.txt");
PrintStream printStreamToFile = new PrintStream(file);
System.setOut(printStreamToFile);
String docToPdf = "C:\\Docx_To_Pdf_Converter\\doc2pdf.bat";
File docPath = new File("C:\\Docx_To_Pdf_Converter\\Letter1.docx");
File pdfPath = new File("C:\\Docx_To_Pdf_Converter\\LetterPDF.pdf");
String command = String.format("%s %s %s", docToPdf, docPath, pdfPath);
Process process = Runtime.getRuntime().exec(command);
// The next line is optional and will force the current Java
//thread to block until the script has finished its execution.
process.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and the .bat file code:
#Echo off
pushd %~dp0
cscript C:\Docx_To_Pdf_Converter\doc2pdf.vbs %1 %2
vbscript code which actually converts the docx to pdf
Const wdFormatPDF = 17 ' PDF format.
Const wdFormatXPS = 18 ' XPS format.
Const WdDoNotSaveChanges = 0
Dim arguments
Set arguments = WScript.Arguments
Function CheckUserArguments()
If arguments.Unnamed.Count < 1 Or arguments.Unnamed.Count > 2 Then
WScript.Echo "Use:"
WScript.Echo "<script> input.doc"
WScript.Echo "<script> input.doc output.pdf"
WScript.Quit 1
End If
End Function
// Transforms a doc to a pdf
Function DocToPdf( docInputFile, pdfOutputFile )
Dim fileSystemObject
Dim wordApplication
Dim wordDocument
Dim wordDocuments
Dim baseFolder
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
Set wordApplication = CreateObject("Word.Application")
Set wordDocuments = wordApplication.Documents
docInputFile = fileSystemObject.GetAbsolutePathName(docInputFile)
baseFolder = fileSystemObject.GetParentFolderName(docInputFile)
If Len(pdfOutputFile) = 0 Then
pdfOutputFile = fileSystemObject.GetBaseName(docInputFile) + ".pdf"
End If
If Len(fileSystemObject.GetParentFolderName(pdfOutputFile)) = 0 Then
pdfOutputFile = baseFolder + "\" + pdfOutputFile
End If
//' Disable any potential macros of the word document.
wordApplication.WordBasic.DisableAutoMacros
// 'from below line the code does not executes
Set wordDocument = wordDocuments.Open(docInputFile)
wordDocument.SaveAs pdfOutputFile, wdFormatPDF
wordDocument.Close WdDoNotSaveChanges
wordApplication.Quit WdDoNotSaveChanges
Set wordApplication = Nothing
Set fileSystemObject = Nothing
End Function
// ' Execute script
Call CheckUserArguments()
If arguments.Unnamed.Count = 2 Then
Call DocToPdf( arguments.Unnamed.Item(0), arguments.Unnamed.Item(1) )
Else
Call DocToPdf( arguments.Unnamed.Item(0), "" )
End If
Set arguments = Nothing
It is not possible to give you a 100% guaranteed answer as we don't have access to your deployment server, but here's what I think is happening there.
If the .bat file were missing or not executable for some reason, then you would get an IOException in your Java code. Since you didn't get an exception, clearly the .bat file was found and executed.
However, whatever is within the .bat file is not being executed as you expect. Either cscript.exe is missing, or the .vbs file is missing. The way your code is written, you would not be aware of this. All you would see is a non-zero status return from the waitfor() method, and you don't bother to check that. Therefore you have no knowledge of what actually happened.
At the very minimum you should change the waitfor() method invocation to:
int rc = process.waitFor();
System.out.printf("Process returned %d\n", rc);
This will tell you the return status from the attempt to execute the .bat file. If it's not zero, then you have a problem, and I'm 99.999% sure you will find this to be non-zero. To troubleshoot this you will need to capture the output from the command. The following is a highly simplified (as in no error handling; that's up to you) example:
Process proc = Runtime.getRuntime().exec(command);
BufferedReader procOutput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while((line = procOutput.readLine()) != null)
{
System.out.println(line);
// Or whatever you need to do to in your environment, such
// as log the output or examine it to ensure the script did
// what you want
}
int rc = proc.waitFor();
System.out.printf("Process returned %d\n", rc);
NOTE The above is not production-level code, it is only an example of how to use the API. This works ONLY if the external command requires no redirected input; if it does require input then you need to handle input and output in separate threads to prevent deadlocks.
Also, you should consider using ProcessBuilder as it is much more flexible. For example, it allows you to redirect the process' output to append to a log file, which you should probably implement.

Java - How can i request Administrator privileges during runtime? [duplicate]

A nasty problem popped out with my software. I am making a program that interacts with another existing software (a game). User has reported that he runs the game with administrator privileges and under that circumstances, my program stops working for him.
Short investigation revealed that some people really need to run the game under administrator account and some don't. It would be great if my program would be able to detect this and warn user if the game is running under administrator account:
If the user clicks "Elevate", I'd like to ask windows to elevate the java.exe running my jar file and invoke the typical UAC dialog.
Obviously, this time the question would not be about java updater but JRE
My question is: Is this possible? Can windows elevate my java.exe instance's privilege? Does java have a way to do it? Or can I use command line command?
I want to avoid restarting the program (though it wouldn't probably be such a big deal).
Edit:
If you look in the comments, you'll see that there's no avoiding the restart of an application - process can only start elevated, not become elevated. This kinda shifts the question, unfortunately. Basically, it now sounds more like: "How to restart my application with admin rights?". Unless, of course, there's a trick like two java.exe sharing one jar...
If still of interest: In Windows 7 my JavaElevator works. It elevates a running Java process when used in the main method of the Java application. Simply add -elevate as last program parameter and use the elevator in the main method.
The elevator class:
package test;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.ShellAPI;
import com.sun.jna.platform.win32.WinDef;
/**
* Elevates a Java process to administrator rights if requested.
*/
public class JavaElevator {
/** The program argument indicating the need of being elevated */
private static final String ELEVATE_ARG = "-elevate";
/**
* If requested, elevates the Java process started with the given arguments to administrator level.
*
* #param args The Java program arguments
* #return The cleaned program arguments
*/
public static String[] elevate(String[] args) {
String[] result = args;
// Check for elevation marker.
boolean elevate = false;
if (args.length > 0) {
elevate = args[args.length - 1].equals(ELEVATE_ARG);
}
if (elevate) {
// Get the command and remove the elevation marker.
String command = System.getProperty("sun.java.command");
command = command.replace(ELEVATE_ARG, "");
// Get class path and default java home.
String classPath = System.getProperty("java.class.path");
String javaHome = System.getProperty("java.home");
String vm = javaHome + "\\bin\\java.exe";
// Check for alternate VM for elevation. Full path to the VM may be passed with: -Delevation.vm=...
if (System.getProperties().contains("elevation.vm")) {
vm = System.getProperty("elevation.vm");
}
String parameters = "-cp " + classPath;
parameters += " " + command;
Shell32.INSTANCE.ShellExecute(null, "runas", vm, parameters, null, 0);
int lastError = Kernel32.INSTANCE.GetLastError();
if (lastError != 0) {
String errorMessage = Kernel32Util.formatMessageFromLastErrorCode(lastError);
errorMessage += "\n vm: " + vm;
errorMessage += "\n parameters: " + parameters;
throw new IllegalStateException("Error performing elevation: " + lastError + ": " + errorMessage);
}
System.exit(0);
}
return result;
}
}
Usage in the main method of the Java application:
public static void main(String[] args) {
String[] args1 = JavaElevator.elevate(args);
if (args1.length > 0) {
// Continue as intended.
...
I know, this is a very basic implementation - sufficient for one of my daily hiccups: Starting an elevated process from Eclipse. But maybe it points someone in some dicrection...
As has been pointed in comments, sadly the Java (or any other process) cannot be elevated while running. While in the case of JWM, it could be theoretically possible to move whole program context from normal user java.exe to elevated one, I don't think it's possible. I hope some day someone will come and tell me I'm wrong.
Surprisingly, even with restart in place, this was a tricky task that took me a while to figure out.
The non java part
First, how do we exactly run a program elevated from command line? There's an answer and you can see it's not simple. But we can break it to this VBS script:
Set UAC = CreateObject("Shell.Application")
UAC.ShellExecute "program name", "command line parameters", "working directory", "runas", 1
Soon, it also turns out that we won't have any success running java.exe from VBS script. In the end, I decided to run a helper batch file. Finally, here (answer to question in the last link) we have a complete set of two scripts which really run the given .jar file elevated. Here's improved version that allows quick testing by drag'n'dropping the Jar file on it:
' Require first command line parameter
if WScript.Arguments.Count = 0 then
MsgBox("Jar file name required.")
WScript.Quit 1
end if
' Get the script location, the directorry where it's running
Set objShell = CreateObject("Wscript.Shell")
strPath = Wscript.ScriptFullName
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile(strPath)
strFolder = objFSO.GetParentFolderName(objFile)
'MsgBox(strFolder)
' Create the object that serves as runnable something
Set UAC = CreateObject("Shell.Application")
' Args:
' path to executable to run
' command line parameters - first parameter of this file, which is the jar file name
' working directory (this doesn't work but I use it nevertheless)
' runas command which invokes elevation
' 0 means do not show the window. Normally, you show the window, but not this console window
' which just blinks and disappears anyway
UAC.ShellExecute "run-normally.bat", WScript.Arguments(0), strFolder, "runas", 0
WScript.Quit 0
The Java part
Java part is more straightforward. What we need to do is to open new process and execute the prepared scripts in it.
/**
* Start this very jar file elevated on Windows. It is strongly recommended to close any existing IO
* before calling this method and avoid writing anything more to files. The new instance of this same
* program will be started and simultaneous write/write or read/write would cause errors.
* #throws FileNotFoundException if the helper vbs script was not found
* #throws IOException if there was another failure inboking VBS script
*/
public void StartWithAdminRights() throws FileNotFoundException, IOException {
//The path to the helper script. This scripts takes 1 argument which is a Jar file full path
File runAsAdmin = new File("run-as-admin.vbs");;
//Our
String jarPath;
//System.out.println("Current relative path is: " + s);
try {
jarPath = "\""+new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath()+"\"";
} catch (URISyntaxException ex) {
throw new FileNotFoundException("Could not fetch the path to the current jar file. Got this URISyntax exception:"+ex);
}
//If the jar path was created but doesn't contain .jar, we're (most likely) not running from jar
//typically this happens when running the program from IDE
//These 4 lines just serve as a fallback in testing, should be deleted in production
//code and replaced with another FileNotFoundException
if(!jarPath.contains(".jar")) {
Path currentRelativePath = Paths.get("");
jarPath = "\""+currentRelativePath.toAbsolutePath().toString()+"\\AutoClient.jar\"";
}
//Now we check if the path to vbs script exists, if it does we execute it
if(runAsAdmin.exists()) {
String command = "cscript \""+runAsAdmin.getAbsolutePath()+"\" "+jarPath;
System.out.println("Executing '"+command+"'");
//Note that .exec is asynchronous
//After it starts, you must terminate your program ASAP, or you'll have 2 instances running
Runtime.getRuntime().exec(command);
}
else
throw new FileNotFoundException("The VBSScript used for elevation not found at "+runAsAdmin.getAbsolutePath());
}
This is my version. It creates a VBScript script, then executes it. This only works if the program that is being run is in a jar file, so you will have to run your IDE as administrator to actually test your program.
public static void relaunchAsAdmin() throws IOException {
relaunchAsAdmin(ThisClass.class); //Change ThisClass to the class that this method is in
}
public static void relaunchAsAdmin(Class<?> clazz) throws IOException {
if(isCurrentProcessElevated()) {
return;
}
final String dir = System.getProperty("java.io.tmpdir");
final File script = new File(dir, "relaunchAsAdmin" + System.nanoTime() +
".vbs");
try {
script.createNewFile();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(script));
osw.append("Set s=CreateObject(\"Shell.Application\")" + ln + "s.ShellExecute \"" +
System.getProperty("java.home") + "\\bin\\java.exe" + "\",\"-jar \"\"" +
new File(clazz.getProtectionDomain().getCodeSource(
).getLocation().toURI()).getAbsolutePath() + "\"\"\",,\"runas\",0" +
ln + "x=createObject(\"scripting.fileSystemObject\").deleteFile(" +
"WScript.scriptfullname)");
osw.close();
if(System.getenv("processor_architecture").equals("x86")) {
Runtime.getRuntime().exec("C:\\Windows\\System32\\wscript.exe \"" +
script.getAbsolutePath() + "\"");
} else {
Runtime.getRuntime().exec("C:\\Windows\\SysWoW64\\wscript.exe \"" +
script.getAbsolutePath() + "\"");
}
} catch(URISyntaxException e) {
e.printStackTrace();
}
Runtime.getRuntime().exit(0);
}
Note that it is a bit messy. I have been using this method before, so it has been line wrapped to 100 characters (except the comment I wrote for this answer). The
isCurrentProcessElevated()
method will have to be implemented in one way or another. You could try using JNI, or you could use a pure Java method, such as writing in the Program Files or System32 directory and seeing if it failed.
Obviously, this solution will only work on Windows. I never needed to elevate on Linux or Mac systems (mainly because I don't have any Mac systems, and I don't use Linux - I just play with it).

Pinning .jar files to the taskbar in windows 7

My question is an extension on another question already answered, https://superuser.com/questions/257467/windows-7-how-to-pin-a-jar-to-the-taskbar
Is there a way to pin a jar to the taskbar, and have the window generated by the jar register as a different process, thus creating a different icon in the task bar? because as it stands, using any of the methods listed in the answer to the above question, you end up with a shortcut that can be pinned. but it is just a shortcut and only that, not the program itself. Im willing to try anything at this point as it is beginning to be very bothersome. not only does it look unprofessional, it uses up unnecessary screen real estate. As I know someone is going to ask what else I've tried, here's a bit of code i tried to run in c# to launch the jar, but of course, it does the same thing, registering the new process as a new process. (should have thought that one through.)
string strCmdText;
strCmdText = "-jar ImgurDownloader.jar";
Process process = new Process();
process.StartInfo.Arguments = strCmdText;
process.StartInfo.FileName = "javaw";
process.StartInfo.UseShellExecute = false;
process.Start();
so then I tried this:
string strCmdText;
strCmdText = "-jar ImgurDownloader.jar";
Process process = Process.GetCurrentProcess();
process.StartInfo.Arguments = strCmdText;
process.StartInfo.FileName = "javaw";
process.StartInfo.UseShellExecute = false;
process.Start();
and yet still, even if i try and replace the current process, it comes across as a new process, and thus a second icon in the taskbar. Please excuse my possibly short tone, the frustration is starting to kick in after a couple weeks.
Edit: have also tried setting the UAMID (User Application Model ID) using the JNA library to access shel32.dll's functions. The following is the code in the jar
public static void setCurrentProcessExplicitAppUserModelID(final String appID) {
if (SetCurrentProcessExplicitAppUserModelID(new WString(appID)).longValue() != 0)
throw new RuntimeException("unable to set current process explicit AppUserModelID to: " + appID);
}
public static String getCurrentProcessExplicitAppUserModelID() {
final PointerByReference r = new PointerByReference();
if (GetCurrentProcessExplicitAppUserModelID(r).longValue() == 0) {
final Pointer p = r.getValue();
return p.getString(0, true); // here we leak native memory by
// lazyness
}
return "N/A";
}
private static native NativeLong GetCurrentProcessExplicitAppUserModelID(PointerByReference appID);
private static native NativeLong SetCurrentProcessExplicitAppUserModelID(WString appID);
static {
Native.register("shell32");
}
then just call the set method. Tested with the get method, however,
NOTE: getCurrentProcessExplicitAppUserModelID is a lazy method and breaks things later on if used.
then in the C# Wrapper,
[DllImport("shell32.dll")]
public static extern int SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
static void Main()
{
int der = SetCurrentProcessExplicitAppUserModelID("MAndWorks.ImgurDownloader.ImgurDownloader.2.0.0.0");
string strCmdText;
Console.WriteLine(der);
strCmdText = "-jar ImgurDownloader.jar";
Process process = new Process();
process.StartInfo.Arguments = strCmdText;
process.StartInfo.FileName = "javaw";
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
Console.WriteLine("AWFURA");
}

Detecting 32/64 -bit Java from within C on windows

I would like to find out if the Java runtime installed on a user's machine supports 32 and 64-bit, and I would like to do this from within C. I had thought that something like the following would do the trick:
Detect 64-bit java:
int f=0
char *path = (char*) malloc(32768);
char out[1035];
FILE *fp;
if(f) fprintf(f,"Checking if 64-bit Java is available via the java command\n");
java64ok = 1;
strcpy(path,"java -d64 -version 2>&1");
fp = _popen(path, "r");
if (fp == NULL) {
if(f) fprintf(f,"Failed to run command\n" );
}
if(fgets(out, sizeof(out), fp) != NULL){
if(strncmp(out,"Error",5)==0){
java64ok = 0;
}
while (fgets(out, sizeof(out), fp) != NULL) {}
}
if (feof(fp)){
pclose( fp );
}
else{
if(f) fprintf(f, "Error: Failed to read the pipe to the end.\n");
}
Detect 32-bit Java:
if(f) fprintf(f,"Checking if 32-bit Java is available via the java command\n");
java32ok = 1;
strcpy(path,"java -d32 -version 2>&1");
fp = _popen(path, "r");
if (fp == NULL) {
if(f) fprintf(f,"Failed to run command\n" );
}
if(fgets(out, sizeof(out), fp) != NULL){
if(strncmp(out,"Error",5)==0){
java32ok = 0;
}
while (fgets(out, sizeof(out), fp) != NULL) {}
}
if (feof(fp)){
pclose( fp );
}
else{
if(f) fprintf(f, "Error: Failed to read the pipe to the end.\n");
}
Unfortunately, this appears that if the user is running a 64-bit system only the 32 bit java is detected if the C code is compiled as a 32 bit executable, and only the 64-bit Java is detected if the program is compiled as a 64-bit program.
With reasonable reliability, you can check %SYSTEMROOT%\SysWOW64\java.exe (which is where 32 bit java.exe resides on a 64 bit machine), and %SYSTEMROOT%\System32\java.exe (which is where 64 bit java resides on a 64 bit machine and also where 32 bit java resides on a 32 bit machine.)
Use the Windows API function GetEnvironmentVariable to deduce %SYSTEMROOT%, or, to get started, hardcode to "C:\Windows", escaping \ as necessary.
How you detect the version externally is platform dependant. I sugges you run a short Java program to tell you.
public class Bitness {
public static void main(String... ignored) {
System.out.println(is64Bit() ? "64" : "32");
}
private static boolean is64Bit0() {
String systemProp;
systemProp = System.getProperty("com.ibm.vm.bitmode");
if (systemProp != null) {
return "64".equals(systemProp);
}
systemProp = System.getProperty("sun.arch.data.model");
if (systemProp != null) {
return "64".equals(systemProp);
}
systemProp = System.getProperty("java.vm.version");
return systemProp != null && systemProp.contains("_64");
}
}
This way you can run java -cp {whatever} Bitness and it will tell you.
the suggestion of Bathsheba is quite solid, though depending on how the PATH variable is defined on a system, it might be possible that another java.exe binary is found before %SYSTEMROOT%\, so there is a chance that a different java version is used.
My suggestion would be to first parse PATH environment variable and find the first hit for java. Second step would be to look at the COFF header of the java.exe file.
With the ImageNtHeader function, you can query the NT header and this contains the field FileHeader, which is a IMAGE_FILE_HEADER.
Here's some example on how you would implement this:
https://stackoverflow.com/a/4316804/435583
Hope this helps you out.
Cheers

Execute a Java program from our Java program

I used
Runtime.getRuntime().exec("_____")
but it throws a IOException as below:
java.io.IOException: CreateProcess: c:/ error=5
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.<init>(Win32Process.java:63)
at java.lang.Runtime.execInternal(Native Method
I don't know whether I have the problem with specifying the path or something else. Can anyone please help me with the code.
You're trying to execute "C:/". You'll want to execute something like:
"javaw.exe d:\\somejavaprogram\\program.jar"
Notice the path separators.
I'm assuming this is for an ad-hoc project, rather than something large. However, for best practice running external programs from code:
Don't hardcode the executable location, unless you're certain it will never change
Look up directories like %windir% using System.getenv
Don't assume programs like javaw.exe are in the search path: check them first, or allow the user to specify a location
Make sure you're taking spaces into account: "cmd /c start " + myProg will not work if myProg is "my program.jar".
You can either launch another JVM (as described in detail in other answers).
But that is not a solution i would prefer.
Reasons are:
calling a native program from java is "dirty" (and sometimes crashes your own VM)
you need to know the path to the external JVM (modern JVMs don't set JAVA_HOME anymore)
you have no control on the other program
Main reason to do it anyway is, that the other application has no control over your part of the program either. And more importantly there's no trouble with unresponsive system threads like the AWT-Thread if the other application doesn't know its threading 101.
But! You can achieve more control and similar behaviour by using an elementary plugin technique. I.e. just call "a known interface method" the other application has to implement. (in this case the "main" method).
Only it's not quite as easy as it sounds to pull this off.
you have to dynamically include required jars at runtime (or include them in the classpath for your application)
you have to put the plugin in a sandbox that prevents compromising critical classes to the other application
And this calls for a customized classloader. But be warned - there are some well hidden pitfalls in implementing that. On the other hand it's a great exercise.
So, take your pick: either quick and dirty or hard but rewarding.
java.io.IOException: CreateProcess: c:/ error=5
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.<init>(Win32Process.java:63)
at java.lang.Runtime.execInternal(Native Method)
If I recall correctly, error code 5 means access denied. This could be because your path is incorrect (trying to execute "c:/") or you are bumping against your OS security (in which case, look at the permissions).
If you are having trouble locating the Java executable, you can usually find it using system properties:
public class LaunchJre {
private static boolean isWindows() {
String os = System.getProperty("os.name");
if (os == null) {
throw new IllegalStateException("os.name");
}
os = os.toLowerCase();
return os.startsWith("windows");
}
public static File getJreExecutable() throws FileNotFoundException {
String jreDirectory = System.getProperty("java.home");
if (jreDirectory == null) {
throw new IllegalStateException("java.home");
}
File exe;
if (isWindows()) {
exe = new File(jreDirectory, "bin/java.exe");
} else {
exe = new File(jreDirectory, "bin/java");
}
if (!exe.isFile()) {
throw new FileNotFoundException(exe.toString());
}
return exe;
}
public static int launch(List<String> cmdarray) throws IOException,
InterruptedException {
byte[] buffer = new byte[1024];
ProcessBuilder processBuilder = new ProcessBuilder(cmdarray);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
InputStream in = process.getInputStream();
while (true) {
int r = in.read(buffer);
if (r <= 0) {
break;
}
System.out.write(buffer, 0, r);
}
return process.waitFor();
}
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("c:/");
List<String> cmdarray = new ArrayList<String>();
cmdarray.add(getJreExecutable().toString());
cmdarray.add("-version");
int retValue = launch(cmdarray);
if (retValue != 0) {
System.err.println("Error code " + retValue);
}
System.out.println("OK");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(Tested Windows XP, Sun JRE 1.6; Ubuntu 8.04, OpenJDK JRE 1.6)
This is the equivalent of running:
java -version
You may also want to look at the "java.library.path" system property (and "path.separator") when trying to locate the executable.
How about just calling the main from your java program?
Test.main(null);
This worked fine for me
Is there any reason you can't just call it directly in your Java code?
If there is a reason I've not tried it for executing a Java Program but you could try Jakarta Commons Exec works well for executing most programs.
I had to do this recently.
Here is how I did it, picking up only the relevant parts:
private static final String[] straJavaArgs =
{
"?i/j2re/bin/java",
"-ms64m",
"-mx64m",
"-Djava.ext.dirs=?i/lib;?i/jar/lib;?i/jar"
};
// ...
// AppDesc appToRun;
List<String> params = new ArrayList<String>();
// Java exe and parameters
params.addAll(ExpandStrings(straJavaArgs));
// Common VM arguments
params.addAll(Arrays.asList(AppDesc.GetCommonVMArgs()));
// Specific VM arguments
params.addAll(ExpandStrings(appToRun.GetVMArgs()));
// The program to run
params.add(appToRun.GetClass());
// Its arguments
params.addAll(ExpandStrings(appToRun.GetProgramArgs()));
// The common arguments
params.addAll(ExpandStrings(AppDesc.GetCommonProgramArgs()));
ProcessBuilder processBuilder = new ProcessBuilder(params);
process = processBuilder.start();
return CaptureProcessOutput(); // Uses a StreamGobbler class
protected ArrayList<String> ExpandStrings(String[] stra)
{
ArrayList<String> alResult = new ArrayList<String>();
for (int i = 0; i < stra.length; i++)
{
// Super flexible, eh? Ad hoc for the current task, at least...
alResult.add(stra[i]
.replaceAll("\\?i", strInstallDir)
.replaceAll("\\?c", strConfigDir)
);
}
return alResult;
}
public enum AppDesc
{
// Enumerate the applications to run, with their parameters
}
Incomplete, if you need more details, just ask.
public class Test {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("\"c:/program files/windows/notepad.exe\"");
p.waitFor();
}
}
The above works quite well, instead of passing \"c:/program files/windows/notepad.exe\" as the arguments for the executable, use the path to your program, I'm not sure if this solution is JVM version dependent, or if it can use relative paths.
You must pass the path of your executable at the exec method. Are you really trying to execute the "-" process?
Also, have a look at this for some useful tips.
Put ant lib in you classpath ( project lib ) and run this code :
import org.apache.tools.ant.taskdefs.Execute;
Execute exe = new Execute();
exe.setCommandline(new String[]{"java", "-version"});
exe.execute();
I can't remember the exact code that I used to get this to work, but you have to pass "java.exe" (or the equivalent) as the executable, and then the class or jar to run as the parameter, with the correct working directory. So it's not as simple as just calling one method.
I had a similiar problem. I needed to run a section of Java code in a seperate VM as it invoked native code via JNI that occasionally blew up taking out the entire VM.
I cheated a little though. I initially used Runtime to invoke a simple batch command file and put the work-in-progress java command in there. This enabled me to tweak it as needed and to run the command in a DOS prompt for easy testing. Once it was finished I simply copied the result into the Runtime invocation.
First you compile the prog-A code and convert to jar file(ie:In NetBeans Shift-F11)and the path is of netbeans(NetBeansProjects/prog-A/dist/prog-A.jar)
public class ProgA {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Helllo print thr ProgA");
}
}
}
Second open the new project in prog-B and add the libraries, and select the jar and give to the prog-A.jar file and write the two line in your program
public class ProgB {
public static void main(String[] args) {
ProgA progA = new ProgA();
String arg[] = null;
progA.main(arg);
}
}
I agree with Ushsa Varghese, if you just want to run your jar file instead of compiling the .java file that is in the same directory you are executing your application from try the code below. This is the same as executing your java application from the command line so you have to invoke the jvm in order to run your application. Also make sure you have the complete path to your jar file the example below assumes that the jar file is in the same directory as the application that is executing the code below. keep in mind this is system dependent code.
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec("java -jar deleteDriveC.jar");
} catch (IOException ex) {
//jar file doesnt exist
//Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
}
The answer is simple all you have to do is put the code -
$ process p = Runtime.getRuntime().exec("javac factorial.java"); in the try catch block
The code would look like this -
try
{
process p = Runtime.getRuntime().exec("javac factorial.java");
}
catch(IOException e)
{
e.printStackTrace();
}
Hey I think this should work. Atleast for me it did work

Categories