Can I get handle of the process by executable name? - java

I am using JNA to use user32.dll and kernel32.dll . I have the sample code which can give me the handle if i specify the title of the process.
hWnd = User32.FindWindowA(null, "Call of Duty®: Modern Warfare® 3 Multiplayer");
I really don't want to search for the process handle by the Title . Is there any method which takes the exe name? Like this:
hWnd = User32.FindWindowByExecutable ( "iw5mp.exe" );
So that, it will return 0 if this process is not running otherwise the handle.
Also, the thing is when using JNA, eclipse obviously can't auto suggest the methods present in User32 or Kernel32 dll. So, what do you do in such cases. Just google the probable method ?

With Java 9, thanks to JEP 102, it will be possible to obtain a handle of the process given an executable name, with the new ProcessHandle interface:
Optional<ProcessHandle> findByExactCommand(String command) {
return ProcessHandle.allProcesses().filter(process -> {
Optional<String> cmd = process.info().command();
return cmd.isPresent() && cmd.get().equals(command);
}).findFirst();
}
Literally answering question in title, ignoring JNA aspects, but reading comments it seems that was OP was after:
I don't think there is anything like Process.GetProcesses in java
Well, now there is ;)

String passed to FindWindow() as a second parameter is NOT title of the process. It is title of some window instead. And value returned by FindWindow() is (surprise!) handle of the window, not process handle.
If title of window you want to find may change i suggest you search window by their class name (first argument of FindWindow) leaving second argument null.
Class of windows application window may be determined by Microsoft Spy++ or similar software.

Related

How to use CreateProcessWithTokenW in Java using JNA

We are using createProcessAsUser function to create a child process running in the context of logged in/Impersonated user using waffle and JNA libraries.
But we need to load the user profile after the impersonation, but the LoadUserProfile function is not available in a JNA library.
As we found that CreateProcessWithTokenW is capable of loading the user profile. But this function also not available in the JNA/Waffle library.
Could anyone help us how to load the user profile or how to use the CreateProcessWithTokenW in Java application.
To use CreateProcessWithTokenW from java with JNA you need to bind the function. JNA is just a layer, that makes it possible to call directly native library functions. For this to work JNA uses java descriptions of the native interface, which are then used to do the actual call.
The jna-platform contrib project (released together with the main project) contains a big number of already bound win32 functions and indeed in Advapi32.java there are already bindings for CreateProcessAsUser and CreateProcessWithLogonW. Based on that I would try this (UNTESTED!):
public interface Advapi32Ext extends StdCallLibrary {
Advapi32Ext INSTANCE = Native.load("Advapi32", Advapi32Ext.class, W32APIOptions.DEFAULT_OPTIONS);
boolean CreateProcessWithToken(
HANDLE hToken,
int dwLogonFlags,
String lpApplicationName,
String lpCommandLine,
int dwCreationFlags,
Pointer lpEnvironment,
String lpCurrentDirectory,
STARTUPINFO lpStartupInfo,
PROCESS_INFORMATION lpProcessInfo
);
}
This assumes that you run with the system property w32.ascii set to false or unset, which is the recommend setup. In that case the W32APIFunctionMapper.UNICODE is used, which appends the "W" suffix automatically. The then also selected W32APITypeMapper.UNICODE ensures, that java String objects are mapped to wchars or in case of a function call to LP*WSTR.

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.

It is possible to NOT add the typed wildcards in JFileChooser's file type combobox?

I need a JFileChooser which acts like notepad.exe or mspaint.exe in save mode. As you may know when you type wildcard (* or ?) characters in the File name field the file view will show only those files which are matching for the users input. This is OK, but my problem is with the Files of type combobox:
In JFileChooser: the Files of type combo box is updated as well when the user enters a wildcard in the File name field.
See the screenshot here!
But if you try this with notepad.exe you will realize that the File name field remains as it was before, so the search pattern is not updated.
See the notepad's screenshot here!
So my question is: Does anybody know a solution how to achieve that the Files of type combo box should NOT be updated by the entered filter?
I need a cross-platform solution, so it should work both on XP and Linux.
Thanks in advance!
Sorry for the links, but I am not allowed to attach it directly!
The glob pattern recognition feature is implemented in the FileChooserUI delegate for each Look & Feel. For example, MetalFileChooserUI contains a nested ApproveSelectionAction, inherited from BasicFileChooserUI, that invokes setFileFilter(). This adds the new pattern, via a PropertyChangeEvent, to the listening MetalFileChooserUI.FilterComboBoxModel. You may be able to intercept the added filter somewhere along the chain.
You may also be able to leverage the file pattern matching capability introduced in Java 7 and discussed here.
Finally I've found a solution:
Using a custom file chooser UI derived from BasicFileChooserUI will solve my issue in the following way: I've overriden the getApproveSelectionAction() method with my custom action:
protected class CustomApproveSelectionAction extends BasicFileChooserUI.ApproveSelectionAction {
#Override
public void actionPerformed(ActionEvent e) {
String filename = getFileName();
// using a custom pattern to accept valid charachters only:
Matcher matcher = pattern.matcher(filename);
if (matcher.matches()) {
// this is the good case, just let the super implementation do what have to do.
super.actionPerformed(e);
} else {
// this is the bad case, we must warn the user and don't let the super implementation take effect.
// display an error message similar like notepad does it.
}
}
}
If the filename is ok, then I allow what super implementation does, otherwise I will display a message.

How to run vbscript function from java?

From java code i am able to run the vbscript by using this code
Runtime.getRuntime().exec("wscript C:\\ppt\\test1.vbs ");
But want to know how to call the method of vbscript from java..for example in test1.vbs
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
Set objPresentation = objPPT.Presentations.Open("C:\ppt\Labo.ppt")
Set objSlideShow = objPresentation.SlideShowSettings.Run.View
sub ssn1()
objPPT.Run "C:\ppt\Labo.ppt!.SSN"
End sub
how to call only ssn1() method from java.Otherwise can we run the macro of a power point from java code..kindly help!!
This should make you happy :) Go to the WScript section : http://technet.microsoft.com/library/ee156618.aspx
Here's my idea... in your vbscript file, make your script listen to a command line parameter that would specify which method to call. Then, in Java, you could only have to use this parameter whenever you want to call a specific method in the file.
Otherwise, if you want to access powerpoint in java, you will need to access its API like you did in vbscript, which is possible if vbscript can do it but the approach / syntax may change.
I'm not so much into the visual basic script side, but if you can expose your visual basic script as a COM object, the you can access the methods of it from java by usage of frameworks such as for example com4j:
http://com4j.java.net/
The PowerPoint application object's .Run method lets you call any public subroutine or function in any open presentation or loaded add-in
This post answers the OP's question:
Otherwise can we run the macro of a power point from java code..kindly help!!
(but does not address the original vbscript question)
There's the JACOB library, which stands for Java COM Bridge, you can find here: http://sourceforge.net/projects/jacob-project/?source=directory
With it you can invoke Excel, Word, Outlook, PowerPoint application object model methods.
I've tried this with Excel but not PowerPoint. (This is just some sample code, one might want to make it more object oriented.)
public class Excel {
private static ActiveXComponent xl = null;
public static Init() {
try {
ComThread.InitSTA();
xl = ActiveXComponent.connectToActiveInstance("Excel.Application.14");
// 14 is Office 2010, if you don't know what version you can do "Excel.Application"
if (xl==null) {
// code to launch Excel if not running:
xl = new ActiveXComponent("Excel.Application");
Dispatch.put(xl, "Visible", Constants.kTrue);
}
}
catch (Exception e) {
ComThread.Release();
}
}
public static String Run(String vbName) {
// Variant v = Dispatch.call(xl, "Run", vbName); // using string name lookup
Variant v = Dispatch.call(xl, 0x103, vbName); // using COM offset
// return Dispatch.get(this, "Name").getString();
return v.getString();
}
public static Variant Run1p(String vbName, Object param) {
// Variant v = Dispatch.call(xl, "Run", vbName, param);
return Dispatch.call(xl, 0x103, vbName, param);
// return Dispatch.get(this, "Name").getString();
}
public static Worksheet GetActiveWorksheet () {
// Dispatch d = xl.getProperty("ActiveSheet").toDispatch();
Dispatch d = Dispatch.get(xl, 0x133).toDispatch ();
return d; // you may want to put a wrapper around this...
}
}
Notes:
For Excel, at least, to get Run to invoke a VBA macro/subroutine several things have to be true:
The Excel workbook containing the macro must be "Active" (i.e. must
be the ActiveWorkbook) otherwise Run will not find the VBA subroutine. (However the workbook does not have to be
screen visible!! This means you can call a VBA Macro that is in an add-in!).
You can then pass the name of the macro using the following syntax as a string literal:
VBAProjectName.VBAModuleName.SubroutineName
For COM object invocations, you can use the name lookup version or the id number version. The id numbers come from the published COM interfaces (which you can find in C++ header files, or possibly have JACOB look them up for you).
If you successfully did the connection to Excel, be sure to call ComThread.Release() when you're done. Put it in some appropriately surrounding finally. If the process of your Java code terminates without calling it, the COM reference count on Excel will be wrong, and the Excel process will never terminate, even after you exit the Excel application. Once that happens, needless to say, Excel starts to behave screwy then (when you try to use it next, it runs but will fail to load any plug-ins/add-ons). If that happens (as it can during debugging esp. if you are bypassing finally's for better debugging) you have to use the task manager to kill the Excel process.

Using Windows API call in Java using "native"

I've tried to solve this issue by referring possible duplicates but none of them seem to be helpful.
Here's a code that I'm using to call Win API methods in Java to get current Windows User Name, and a native Windows MessageBox, but I'm getting UnsatisfiedLinkError that says that my code is unable to locate the native method I'm trying to call.
public class TestNative
{
public static void main(String[] args)
{
long[] buffer= { 128 };
StringBuffer username = new StringBuffer((int)buffer[0]);
GetUserNameA(username,buffer);
System.out.println("Current User : "+username);
MessageBoxA(0,"UserName : "+username,"Box from Java",0);
}
/** #dll.import("ADVAPI32") */
static native void GetUserNameA(StringBuffer username,long[] buffer);
/** #dll.import("USER32") */
private static native int MessageBoxA(int h,String txt,String title,int style);
}
What can be my possible (relatively simple) solution to call native Windows methods in Java. I realize that it will kill the very reason of Java being a cross-platform language, but I need to work on a project for Windows, to be developed in Java.
Thanks.
Update
As David Heffernan suggested, I've tried changing the method signature of MessageBox to MessageBoxA, but still it's not working.
I would guess it's related to the signatures not matching completely.
The GetUserName function takes two parameters: a LPTSTR and a LPDWORD. Java will likely not handle the StringBuffer acting as a TCHAR array for you.
Also, why bother using the Windows API for this? Java can probably get the user's logon name (quick google says: System.getProperty("user.name")), and Swing can make a message box (even one that looks like a Windows one).
Have you tried https://github.com/twall/jna. I have heard good things and its supposed to make jni that bit easier with many conveniences and simplifications.
Do you have a -Djava.library.path VM arg set with the path to your DLL's? Alternatively, you can have it in your system PATH.
The error is because there is no MessageBox. You presumably mean MessageBoxA.

Categories

Resources