I built a Java application that is delivered on USB sticks. To ensure compatibility, I ship an appropriate JVM on the sticks. I made an EXE that simply invokes this JVM with the application jar.
Now the problem: some virus scanners act aggressively and just remove the executable!
I tried an exe made with a "Batch file to Executable" tool and one written myself in C (invoking ShellExecute); both versions are detected and eliminated by Norton SONAR but I can imagine other virus scanners might react similarly.
I initially opted for a windows shortcut but these don't seem to support relative paths. A batch file is not acceptable either since I don't want the command console to be shown.
You could try using one of the many configurable java launchers - they may be less likely to be picked up by AVs:
NSIS
Janel
JSmooth
Launch4J
WinRun4J
(full disclosure: i work on winrun4j)
Use start/b java.exe ... in a batch file. There will be a short flicker but the window will quickly go away.
As for the virus scanner removing your file: Use a stick that has a hardware switch which can make it write protected. It's for your own safety: just because there is a virus scanner doesn't mean there is no virus. If no one can write to the stick, no one can mess with it.
If you launch your app using javaw.exe you shouldn't have an associated console window at all so that might get round the need to convert your bat file into an .exe.
You could also consider distributing your app as a Webstart app, whereby the associated jnlp file describes the minimum required version of the JVM.
Since the program won't have to change very often: Submit it as a false-positive to the AV vendors, then it will probably be white-listed quite rapidly. Or at least you might find out what it is that they find so objectionable.
Related
Using Java, I want to move a file on the file system despite if it's being used by another process? I've found this for deleting FileDeleteStrategy.FORCE.delete() is there an equivalent one for moving the file into another directory?
As others already pointed out, on Windows there is no such thing as move file while it's being used by other process. There is however standard way of handling such situation, but it will require OS restart.
From documentation of MoveFileEx:
MOVEFILE_DELAY_UNTIL_REBOOT 4 (0x4)
The system does not move the file until the operating system is restarted. The system moves the file immediately after AUTOCHK is executed, but before creating any paging files.
To use this function from java application, you could use JNA, but your application needs to be running with admin privileges with appropriate UAC.
From UX point of view, Jared Smith's answer make much more sense.
I'm restoring an antique vehicle and for that I use the EPC (Electronic Parts Catalog) from Mercedes Benz. (Membership is free, so those wanting to see the program I'm talking about can go here if they want to check it out.) To get to the program, there's a sign in page, then another page with a link. Clicking the link downloads a file called ewa-net.jnlp and it's launched with JavaWS.
I used to use this program on my Linux system and it worked. I remember I changed either the osname variable in my /etc directory or I changed the OS in Firefox before I ran the program and changed it back when I was done, so it wouldn't effect any other Java program. The EPC program worked just fine under those conditions. I strongly suspect the reason for requiring Windows is more of a defensive move (for example, to avoid liability or to avoid having to fix bugs on multiple OSes).
I'm aware that making changes like this can mess up a program, but this is used only to go through the parts catalog and to examine part diagrams, which helps in determining part locations or placements or helps the parts guys because I can help them find the page a part is on quickly if I've done my research before calling them. I'm not saving data or modifying anything on a disk drive or elsewhere (although I do sometimes take a screenshot and print it out).
I cannot download ewa-net.jnlp and just run it whenever I want. I have to go through the HTML login page, then run the program from their site, so I can't just run the program from the command line or something like that. (Unless that replaces running it with JavaWS right after I log in.)
Now I'm using an iMac, using Snow Leopard. I tried finding and changing the osname on here, and it didn't work.
Right now whenever I need to use the EPC, I have to start up a Windows VM in Parallels and about the only reason I use that Windows VM is for this program.
Is there some way I can trick Java so when I run this program, it thinks it's on Windows? I'm aware this could crash, but since the catalog worked fine on Linux, I want to at least try it on OS X.
I thought maybe I could use a wrapper script that runs JavaWS, but I'm not quite sure what to do and, as I said previously, changing the osname setting didn't seem to work.
Is there anything that might help me trick this program into thinking it's on Windows?
It depends on exactly what is applying the Windows restriction.
It is possible for a JNLP file to specify elements for specific operating systems only, thus effectively restricting it to a particular OS. So if the JNLP file contains something like this...
<resources os="Windows XP">
<j2se version="1.5+" />
<jar href="/example.jar" />
</resources>
...then that could be what's preventing you from running it on Mac OS X. Have a look at the JNLP file (I'm unable to see it, as a non-US resident I can't sign up myself) and see if that's the cause. If it is maybe you can edit it. Why is it that you said you can't download ewa-net.jnlp? If you can download the JNLP file, edit it to have os="Mac OS X", then double-click it to run it (or right-click and choose Open With > Java Web Start).
Alternately, the reason why changing osname didn't work for you could be that you changed it in the wrong installation of Java. Apple moved the installation location of Java sometime (I think) after Snow Leopard was released. So you may find your installation in either of these locations:
/System/Library/Frameworks/JavaVM.framework/Versions
/System/Library/Java/JavaVirtualMachines
If you only updated one of these locations, you may have to do it in the other location too.
I made a simple command-line based game in java, only two classes (using Eclipse). But I was wondering how I can make this into a usable application for anyone, without running it through eclipse (ie send it to someone who knows nothing about java but would still be able to play the game)? Thanks!
You want to create a runnable jar file.
Eclipse has an option for this in the "Export" menu. For more options, search for "executable jar file" here or on Google.
You want to make sure that you also include any jar files your code depends on as well (Eclipse can also do that for you).
Users will be able to start this by double-clicking on the file on most platforms. If you need better integration (such as a custom icon), you will need to bundle it up further into an OS-specific executable. But for starters, a simple runnable jar works fine.
send it to someone who knows nothing about java
You need to get them to at least install the Java runtime on their machine (if it is not already there).
Just to be clear, "command-line" and "knows nothing about java" are probably not going to work very well for you given that:
java is OS agnostic, therefore, if you send (presumably) a jar file to say...your grandma and she has a mac and you have a PC chances are her getting it to work is not going to be "out of the box easy" so to speak.
Left with this, I think you have a couple choices...first off, you do need to package your classes - a runnable jar will work fine. Aside from that, you will most likely have to build OS specific scripts (batch scripts for Windows, shell scripts for unix, etc.) and you will have to hand these out with your jar file. That being said, the intended user will still need to have java installed, and the batch scripts themselves are not likely to be trivial endeavors.
Your next option would be to use JNLP. However, I don't think JNLP has a command line mode, so you will likely have to simulate a console with something like a JTextArea.
As far as I see it, your last option it to use one of the many products (not sure if there are any free ones) that package java into native code. I think Exe4j is one such example - but, like I said, I am not sure if there are any free ones and I am not sure how hard they are to use.
Best of luck, and if you can't get your jar to work you should probably move that to its own question.
I have a jar. I want the jar to be able to make a copy of itself while running. I understand windows may have problems with this. How would I do this, or am I over thinking it?
Edit: To explain a bit more....
I'm writing a repackagable firmware deployment system... http://code.google.com/p/heimdall-one-click/ The idea is that a ROM developer from XDA can make his own, then pack it up in a cross-platform deployable one-click packaging nearly as easily as it is to deploy the firmware.
My program takes alot of the work out by automating the tasks... I'm trying to automate packaging of the one-click deployable packaging system.... give the developers a form to fill out which will change the header information, then they select their firmware files to be deployed. I'm trying to keep it all in one jar.
As josh says, it would be nice if you tell why do you want to do this in order to help.
Answering only what have you post, copying the jar is just copying another file. There is the issue that it might be blocked by the OS (Windows); another issue is how do you locate it in the machine and if the user running the process has the permissions needed.
Once those two issues are solved, it is just a copy operation, the OS could not care less that if the order to copy comes from the process run from the file or from another one.
EDIT to asnwer changes in the first post.
As I told before, in the end copying a file is a OS issue. If you want to copy the current jar in Windows, then the jar must not be locked by other process so it becomes an OS question rather than a Java one.
Possible workarounds:
The faster (but dirtiest) is to launch a .bat that does a sleep of a few seconds and then does the copy. Immediately after launching it, your close your java app. If you need to continue doing things in Java, after copying the file, the .bat launches the java app again (with the appropiate parameters).
A variant of the previous is slightly sleazier... launch your java app from a .bat, and the first thing that .bat does is copying your jar to the PC temp directory. Be sure to document it well so your users do not get scared!
JNI library to unlock a file. There are several programs that (Unlocker) that try to unlock files; do not know to which point it is effective or how will it affect the JVM.
I believe you can use:
File file = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
to get a reference to the path to the .JAR file.
Then you just make a copy of it:
http://download.oracle.com/javase/tutorial/essential/io/copy.html
Your operating system might not allow this, but I think it should.
On his blog Scott Kovatch writes:
Without getting into too much detail, typing ‘java MyAWTCode’ from a Terminal window violates a whole lot of assumptions about what an application is on Mac OS X, and needs a lot of cooperation between the AWT and the Process Manager to sort it out.
http://skovatch.wordpress.com/2011/01/03/secret-smoke-screens/
Out of curiosity - what assumptions are violated? Surely this is just a candidate for an API call with callbacks?
Sure, I can elaborate on that a bit.
The Process Manager starts with the assumption that all applications that present a UI on Mac OS X are bundled, are packaged in a folder named Application.app, binary in Contents/MacOS/Application, and most importantly, have an Info.plist to get things like the name of the application that will be shown in the application menu. When you run a Java application from the command line (Swing or SWT) there is no Info.plist, so we had to create a CFDictionary to be passed off to a private SPI that would register the application, give it a proper name in the Dock -- as opposed to just 'java' -- and could be force-quit.
Even then, it's not perfect, because the Dock also assumes it can store an alias to the bundled application when you right-click and choose Keep In Dock, but since there isn't one that fails silently. There's no way to store a shortcut or command line to start the application like Windows can.
The SWT just calls TransformProcessType, which is a start but is nowhere near sufficient to turn a Java application into a full UI application. For doing pure SWT testing and development it's enough to get you going. When you create an Eclipse RCP-based application for deployment you end up with a bundled application with the Eclipse launcher, and plugins and features, and you're ready to go.
Of course, if you go the extra mile and package your Java application into a bundle, this is all moot, but the vast majority of developers coming from other platforms don't bother and just want to run an executable JAR file or even a folder of class files with a shell script.
I am not sure what he had in mind, but I guess a big difference is the file structure: a normal MacOS X application is a bundle with the structure NameOfTheApp.app/Contents/MacOS/NameOfTheApp , and specific files in the Contents directory. When we use the terminal with a "java" command, the JVM has to create a "virtual" application specific to the Java code, and handle all the MacOS events for it. Also, when you open an application twice in the Finder, it simply activates the application the second time, while you need to launch separate applications every time you use "java MyAWTCode".