C# data to Java - java

I want to check if a Windows Workstation is logged on or off. I've found a solution in C#:
public class CheckForWorkstationLocking : IDisposable
{
private SessionSwitchEventHandler sseh;
void SysEventsCheck(object sender, SessionSwitchEventArgs e)
{
switch (e.Reason)
{
case SessionSwitchReason.SessionLock: Console.WriteLine("Lock Encountered"); break;
case SessionSwitchReason.SessionUnlock: Console.WriteLine("UnLock Encountered"); break;
}
}
public void Run()
{
sseh = new SessionSwitchEventHandler(SysEventsCheck);
SystemEvents.SessionSwitch += sseh;
}
#region IDisposable Members
public void Dispose()
{
SystemEvents.SessionSwitch -= sseh;
}
#endregion
}
but at the end I'm going to need this boolean in my Java Program.
I already tried the following:
I started both programs and C# writes into a file from where I can check all few seconds if the data has changed or not from java (don't need to say that this solution is just slow and insufficient)
Another solution would be :
Java starts the C# .exe which waits until Java connects to it through sockets and they share the data over the open connection.
Is there a better way to solve this with less effort than with this socket interface solution?

You don't have to go to any complicated lengths to get this done. It can be quite simple.
Save the boolean into a file in C#, then have a file watcher watching the directory in Java. If there is a change it can read the file in Java and find the value of the boolean. Such a solution would not be expensive and eat up a lot of CPU cycles, like a solution where you had a while loop that checked the file would be.
The beginnings of the Java code can be as simple as
import static java.nio.file.StandardWatchEventKinds.*;
Path dir = ...;
try {
WatchKey key = dir.register(watcher,
ENTRY_CREATE,
ENTRY_DELETE,
ENTRY_MODIFY);
} catch (IOException x) {
System.err.println(x);
}

There are lots of possible solutions to this issue. My personal preference would be to use a message queue to post messages between the applications. (http://zeromq.org/ is light and would be my recommendation)
The advantage of this approach is the two applications are decoupled and and its not relying on the filesystem which is notoriously prone to errors.

To call a function that is written in C# (or any .NET library function) from Java, you can use JNI.
However, all JNI will do is get you to C/C++. You will need to write a simple managed C++ object that can forward request from the unmanaged side to the .NET library.
Example Here

Related

Java crashes when closing WDropTargetContextPeerFileStream with heap corruption

I am currently working on implementing Drag & Drop from Outlook to Swing (on Windows) using a Swing DropTarget. Because Outlook Drag and Drop does no automatically work with Swing, I debugged it and found out it used the FileNameW native for the event. To support this I use this code:
private static final String nativeFileNameW = "FileNameW";
private static final DataFlavor fileNameWFlavor = new DataFlavor(InputStream.class, nativeFileNameW);
public void installFileNameWFlavorIfWindows(DropTarget dt) {
FlavorMap fm = dt.getFlavorMap();
if (!(fm instanceof SystemFlavorMap)) {
fm = SystemFlavorMap.getDefaultFlavorMap();
}
if (fm instanceof SystemFlavorMap) {
SystemFlavorMap sysFM = (SystemFlavorMap) fm;
sysFM.addFlavorForUnencodedNative(nativeFileNameW, fileNameWFlavor);
sysFM.addUnencodedNativeForFlavor(fileNameWFlavor, nativeFileNameW);
dt.setFlavorMap(sysFM);
}
}
It seems to work fine, but I am not sure if this is the correct approach, since I couldn't find any resources on this problem.
In the drop event I can now get an InputStream when an Outlook Email is dropped on the Swing Component. I use the following code in my drop method (the real method is more complex, because it also handles other DataFlavors, but this example here can reproduce the error):
public void drop(DropTargetDropEvent dtde) {
Transferable transfer = dtde.getTransferable();
boolean accepted = false;
if (transfer.isDataFlavorSupported(fileNameWFlavor)) {
accepted = true;
dtde.acceptDrop(DnDConstants.ACTION_COPY);
try (InputStream is = (InputStream) transfer.getTransferData(fileNameWFlavor)) {
//Do something with InputStream
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
dtde.dropComplete(accepted);
}
I use a try with resource statement to ensure the stream is closed after the drop event. I want to close the stream to make sure there are no open File Handles or similar native resources, that could be limited, after the drop is completed.
The InputStream for a Drop from Outlook is an Instance of WDropTargetContextPeerFileStream and when the close method is called, it crashes in the native Method freeStgMedium, which should free the native windows data structure.
I do not get any error output on the command line.
The Program terminates with error code -1073740940 which seems to indicate a heap corruption error.
Is there anything I am missing? Is this InputStream not supposed to be closed or is there a Bug earlier on.
I am using the JDK from Azul, Zulu 8.48.0.53 (Java 8u265).
I have also tried it with Zulu 11, Oracle Java 8 and a Redhat build of Openjdk 8, all fail the same way.
Update:
I think I tracked the bug down to JDK native code, that gets the data.
The JDK Code creates a STGMEDIUM object on the stack and passes a Pointer to that to the Windows Method IDataObject::GetData(). This method writes its data back into the STGMEDIUM* parameter.
This should not be a problem, since all examples of this Windows function did it the same way. But it seems, that Outlook does not initialize the member variable IUnknown *STGMEDIUM::pUnkForRelease, but instead relies on the caller to zero-fill the data structure (or Outlook has a Bug).
When the native resources are released by Java, it calls ReleaseStgMedium, which tries to call Release on the pUnkForRelease pointer, if it isn't NULL, which causes the error.
For now, I simply don't close the input stream and let a FileHandle leak, which is not optimal, but I don't see any other solution.
If I find a real solution to this Bug, I will write an Update/Answer here.

Open file from file browser in already running application [duplicate]

I need to prevent users from starting my Java application (WebStart Swing app) multiple times. So if the application is already running it shouldn't be possible to start it again or show a warning / be closed again.
Is there some convenient way to achieve this? I thought about blocking a port or write sth to a file. But hopefully you can access some system properties or the JVM?
btw. target platform is Windows XP with Java 1.5
I think your suggestion of opening a port to listen when you start your application is the best idea.
It's very easy to do and you don't need to worry about cleaning it up when you close your application. For example, if you write to a file but someone then kills the processes using Task Manager the file won't get deleted.
Also, if I remember correctly there is no easy way of getting the PID of a Java process from inside the JVM so don't try and formulate a solution using PIDs.
Something like this should do the trick:
private static final int PORT = 9999;
private static ServerSocket socket;
private static void checkIfRunning() {
try {
//Bind to localhost adapter with a zero connection queue
socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
}
catch (BindException e) {
System.err.println("Already running.");
System.exit(1);
}
catch (IOException e) {
System.err.println("Unexpected error.");
e.printStackTrace();
System.exit(2);
}
}
This sample code explicitly binds to 127.0.0.1 which should avoid any firewall warnings, as any traffic on this address must be from the local system.
When picking a port try to avoid one mentioned in the list of Well Known Ports. You should ideally make the port used configurable in a file or via a command line switch in case of conflicts.
As the question states that WebStart is being used, the obvious solution is to use javax.jnlp.SingleInstanceService.
This service is available in 1.5. Note that 1.5 is currently most of the way through its End Of Service Life period. Get with Java SE 6!
I think that the better idea would be to use file lock (quite an old idea :) ). Since Java 1.4 a new I/O library was introduced, that allows file locking.
Once the application starts it tries to acquire lock on a file (or create it if does not exist), when the application exits the lock is relased. If application cannot acquire a lock, it quits.
The example how to do file locking is for example in Java Developers Almanac.
If you want to use file locking in Java Web Start application or an applet you need to sing the application or the applet.
You can use JUnique library. It provides support for running single-instance java application and is open-source.
http://www.sauronsoftware.it/projects/junique/
See also my full answer at How to implement a single instance Java application?
We do the same in C++ by creating a kernal mutex object and looking for it at start up. The advantages are the same as using a socket, ie when the process dies/crashes/exits/is killed, the mutex object is cleaned up by the kernel.
I'm not a Java programmer, so I am not sure whether you can do the same kind of thing in Java?
I've create the cross platform AppLock class.
http://mixeddev.info/articles/2015/02/01/run-single-jvm-app-instance.html
It is using file lock technique.
Update. At 2016-10-14 I've created package compatible with maven/gradle https://github.com/jneat/jneat and explained it here http://mixeddev.info/articles/2015/06/01/synchronize-different-jvm-instances.html
You could use the registry, although this halfheartedly defeats the purpose of using a high-level language like java. At least your target platform is windows =D
Try JUnique:
String appId = "com.example.win.run.main";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (alreadyRunning) {
Sysout("An Instance of this app is already running");
System.exit(1);
}
I've seen so many of this questions and I was looking to solve the same problem in a platform independent way that doesn't take the chance to collide with firewalls or get into socket stuff.
So, here's what I did:
import java.io.File;
import java.io.IOException;
/**
* This static class is in charge of file-locking the program
* so no more than one instance can be run at the same time.
* #author nirei
*/
public class SingleInstanceLock {
private static final String LOCK_FILEPATH = System.getProperty("java.io.tmpdir") + File.separator + "lector.lock";
private static final File lock = new File(LOCK_FILEPATH);
private static boolean locked = false;
private SingleInstanceLock() {}
/**
* Creates the lock file if it's not present and requests its deletion on
* program termination or informs that the program is already running if
* that's the case.
* #return true - if the operation was succesful or if the program already has the lock.<br>
* false - if the program is already running
* #throws IOException if the lock file cannot be created.
*/
public static boolean lock() throws IOException {
if(locked) return true;
if(lock.exists()) return false;
lock.createNewFile();
lock.deleteOnExit();
locked = true;
return true;
}
}
Using System.getProperty("java.io.tmpdir") for the lockfile path makes sure that you will always create your lock on the same place.
Then, from your program you just call something like:
blah blah main(blah blah blah) {
try() {
if(!SingleInstanceLock.lock()) {
System.out.println("The program is already running");
System.exit(0);
}
} catch (IOException e) {
System.err.println("Couldn't create lock file or w/e");
System.exit(1);
}
}
And that does it for me. Now, if you kill the program it won't delete the lock file but you can solve this by writing the program's PID into the lockfile and making the lock() method check if that process is already running. This is left as an assingment for anyone interested. :)

Getting every file from directory in Java

I'm trying to write a method that, from a given directory, extract every file (also in every subdirectories). I'm using Files.find for this. The problem is that whenever it finds a file that I can't access it stops but I want to continue the research and add to the list the other files.
This is my code
public static List<String> search(String dir){
List<String> listFiles = new ArrayList<>();
try{
Files.find(Paths.get(dir), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile())
.forEach((file) -> {
listFiles.add(file.toAbsolutePath().toString());
});
} catch (UncheckedIOException ue){
System.out.println("Can't access that directory");
} catch (IOException e) {
e.printStackTrace();
}
return listFiles;
}
How can I change it?
You're looking for the FileVisitor interface from Java 8's NIO package. This class offers multiple functions to test directories for accessibility etc before entering them, as well as built-in error handling and an API to control the behaviour of your application.
Your specific problem would require to create some kind of list (E.g. outside of the FileVisitor) which you can then fill from inside the method using Collection::add
Sadly, Java's Stream API is completely unable to handle exceptions on its own, so any try to solve your problem with Streams would require a lot of unneccessary work, considering that NIO offers the more verbose, but far superior FileVisitor solution.

Major java libraries doesn't predict the case of “cyclic copy” of a file onto a destination differently mapped

In my experience and after repeated tests I've done and deep web researches, I've found that major java libraries (either "Apache Commons" or Google.coomons or Jcifs) doesn't predict the case of “cyclic copy” of a file onto a destination differently mapped (denoted with different RootPath according with newer java.nio package Path Class) that,at last end of mapping cycle,resolves into the itself origin file.
That's a situation of data losing, because Outputsream method nor jnio's GetChannel method prevents itself this case:the origin file and the destination file are in reality "the same file" and the result of these methods is that the file become lost, better said the size o file become 0 length.
How can one avoid this without get off at a lower filesystem level or even surrender to a more safe Runtime.exec, delegating the stuff at the underlying S.O.
Should I have to lock the destination file (the above methods not allowing this), perhaps with the aid of the oldest RandomAccessFile Class ?
You can test using those cited major libraries with a common "CopyFile(File origin,File dest)" method after having done:
1) the origin folder of file c:\tmp\test.txt mapped to to x: virtual drive via a cmd's [SUBST x: c:\tmp] thus trying to copy onto x:\test.txt
2) Similar case if the local folder c:\tmp has been shared via Windows share mechanism and the destination is represented as a UNC path ending with the same file name
3) Other similar network situations ...
I think there must be another better solution, but my experience of java is fairly few and so I ask for this to you all. Thanks in advance if interested in this “real world” discussion.
Your question is interesting, never thought about that. Look at this question: Determine Symbolic Links. You should detect the cycle before copying.
Perhaps you can try to approach this problem slightly differently and try to detect that source and destination files are the same by comparing file's metadata (name, size, date, etc) and perhaps even calculate hash of the files content as well. This would of course slow processing down.
If you have enough permissions you could also write 'marker' file with random name in destination and try to read it at the source to detect that they're pointing to the same place. Or try to check that file already exist at destination before copying.
I agree that it is unusual situations, but you will agree that files are a critical base of every IT system. I disagree that manipulating files in java is unusual: in my case I have to attach image files of products through FileChooser and copy them in ordered way to a repository ... but real world users (call them customers who buy your product) may fall in such situations and if it happens, one can not 'blame the devil of bad luck if your product does something "less" than expected.
It is a good practice learning from experience and try to avoid what one of Murphy's Laws says, more' or less: "if something CAN go wrong, it WILL go wrong sooner or later.
Is perhaps also for one of those a reason I believe the Java team at Sun and Oracle has enhanced the old java.io package for to the newest java.nio. I'm analyzing a the new java.nio.Files Class which I had escaped to attention, and soon I believe I've found the solution I wanted and expected. See you later.
Thank for the address from other experienced members of the community,and thanks also to a young member of my team, Tindaro, who helped me in the research, I've found the real solution in Jdk 1.7, which is made by reliable, fast, simple and almost definitively will spawn a pity veil on older java.io solutions. Despite the web is still plenty full of examples of copying files in java using In/out Streams I'll warmely suggest everyone to use a simple method : java.nio.Files.copy(Path origin, Path destination) with optional parameters for replacing destination,migrate metadata file attributes and even try a transactional move of files (if permitted by the underlying O.S.).
That's a really good Job, waited for so long!
You can easily convert code from copy(File file1, File file2) by appending a ".toPath()" to the File instance (e.g. file1.toPath(), file2.toPath().
Note also that the boolean method "isSameFile(file1.toPath(), file2.toPath())", is already used inside the above copy method but easily usable in every case you want.
For every case you can't upgrade to 1.7 using community libraries from Apache or Google is still suggested, but for reliable purpose, permit me to suggest the temporary workaround I've found before:
public static boolean isTheSameFile(File f1, File f2) {//throws Exception{
// minimum prerequisites !
if(f1.length()!=f2.length()) return false;
if (!file1.exists() || !file2.exists()) { return false; }
if (file1.isDirectory() || file2.isDirectory()){ return false; }
//if (file1.getCanonicalFile().equals(file2.getCanonicalFile())); //don't rely in this ! can even still fail
//new FileInputStream(f2).getChannel().lock();//exception, can lock only on OutputStream
RandomAccessFile rf1=null,rf2=null; //the only practicable solution on my own ... better than parse entire files
try {
rf1 = new RandomAccessFile(f1, "r");
rf2=new RandomAccessFile(f2, "rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
try {
rf2.getChannel().lock();
} catch (IOException e) {
return false;
}
try {
rf1.getChannel().read(ByteBuffer.allocate(1));//reads 1 only byte
} catch (IOException e) {
//e.printStackTrace(); // if and if only the same file, the O.S. will throw an IOException with reason "file already in use"
try {rf2.close();} catch (IOException e1) {}
return true;
}
//close the still opened resources ...
if (rf1.getChannel().isOpen())
try {rf1.getChannel().close();} catch (IOException e) {}
try {
rf2.close();
} catch (IOException e) {
return false;
}
// done, files differs
return false;
}

check for single instance java program [duplicate]

This question already has answers here:
How to implement a single instance Java application?
(17 answers)
Closed 2 years ago.
I have a program in Java (with a swing gui), and I would like only 1 instance ever to exist. If it attempted to open another instance of the program I would like the current instance to be brought to the foreground.
How do I do this?
Thanks in advance.
Launch the application using Java Web Start and implement the SingleInstanceService of the JNLP API. Here is a demo. of the SingleInstanceService.
If it attempted to open another instance of the program I would like the current instance to be brought to the foreground.
Hook that up in the newActivation(String[]) method of the SingleInstanceListener. It will be passed any arguments that were provided for the new launch. The existing instance gets to decide what to do with the new args (e.g. change file, add new tab, ignore..)
You can do it using a ShutDownHook and a lock file , see this simple example .
I think that it is the simplest way ...
There is no prev-instance in Java, but you can create a pid file in the temp (or /var/run) directory. (And make it File.deleteOnExit() to clean it anyway on exit)
To bring the existing window to top, you may notify the program yourself, thru named pipe, unix socket, or java remote method call, etc. A simple & dirty way is to write to a small file, say $TEMP/foobar-app.bring-to-top, and the program should periodically poll this small file, if it comes to exist, bring the window to top and remove this small file.
I guess Java couldn't handle signals, i.e., kill -HUP PID may not work for Java applications. Even if it could, not every OS have signals.
I did this once with a Socket and a ServerSocket:
First, when you start your application, make a ServerSocket listen on some port, for example 4004. The trick is to check whether it throws an IOException. If it does, there either is another application running or the port is used by another application (check this list for commonly used ports; Note that TCP and UDP ports are not blocking each other), otherwise you can continue with your application startup. If an instance is currently running, you might want to notify it by connecting a TCP Socket (which guarantees that your connection arrives; UDP doesn't).
Here is an example:
ServerSocket ss = null;
try {
ss = new ServerSocket(4004);
} catch (IOException ex0) {
// Port either occupied by your application or a foreign one
// -> Connect
Socket s = null;
try {
s = new Socket();
} catch (Exception ex1) {
// Something went wrong
}
if (s != null) {
// Send some singnal
}
}
if (ss == null) {
// Close or do something else
}
(I wrote this out of my memory, so some things might be wrong or could be done better).
In C# you usually create a Mutex at Applicaiton start. If you cannot create/get it, another instance of the application is already running. Unfortunately I am not 100% sure if this behaves the same in Java or what the exact syntax is.
Hope this helps.
Pattern singletone:
class SingleInstance {
private static SingleInstance instance;
public SingleInstance getInstance() {
if (instance==null)
instance = new SingleInstance();
return instance;
}
private SingleInstance() {
//construct it!
}
}

Categories