This question already has answers here:
Java Runtime Exec With White Spaces On Path Name
(2 answers)
Closed 6 years ago.
I want to launch external Program with Arguments(one of the argument is to load the Config file to that external program) after I click the button of javafx app(the btn event not included in the code) but I wonder why it keeps giving me errors!
My IDE is InjellJ IDEA Community edition
I know this question is the duplicate but among all the examples given here in this platform have been tried with no sucess however my code contains config file as part of the argumets
Here is the code
private String appDomain = Paths.get("").toAbsolutePath().normalize().toString();
private String exepath = appDomain+"\\src\\bin\\exeResources\\MyExe.exe";
private String exeargs = appDomain+"\\src\\bin\\exeResources\\MyExe.ppx silent-load";
try {
Runtime r = Runtime.getRuntime();
r.exec(exepath +" "+exeargs);
} catch (IOException e) {
e.printStackTrace();
}
when I remove the "exeargs" I get the error
CreateProcess error=193, %1 is not a valid Win32 application
Making it difficult for me to know if "exeargs" can work with the above snippet.
Your help will be appreciated
EDIT
The exefile and execonfig I have to load is located in one of the package in my project **bin.exeResource**
Printing the paths and args by
System.out.println(exepath+" "+exeargs);
Gives me
C:\Users\{MyUser}\OneDrive\IntelliJ IDEA Projects\MyProject Package\src\bin\exeResources\MyExe.exe ...\src\bin\exeResources\MyExe.ppx silent-load
with an Error
CreateProcess error=193, %1 is not a valid Win32 application
There is a exec method specifically overloaded for your purposes. It takes as an argument String array which holds the command and the arguments for the command. That seems to be exactly what you need. Please look at the API
I think you are confusing about the exe arguments. Try this one:
private String appDomain = Paths.get("").toAbsolutePath().normalize().toString();
private String exepath = appDomain + "\\src\\bin\\exeResources\\MyExe.exe";
private String exeargs = "silent-load";
try {
Runtime r = Runtime.getRuntime();
r.exec(exepath + " " + exeargs);
} catch (IOException e) {
e.printStackTrace();
}
Related
After exporting a matlab function to java package. I have tried to run the following code unix environment which contains MATLAB runtime.
import com.mathworks.toolbox.javabuilder.MWArray;
import com.mathworks.toolbox.javabuilder.MWCharArray;
import calibrationAPINew.Calibration;
public class CHIndexCalculation {
public static void main(String[] args) {
MWCharArray number1 = null;
Object[] result = null;
Calibration calibration = null;
String data = "{\r\n" +
"\"tsId\" : \"121213\",\r\n" +
"\"datapoints\" : [0.1,0.2,0.3,0.4]\r\n" +
"}";
try
{
System.out.println("Input data: " + data);
number1 = new MWCharArray(data); // Array of Input to be sent to MATLAB Runtime
System.out.println("MWCharArray: " + number1);
calibration = new Calibration();
result = calibration.calibrationAPI(1,number1);
System.out.println("Output : " + result[0]);
}
catch (Exception e)
{
System.out.println("Exception Occurred : " + e);
e.printStackTrace();
}
finally
{
//MWArray.disposeArray(number1);
//MWArray.disposeArray(result);
//calibration.dispose();
}
}
}
I have installed the matlabruntime on unix box and set the environment variables using export statement
export LD_LIBRARY_PATH=matlabrt/v92/runtime/glnxa64:matlabrt/v92/bin/glnxa64:matlabrt/v92/sys/os/glnxa64:matlabrt/v92/sys/opengl/lib/glnxa64
Now when I try to run the command ( calibrationAPINew.jar is the jar file exported from MATLAB)
java -cp javabuilder.jar:calibrationAPINew.jar:. CHIndexCalculation
I get the following exception
com.mathworks.toolbox.javabuilder.MWException: Undefined function 'pdist2mex' for input arguments of type 'double'.
at com.mathworks.toolbox.javabuilder.internal.MWMCR.mclFeval(Native Method)
at com.mathworks.toolbox.javabuilder.internal.MWMCR.access$600(MWMCR.java:31)
at com.mathworks.toolbox.javabuilder.internal.MWMCR$6.mclFeval(MWMCR.java:882)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.mathworks.toolbox.javabuilder.internal.MWMCR$5.invoke(MWMCR.java:769)
at com.sun.proxy.$Proxy0.mclFeval(Unknown Source)
at com.mathworks.toolbox.javabuilder.internal.MWMCR.invoke(MWMCR.java:443)
at calibrationAPINew.Calibration.calibrationAPI(Calibration.java:223)
at CHIndexCalculation.main(CHIndexCalculation.java:24)
I know this has something to do with MATLAB runtime but I am unable to figure out what ? The same set up works fine on windows environment.
I think the matlab program uses some mexfile which is already compiled for windows, so that it is working perfect on windows. Since the mexfile is already available it will work perfect on windows. But when your script failed to find the corresponding mexfile for linux it fails or tries to compile the source files for linux using the function 'pdist2mex' which is not included in the jar package.In windows there is no need of this function so it works fine. If this is the case then you can either add the function 'pdist2mex' to your jar from matlab or you should compile the sources to linux compatible mex-file manually using matlab and then try to repackage it then the matlab automatically wrap the corresponding mex file to the jar
Hello working on a small program that just needs to run a python script I have. This python script will play a given .wav file, and draw a shape on the turtle screen. As such, I'm not looking for an output to be returned to java. Here is my java code:
public class Driver {
public static void main(String[] args){
try {
Process p = Runtime.getRuntime().exec("python " +
" D:/Coding Files/Python/MusicColors.py" +" teenagers.wav");
}
catch (Exception e){
System.out.println(e);
}
}
}
The exception I get is:
java.io.IOException: Cannot run program "python":
CreateProcess error=2, The system cannot find the file specified
I probably am making a very stupid mistake as I have limited knowledge in the subject of processes and such. I added python to my system path, so whenever I put "python" into command line, it returns with
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
And makes it the python shell.
Here is the exact line I added to my environment path:
C:\Users\Joe\AppData\Local\Programs\Python\Python35-32
If anyone can figure out where I went wrong I'd really appreciate it!
The $PATH variable you've set is not inherited in Java's execution context. Try passing the Python's bin path to exec()'s execution environment.
To do this, the code below first retrieve all the environment variables and create an array of ENV_KEY=ENV_VALUE pairs.
Then, the path to your Python's bin is appended to the PATH value.
Finally, we pass the array of all environment variables to exec() (via the second parameter).
import java.util.HashMap;
import java.util.Map;
public class Driver {
public static void main(String[] args){
try {
String[] commands = {"python D:/Coding Files/Python/MusicColors.py teenagers.wav"};
// Get a list of all environment variables
final Map<String, String> envMap = new HashMap<String, String>(System.getenv());
// Append Python bin path to Path
envMap.put("Path", envMap.get("Path") + ";C:/Users/Joe/AppData/Local/Programs/Python/Python35-32");
// Convert to an array of ENV_KEY=ENV_VALUE format strings
final String[] envs = new String[envMap.size()];
int i = 0;
for (Map.Entry<String, String> e : envMap.entrySet()) {
envs[i] = e.getKey() + '=' + e.getValue();
i++;
}
// Exec with the environment variables
Process p = Runtime.getRuntime().exec(commands, envs);
}
catch (Exception e){
System.out.println(e);
}
}
}
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).
As the title says, I'm wondering if it is possible for a program written in Java (and only java) to relaunch himself (preferably a .jar) with administrator privileges, showing in the way the native Windows UAC (in order to make it more trustable for the user), i did my homework and found out that it is possible to accomplish this using bridges between c++ and java, but i would really like to do this as a pure java project.
P.S: In the remote case that this result to be impossible, can someone show me the "easy" way to do this using another language (i mean, I've found tutorials, but they are to complicated for something I think it should not be that complicated).
P.S2: In case it is possible to accomplish this, would it work, on other platforms (OS X, Linux)
It cannot be done in pure java.
Best bet would be to write this to a file:
#echo Set objShell = CreateObject("Shell.Application") > %temp%\sudo.tmp.vbs
#echo args = Right("%*", (Len("%*") - Len("%1"))) >> %temp%\sudo.tmp.vbs
#echo objShell.ShellExecute "%1", args, "", "runas" >> %temp%\sudo.tmp.vbs
#cscript %temp%\sudo.tmp.vbs
and save it as something.bat in Windows temp directory (as we have access to this).
You would then execute this from your application using Runtime or ProcessBuilder and exit your application (System.exit(0);).
You should add an immediate start up check to your application that checks if the program has elevation, if it has proceed if not re-run the batch and exit.
Here is an example I made (this must be run when compiled as a Jar or it wont work):
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
/**
*
* #author David
*/
public class UacTest {
public static String jarName = "UacTest.jar", batName = "elevate.bat";
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
if (checkForUac()) {//uac is on
JOptionPane.showMessageDialog(null, "I am not elevated");
//attempt elevation
new UacTest().elevate();
System.exit(0);
} else {//uac is not on
//if we get here we are elevated
JOptionPane.showMessageDialog(null, "I am elevated");
}
}
private static boolean checkForUac() {
File dummyFile = new File("c:/aaa.txt");
dummyFile.deleteOnExit();
try {
//attempt to craete file in c:/
try (FileWriter fw = new FileWriter(dummyFile, true)) {
}
} catch (IOException ex) {//we cannot UAC muts be on
//ex.printStackTrace();
return true;
}
return false;
}
private void elevate() {
//create batch file in temporary directory as we have access to it regardless of UAC on or off
File file = new File(System.getProperty("java.io.tmpdir") + "/" + batName);
file.deleteOnExit();
createBatchFile(file);
runBatchFile();
}
private String getJarLocation() {
return getClass().getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);
}
private void runBatchFile() {
//JOptionPane.showMessageDialog(null, getJarLocation());
Runtime runtime = Runtime.getRuntime();
String[] cmd = new String[]{"cmd.exe", "/C",
System.getProperty("java.io.tmpdir") + "/" + batName + " java -jar " + getJarLocation()};
try {
Process proc = runtime.exec(cmd);
//proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void createBatchFile(File file) {
try {
try (FileWriter fw = new FileWriter(file, true)) {
fw.write(
"#echo Set objShell = CreateObject(\"Shell.Application\") > %temp%\\sudo.tmp.vbs\r\n"
+ "#echo args = Right(\"%*\", (Len(\"%*\") - Len(\"%1\"))) >> %temp%\\sudo.tmp.vbs\r\n"
+ "#echo objShell.ShellExecute \"%1\", args, \"\", \"runas\" >> %temp%\\sudo.tmp.vbs\r\n"
+ "#cscript %temp%\\sudo.tmp.vbs\r\n"
+ "del /f %temp%\\sudo.tmp.vbs\r\n");
}
} catch (IOException ex) {
//ex.printStackTrace();
}
}
}
Use a batch file and the runas command.
I doubt "only Java". At best you would have to have a JNI wrapper around the MSFT module. Unless just invoking the exe using ProcessBuilder counts as "only Java" -- your code to bring up the user console would be only Java but not what it invokes. IOW, Win does not come with a Java API
To relaunch your application elevated, you have to call ShellExecute or ShellExecuteEx function from Windows API and use runas verb.
You can use these API in pure Java with JNA library.
To relaunch yourself, you would have to know the full path to java.exe or javaw.exe, the command-line parameters (class path, if any, and the path to your jar). Obviously you can get this information by using Windows API.
What do you mean by remote case?
You cannot start remote elevated process this way.
You can re-launch your application elevated from a network share. Yet it won't work with mapped drives: after elevation there's no access to user's mapped drives.
No, this can't work on other platforms. UAC is a Windows feature. It's similar to sudo in Linux in some ways, so for Linux you can use sudo $pathtojava/java.exe <yourparameters>. However this won't work nicely if your application is not started from a console. Window Managers usually have wrappers which prompt for password in a GUI dialog.
Just do this with Hackaprofaw (v29). Also it was released in 2002 and started development in 1997 soooooo ye. in 2021 its on version 29.10.7 but-
if raw ram = 0
disable "featureII" program = "JAVA(math = any)"
run on "Hackaprofaw (math = v29(x))
when "featureII" disabled
end
I m passing multiple tab delim files into R via Java.The R programm merges those tab delim files as single file and sends back to java and it is captured in the variable "name".Now I want to rename and save that file stored in "name" as tab delim using save dialog box in windows.Any help highly appreciated.Here is the java code:
import org.rosuda.REngine.*;
public class rjava {
// Before this run Rserve() command in R
public String ana(String filenames)
{
String name = "";
try{
System.out.println("INFO: Trying to connect to R ");
RConnection c = new RConnection();
System.out.println("INFO: Connected to R");
System.out.println("INFO: The Server version is "+ c.getServerVersion());
// c.voidEval("source('D:/combine/combining_files.r')");
c.voidEval("source('D:/combine/merge.r')");
c.assign("file",filenames);
// name = (c.eval("fn(file)").asString());
name = (c.eval("combine (file)").asString());
c.close();
}
catch(Exception e)
{
System.out.println("ERROR: In Connection to R");
System.out.println("The Exception is "+ e.getMessage());
e.printStackTrace();
}
return name;
}
}
I find passing complex objects between R and Java to be a pain the ass. I would not pass the full data, but rather would pass only file names as a string. Either have Java tell R to write out the new file (my pref) or have Java read in the file and then write out with a new name.
Can you modify the R program, so that it outputs files in the same path with a given file name, such as [path]/filename.out?
Otherwise, you can modify the execte string so that the R program outputs in a given location.
See http://cran.r-project.org/doc/manuals/R-intro.html#Invoking-R-from-the-command-line
When working at a command line on UNIX or Windows, the command ‘R’ can be used both for starting the main R program in the form R [options] [<infile] [>outfile]
-- EDIT
I just saw that you are using an RConnection. According to the R docs, you can define where to pipe stdout
The function sink, sink("record.lis") will divert all subsequent output from the console to an external file, record.lis.