This is a followup question to one I previously asked:
start-program-if-not-already-running-in-java
I didn't get a great solution there (as there doesn't appear to be one), but I have a related question:
Is there anyway to launch an application in Java code (an .exe in Windows, not a Java app) and have it start minimized? Or perhaps to minimize it right after start? That would solve the focus issue from the other question and the already running problem would more or less deal with itself.
Clarification issues again: the Java client and the .exe are running in Windows and I really don't have the ability to write any wrappers or make use of JNI mojo or anything like that. I more or less need a pure Java solution.
Again, thanks for the help and I am more than willing to accept an answer that is simply: "This is just not possible."
Windows only:
public class StartWindowMinimized {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err
.println("Expected: one argument; the command to launch minimized");
}
String cmd = "cmd.exe /C START /MIN ";
Runtime.getRuntime().exec(cmd + args[0]);
}
}
Sample usage:
java -cp . StartWindowMinimized notepad.exe
java -cp . StartWindowMinimized cmd.exe
To understand the arguments involved:
cmd /?
START /?
I'm not that familiar with the specifics of Java, but according to a web site I just looked at, if you're using java.awt.Frame (which includes JFrame from Swing), you should use the function off of that frame called setState, which accepts Frame.ICONIFIED and Frame.NORMAL as a parameter (iconified would be the minimized state).
How do I minimize a Java application window?
If these apps have command-line switches to make them start minimized, then you can easily use those. Otherwise, I can't be 100% sure, but I highly doubt this is possible. You would have to have some way to interface with the Windows window manager, which is inherently very platform-specific and Java is therefore unlikely to include it. It's always possible that someone has written a third-party library to handle the task but it just doesn't seem likely to me.
Related
When I launch any third-party application, e.g. Notepad (but you could take anything else), from a Java 9 application and then exit the Java application:
import java.io.*;
public class LaunchNotepad {
public static void main(String[] args) throws IOException {
Runtime.getRuntime().exec(new String[] {"C:\\Windows\\notepad.exe"});
}
}
the launched third party application keeps locking Java 9's lib\modules file. This makes it hard for our Java application with a private JRE to update itself, because the original directory (containing the JRE) can't be renamed. Here's a screenshot from ProcessExplorer (Sysinternals):
This smells like a Java 9 bug (reported as JDK-8194734), but is there a work-around for launching an application on Windows without locking the lib\modules file, e.g. by using an external (proxy) application that simply launches the passed parameter as an application?
I fixed this bug. Does this count as a workaround? :)
Otherwise, some workarounds are indeed possible.
Workaround 1: Use awt.Desktop
Scanning through the Java sources, I found that awt.Desktop can call ShellExecute for us.
Unfortunately, this method does not allow to pass commandline arguments. You can write a temporary batch file to disk and launch it as workaround.
import java.io.*;
import java.awt.Desktop;
public class LaunchNotepad {
public static void main(String[] args) throws IOException {
File program = new File("C:\\Windows\\notepad.exe");
Desktop.getDesktop().open(program);
}
}
Workaround 2: Use PsExec as proxy
SysInternals PsExec does not inherit files into processes started with it. Remember to use -d parameter, or PsExec itself will hold the file.
Using cmd.exe as proxy is not possible, because it always inherits handles.
Workaround 3: Make your own proxy
You will need to use one of two WINAPI's: CreateProcess (specifying bInheritHandles=FALSE) or ShellExecute.
If you have an Oracle Java Support contract, you should go through the support channels to ask when a fix will be forthcoming.
UPDATE - Based on https://bugs.openjdk.java.net/browse/JDK-8194734, the current answer is likely be "when Java 11 is released". But Oracle may decide to backport the fix to Java 9 and 10.
If you are really desperate for a fix, then consider doing the following:
Download the OpenJDK source code and build your own JVM.
Figure out where the bug is. You seem to know what it is, so it should not be hard to figure out where to look.
Develop a fix for the bug.
Contribute the fix to the OpenJDK project as a patch.
That will increase the likelihood of the problem being fixed sooner in the standard codebase and the distributions produced from it. It will also give you a workaround for in-house testing and for customers who are willing to use your "fixed" JVM.
I mentioned one possible workaround that involved reworking your code which you rejected out of hand. There are others too. AFAIK there are no workarounds that don't involve work for you, one way or another.
I'm in a bit of a fix at the moment with an application I'm developing. Currently I am trying to get the program to run solely off of a USB flash drive. I want to achieve this because the computers at work don't have admin privileges to install Java. I have Java installed on my flash drive and I have my program on it as well. I would prefer to not have any CMD windows pop up because it looks really ugly. I would just like my GUI to appear but I'm running into the dumbest problem in the world. Relative paths. For some reason windows shortcuts will not allow relative paths and I can't find a way around it.
I have tried shortcuts, vbscript, and batch files. I really can't find a practical solution to this.
If anyone can offer any help, that'd be great, thanks!
EDIT: inb4 "Why do you need to do this? That's suspicious!, etc". I'm the IT guy and the program generates a nice little printer friendly table of system information in html.
I finally got it! Due to #wOxxOm's link, I was able to make a command and work my way through the restrictions. Like you can't run cmd.exe /c ./dir/program.exe because cmd doesn't like the path to the program starting with ./ for some reason. It accepts "./dir/program.exe, but vbscript doesn't like the extra quotes. My final solution involved a combination of commands strung together with the && operator.
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("cmd.exe /c cd /java/64-bit/bin/ && java -jar ../../../resources/System_Information.jar"), 0, True
Just for reference, ../../../ was faster to type than another cd command.
Anyway, thanks for the help guys!
I want to add arguments to my Java application before i run it. I want to be able do somthing like:
public static void main(String args[])
{
String document = args[0];
new DocumentViewer(document);
}
I want to do somthing like when you click on a Word document it opens up the document by itself, you dont have to open word and then click open. Does anyone know how to add arguments? All relevant answers are appriciated!
java YourClass yourfile.xtx
To associate your program with a file extension, so that it is automatically called, you have to configure your Desktop Environment (Linux) or Windows (Windows) (I don't know for OSX).
I don't have it in my head, but as far as I remember, you combine the extension, xtx for example, with a starting command, like
java -cp C:\Programs\yourlibs\your.jar YourClass %1%
If you have or can have more arguments (mark multiple files, and drag them to your starter) you can, afaik, go up to %9%:
java -cp C:\Programs\yourlibs\your.jar YourClass %1% %2% %3%
%1% is for the first param and so on.
There is nothing you can do from Java, except catching those parameter, what you already do.
On Linux, your starter is very similar:
java -cp /usr/local/lib/your.jar YourClass $1 $2 $3
If you're launching your app from the command line you could just pass the arguments separated by a blank space right after the application name like this:
java name_app arg1 arg2 etc...
//the code above passes to name_app 3 strings: "arg1", "arg2", and "etc..."
Not sure about what you want to do with Word but I hope this was helpful.
Java Web Start
..JWS provides many appealing features including, but not limited to, splash screens, desktop integration, file associations, automatic update (including lazy downloads and programmatic control of updates), partitioning of natives & other resource downloads by platform, architecture or Java version, configuration of run-time environment (minimum J2SE version, run-time options, RAM etc.), easy management of common resources using extensions..
For a demo. of the file associations, see the JNLP API file service demo.
The application that you are trying to create is a GUI application while the arguments that main method take is meant for Command Line interface input.
Where string [] args is the String array that can story many arguments from CLI. Of course you can implement the feature with a mix of CLI and GUI program but then you will be limited to launch your application from CLI, which doesn't make sense.
Another workaround can be. Create a demo frame that appears in the beginning have some textboxes and let users enter what you want to take as an argument, pass that value in the method, or data types you like. In that way you can have a full blown GUI application.
I wrote a program that solves mazes with depth-first search. I was wondering how to turn this Java program into a Screensaver application? Is there a way that Windows 7 starts my app when the screensaver would normally be activated?
A Windows screen saver is just program that accepts certain command line arguments. So in order to have your program be runnable as a screen saver you must code it to accept those arguments.
Next you will probably want your screen saver to run in full screen mode. This is very simple to do in Java as the example below shows:
public final class ScreenSaver {
public static final void main(final String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
final JFrame screenSaverFrame = new JFrame();
screenSaverFrame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE);
screenSaverFrame.setUndecorated(true);
screenSaverFrame.setResizable(false);
screenSaverFrame.add(new JLabel("This is a Java Screensaver!",
SwingConstants.CENTER), BorderLayout.CENTER);
screenSaverFrame.validate();
GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.setFullScreenWindow(screenSaverFrame);
}
}
Finally you will need to make your Java program into a Windows executable using something like Launch4j and give it .scr extension.
I have never used this but it might be the place to start. Screen Saver API.
The link to the screensaver SDK seems to be broken at the moment so I am linking to the index page: JDIC. When they fix their link I'll adjust this.
Windows screensavers are just exe files that accept certain command-line arguments, detailed here.
If you can compile your java app into an exe (I don't use java much any more so I'm not sure what tools exist), then rename it to .scr, that would do it.
Or it might be enough just to make a .bat file like:
#echo off
java myProg.class %1
.. And rename it to .scr.
I would look into the SaverBeans API for creating screen savers in Java.
Use the JScreenSaver library.JScreenSaver is the middleware to make a screen saver for Windows in Java language
One of the alternative to this approach is the new JavaFX. You can create fancy screen saver in the same way you do it in Swing. On top of that you get *.exe file quite easily using NetBeans.
This question already has answers here:
how to change the name of a Java application process?
(10 answers)
Closed 8 years ago.
If a Java program is started, it get's in the system process-monitor the name java. Many Java-programs are that way hard to distinguish. So it would be nice, if a way exists, to set the name, that will be shown in the process-monitor. I'm aware that this may work different on different Operating Systems.
A simple way would be, if the java-interpreter would support a switch to set the name, like this:
java -processname MyProgram -jar MyProgram
But I couldn't find such a switch, so it is probably non-existant. An API in Java to set the process-name would be also fine.
So, so you have any suggestions?
I don't know if this is possible, but you could use a command line tool that comes with the JDK called 'jps'. It's like *nix ps, but just Java programs instead. jps -v shows all the arguments you have passed to java.
Also, I have seen people attach a "process name" to their java processes by adding an unused -Dmyprocessname to the args.
as #omerkudat said:
jps -v
prints out all java processes {processID, params list}
If the params list is not enough to recognize the applications you need,
try adding some dummy params when running them:
java -Dname=myApp -cp myApp.jar some.client.main.MainFrame
This will print like:
7780 MainFrame -Dname=myApp
and you can use the process ID to kill / monitor it.
You can do this with an LD_PRELOAD shim: https://github.com/airlift/procname
The shim simply calls the Linux-specific prctl() when the process starts:
static void __attribute__ ((constructor)) procname_init()
{
prctl(PR_SET_NAME, "myname");
}
The call has to happen on the main thread, so it isn't possible to do this from Java or even with a JVMTI agent, since those happen on a different thread.
When I first read this, the idea of changing the process name struck me as impossible. However, according to this ancient thread on the sun forum you can use C++ wrappers around the JVM executable to achieve this.
Though frankly, I wonder what your real problem is, as I'd guess there is a more standard solution then attempting to change the process name.
Your best option is something like launch4j
http://launch4j.sourceforge.net/
There is a bug logged in the sun bugtracker for this, but it's not high priority
http://bugs.sun.com/view_bug.do?bug_id=6299778
There are mainly 2 approaches: one is as already described: using tools like Launch4j, WinRun4J to create native Windows launchers.
Another approach that seems better is to use Apache Procrun to wrap the java application as a Windows service. During the install service process, we can give the process an meaningful name such as OurApp.exe.
All we need do is rename prunsrv.exe to OurApp.exe and replace every occurrence of prunsrv.exe in our install|start|stop|uninstall service scripts to MyApp.exe.
See more from Using Apache Procrun to Rename Process Name of a Java Program in Windows
If you want to use a different process name you'll have to create your own binary to launch your Java application using something like JSmooth.
Look at this question for a discussion of creating such binaries.
That's because Java applications aren't actually executable they're ran by the Java virtual machine which is why java appears in the process monitor, it's the host of your application.
Things like LimeWire however do but I think that's more down to GCJ - http://gcc.gnu.org/java/