How to have only one instance of the CHM file opened? - java

I want to set up only one instance of the CHM file when clicking on "Help" in the menubar and stopping it from opening twice when clicked again - therefore how do I code it?
I've tried to use it with process.isAlive(), but after I close it I want a counter set to zero, which only opens another CHM file when the counter is 0.
helpMenu.addMouseListener(new MouseAdapter() {
// do this after clicked
openCHM();
});
So MouseEvent is fired once.
openCHM() {
Process p;
if(cnt == 0) {
p = Runtime.getRuntime().exec("hh.exe Help.chm");
cnt++;
if(!p.isAlive()) {
cnt = 0;
}
}
I expected the counter to be 0, but then came to the conclusion that MouseEvent already fired once and the code got already executed, therefore it never goes to the second if-statement and sets my counter to 0.
EDIT
There is no correct answer how to open a CHM file once, but there is a workaround that makes it possible, we just need to look if the file is renamable or not.
protected void openCHM() {
try {
File file = new File("YOURNAME.chm");
boolean renamable = file.renameTo(file); // can't rename if file is already open, returns true if renaming is possible
if(renamable) {
Runtime.getRuntime().exec("hh.exe YOURNAME.chm");
} else if(!file.exists() ){
// message: file doesn't exist (in path)
} else {
// file is already open
}
} catch () {
}
}

I'm not a Java programmer but the short story - not possible (AFAIK).
You know, hh.exe is the HTMLHelp executable and associated with *.CHM files. It's just a shell that uses the HTML Help API and is really just hosting a browser window.
HH.EXE is not single instance, if you open a CHM or another file three times using HH.EXE, then three help windows will appear. Try it using PowerShell:
PS D:\_working> hh.exe C:\Windows\Help\htmlhelp.chm
Several client-side command line switches are available to help authors that are part of the HTML Help executable program (hh.exe) and therefore work when HTML Help Workshop is not set up.
KeyHH.exe was running years ago with special parameters.
If you call the HH API directly from your application, and not via a second helper program like HH.EXE or KEYHH.EXE, then you MUST close any open help windows before shutting down the application or you will probably crash Windows.
For some information related to the problem you maybe interested in Open CHM File Once.
Some quoted info from the link above:
When you do that you are just calling the help viewer again and again from the command line, you're not using the HTML Help API which is what you need to access the CHM once it is open. You need to check whether your flavors of Java and Smalltalk support calls to the HTML Help API. This API is documented in detail in the help file of Microsoft HTML Help Workshop, which is the compiler package you installed to be able to generate CHMs.

Related

Files delete() method in Java is not working

Not able to delete the file001.txt which is created in my local dir path by using the removeFile(s) method in switch case. Then the method removeFile(s) calls the class Employee_Remove, where file.delete() method does not delete the files. Please find the below 2 codes and also screenshot.
I don't want to create duplicate or renaming the filename. I just need to delete the files which is created in my local dir. I did not understanding the problem whether it code problem or Eclipse problem.
Can anyone help to solve the issue.
case 3:
{
System.out.print("\nPlease Enter Employee's ID :");
String s=sc.nextLine();
Employee_Remove epr =new Employee_Remove();
epr.removeFile(s);
break;
}
class Employee_Remove {
public void removeFile(String ID) {
File file = new File("file" + ID + ".txt");
if (file.exists()) {
if (file.delete()) {
System.out.println("\nEmployee has been removed Successfully");
}
} else {
System.out.println("\nEmployee does not exists :( ");
}
}
}
If you get no output to the Eclipse console window, that means that:
Your application code has found the file. If it didn't find it, you would get a message.
The file was not deleted. If the delete had succeeded, then you would get a message to say so.
It is not clear why your application found the file but did not delete it deleted. One possibility is that your application does not have permission to delete the file. A second possibility is that something else has the file open. On Windows that locks the file, and that would prevent the application from deleting it. (There are some other more obscure causes, but I doubt that they would be applicable here ...)
If you want to get diagnostics that explain give more information about why the file wasn't deleted, switch to using the newer java.nio.file.* APIs; e.g. java.nio.file.Files::delete(Path).
If the output is NOT as you described, then it is possible that the application DID delete the file (and said so) but Eclipse has not noticed. In my experience Eclipse does not notice changes made to files that were not made by Eclipse itself.
If this is the case, then doing an Eclipse refresh should update the view. The Eclipse shortcut for this is typically F5 or CNTRL-F5, but check the key bindings.

showing error in java

I want to create an application that shows a user how many times he opened or used the software. For this I have created the code below. But it is not showing correct output: when I run the application first it is showing 1 and then the second time I run it it is also showing 1.
public Founder() {
initComponents();
int c=0;
c++;
jLabel1.setText(""+c);
return;
}
I’m unsure whether I’m helping you or giving you a load of new problems and unanswered questions. The following will store the count of times the class Founder has been constructed in a file called useCount.txt in the program’s working directory (probably the root binary directory, where your .class files are stored). Next time you run the program, it will read the count from the file, add 1 and write the new value back to the file.
static final Path counterFile = FileSystems.getDefault().getPath("useCount.txt");
public Founder() throws IOException {
initComponents();
// read use count from file
int useCount;
if (Files.exists(counterFile)) {
List<String> line = Files.readAllLines(counterFile);
if (line.size() == 1) { // one line in file as expected
useCount = Integer.parseInt(line.get(0));
} else { // not the right file, ignore lines from it
useCount = 0;
}
} else { // program has never run before
useCount = 0;
}
useCount++;
jLabel1.setText(String.valueOf(useCount));
// write new use count back to file
Files.write(counterFile, Arrays.asList(String.valueOf(useCount)));
}
It’s not the most elegant nor robust solution, but it may get you started. If you run the program on another computer, it will not find the file and will start counting over from 0.
When you are running your code the first time, the data related to it will be stored in your system's RAM. Then when you close your application, all the data related to it will be deleted from the RAM (for simplicity let's just assume it will be deleted, although in reality it is a little different).
Now when you are opening your application second time, new data will be stored in the RAM. This new data contains the starting state of your code. So the value of c is set to 0 (c=0).
If you want to remember the data, you have to store it in the permanent storage (your system hard drive for example). But I think you are a beginner. These concepts are pretty advanced. You should do some basic programming practice before trying such things.
Here you need to store it on permanent basic.
Refer properties class to store data permanently: https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
You can also use data files ex. *.txt, *.csv
Serialization also provide a way for persistent storage.
You can create a class that implements Serializable with a field for each piece of data you want to store. Then you can write the entire class out to a file, and you can read it back in later.Learn about serialization here:https://www.tutorialspoint.com/java/java_serialization.htm

How to handle if there is no default program to launch .pdf file using Runtime.getRuntime().exec("filename ")?

I have PDF file and I'm opening it using
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler "+filename+".pdf");
I'm able to open file properly, but if there are no default programs to open pdf file i need to handle that and show to user
I tried following code
public String openPdfFile(String filename){
String returnValue="";
try {
if(checkIfFileExists(filename+".pdf")){
Process pPDF= Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler "+filename+".pdf");
returnValue=""+pPDF.waitFor();
}
}
} catch (Exception e) {
return "ERROR";
}
return returnValue;
}
it will always return 0 even when there is no default program to launch. How can I achieve this?
I recommend using Desktop.open(File) instead.. It throws:
IOException - if the specified file has no associated application or the associated application fails to be launched..
The OP replied (paraphrased)..
That was really good suggestion and I tested it and it worked but it's an AWT API & I was looking for this functionality only in pure Java API..
AWT is a package in the J2SE. You cannot get more 'pure' than that. If, for some reason by 'pure' you mean 'with no GUI classes' then that doesn't make sense either, since if the user of the code is on a computer that can display a PDF, then that method should work.
Further, use of exec is as impure Java as you can get (besides that being a very poor implementation1 of use of a Process)!
Here is a small table comparing the exec implementation shown above with the Desktop method.
**OS **exec **Desktop
Windows maybe true
OS X false true
Linux false true
Unix false true
Meaning of values
true means it should work, barring a bug in the JRE or as mentioned, no suitable viewer for the file type.
false it will fail reliably - every time.
maybe it will work, presuming:
The output or error stream does not become full.
The file name has no spaces in the path or name.
There is a suitable viewer for that file type.
So I cannot see how using exec could be considered preferable to using a cross-platform method like Desktop.open(File).
See When Runtime.exec() won't for many good tips on creating and handling a process correctly. Then ignore it refers to exec and use a ProcessBuilder to create the process.

Issue with running JAR from Desktop, but not from command line or Eclipse

I am running into a peculiar issue (peculiar for me anyways) that seems to happen in a SwingWorker that I use for saving the result of another 'SwingWorker' thread as a tab-delimited file (just a spreadsheet of data).
Here is the worker, that initializes and declares an object which organizes the data and writes each table row to a file (using BufferedWriter):
// Some instance variables outside of the SwingWorker:
// model: holds a matrix of numerical data (double[][])
// view: the GUI class
class SaveWorker extends SwingWorker<Void, Void> {
/* The finished reordered matrix axes */
private String[] reorderedRows;
private String[] reorderedCols;
private String filePath; // the path of the file that will be generated
public SaveWorker(String[] reorderedRows, String[] reorderedCols) {
// variables have been checked for null outside of the worker
this.reorderedRows = reorderedRows;
this.reorderedCols = reorderedCols;
}
#Override
protected Void doInBackground() throws Exception {
if (!isCancelled()) {
LogBuffer.println("Initializing writer.");
final CDTGenerator cdtGen = new CDTGenerator(
model, view, reorderedRows, reorderedCols);
LogBuffer.println("Generating CDT.");
cdtGen.generateCDT();
LogBuffer.println("Setting file path.");
filePath = cdtGen.getFilePath(); // stops inside here, jumps to done()
LogBuffer.println("Path: " + filePath);
}
return null;
}
#Override
protected void done() {
if (!isCancelled()) {
view.setLoadText("Done!");
LogBuffer.println("Done saving. Opening file now.");
// need filePath here to load and then display generated file
visualizeData(filePath);
} else {
view.setReorderOngoing(false);
LogBuffer.println("Reordering has been cancelled.");
}
}
}
When I run the program from Eclipse, this all works perfectly fine. No issues whatsoever. Now I know there have been tons of question on here that are about Eclipse running fine while the runnable JAR fails. It's often due to not including dependencies or referring to them in the wrong way. But what's weird is that the JAR also works completely fine when it's being started from command line (Windows 8.1):
java -jar reorder.jar
Et voilà, everything as expected. The CDTGenerator will finish, write all the matrix rows to a file, and return the filePath. With the filePath I can subsequently open the new file and display the matrix.
In the case of double-clicking the JAR on my desktop, where I placed it when creating it from Eclipse, this is where the program will let me know that stuff happens. I get the error message I created for the case of filePath == null and using some logging I closed in on where the CDTGenerator object stops executing its method generateCDT() (Eclipse debugger also won't reproduce the error and do everything as planned).
What the log shows made me think it's an issue with concurrency, but I am actually leaning against that because Eclipse and command line both run the code fine. The log just tells me that the code suddenly stops executing during a loop which transforms double values from a matrix row (double[]) to Strings to be stored in a String[] for later writing with BufferedWriter.
If I use more logging in that loop, the loop will stop at a different iterator (???).
Furthermore, the code does work for small matrices (130x130) but not for larger ones (1500x3500) but I haven't tested where the limit is. This makes it seem almost time dependent, or memory.
I also used jVisualVM to look at potential memory issues, but even for the larger matrices I am on ~250MB which is nowhere near problematic regarding potential OutOfMemoryExceptions.
And finally, the last potential factor I can think of: Generating the JAR 'fails' due to some classpath issues (clean & rebuild have no effect...) but this has never been an issue before as I have run the code many many times using the 'broken' JAR and execute from Desktop.
I am a real newbie to programming, so please point in some direction if possible. I have tried to find logged exceptions, logged the values of variables, I am checking for null and IndexOutOfBound issues at the array where it stops executing... I am at a complete loss especially because this runs fine from command line.
It looks like the problem had to see with the java versions installed in OP's computer. They checked the file extensions and the programs associated to each one in order to see if it was the same java version as executed from Eclipse and the command line.
Once they cleaned older java versions the jar started to work by double-clicking it :)
Cause I do not have enough points (need 50 to directly answer your question), I need to ask this way:
If you double click a JAR you won't see a console which is often the problem because you can't see stack traces. They get just written to "nowhere". Maybe you get an NPE ore something else.
Try to attach an Exceptionhandler like this Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler) and let this handler write down a message to a file or such...
Just an idea.

listen for "open file with my java application" event on windows

Title is confusing, but don't know how to explain this in a few words:
I have a java application that reads *.example files. I've also added a file association thanks to install4j so my application is launched when the user double clicks any file with extension *.example
It seems that install4j sends the file path in the args[] so it should be easy to open that file and show it in my app. BUT what happens if the app is already running? I can only allow one instance of the application so, how can I know that the user is opening a file?
I've found this: http://resources.ej-technologies.com/install4j/help/api/com/install4j/api/launcher/StartupNotification.html
But I still don't understand how should I use it and what should I add in my app to listen for this event. Where can I find an example?
Based on the documentation you linked to, it looks like you can do this:
StartupNotification.registerStartupListener(new StartupNotification.Listener() {
public void startupPerformed(String parameters) {
System.out.println("Startup performed with parameters " + parameters);
}
});
Since startupPerformed will be called from different threads, you will need to make sure that the code that handles these notifications is thread-safe.
The documentation also says:
For multiple files, files are surrounded by double-quotes and separated by spaces.
So you will need to parse the parameter string yourself as well.

Categories

Resources