B4J Question How to set a focus on the loaded window?

T201016

Active Member
Licensed User
Longtime User
Example::
Private parms As List
    Private DirApp As String = File.Combine(File.DirApp,"JAR2_ConvertPDFtoJPG.exe")
   
    Try
        parms.Initialize
        parms.Add("-jar")
        parms.Add(DirApp)
   
        shl.Initialize("shl", "java.exe" , parms)
        shl.WorkingDirectory = File.DirApp
        shl.Run(-1) 'set a timeout of 10 seconds - Pass -1 to disable the timeout.
        Return True
    Catch
        If shl.IsInitialized Then shl.KillProcess
        Return False
    End Try


The above example will allow you to launch and open the program window.

How can I prevent the same program from restarting?
- Instead, I would like to focus on the existing window of this program (on the monitor screen).

I don't know if you can do something like that on external executable files.
How can I extract the assigned name of the charged window?

I am asking for possible knowledge on this subject.
 

T201016

Active Member
Licensed User
Longtime User
Maybe you can deal with the described different approaches to load multiple versions of the same class
Java Classloader - Handling Multiple Versions of The Same Class
Hi @MicroDrie
Charging jars during the performance, which was always considered a bad practice, is now more difficult-from Java, 9 things have become much more complicated in the new module system: JAVA9.

If I don't find a library, I can create my own on the basis of this example:

Loader::
#if Java
     import java.lang.reflect.*;
     import java.io.File;
     import java.net.URLClassLoader;
     import java.net.URL;
      import java.util.Arrays;
   
    public static synchronized void loadJDBCLibrary(String  jarFile)
   
    {
   
        try {
            java.io.File driverJDBC  = new  java.io.File(jarFile);
            java.net.URLClassLoader systemLoader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
            java.net.URL driverJDBCURL =  driverJDBC.toURI().toURL();
            for (java.net.URL loadedJars : java.util.Arrays.asList(systemLoader.getURLs())){
                if (loadedJars.equals(driverJDBCURL)){
                    return;
                }
            }
            java.lang.reflect.Method methodAddURL = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
            methodAddURL.setAccessible(true);
            methodAddURL.invoke(systemLoader, new Object[]{driverJDBCURL});
        } catch (Exception e){
          throw new RuntimeException(e);
         
        }
    }

    #End If
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
I've literally just written code to load a jar and a class from the jar, I don't know what will happen if you load 2 versions of the jar though. You'll have to try that.

Hope it helps

Class LoadJar:
Sub Class_Globals
'    Private fx As JFX
    Dim URLClassLoader As JavaObject
    Dim mLoaded As  Boolean = False
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
 
End Sub

'Loads a jar to the classpath
Public Sub JarLoad(jarFilePath As String, ClassName As String, ExceptionList As List ) As Object', JavaClass As String' As JavaObject
    mLoaded = False
    Try
        URLClassLoader =  Me.as(JavaObject).RunMethod("loadJar",Array(File.GetUri(jarFilePath,""),ClassName))
        Dim LoadedClass As JavaObject = Me.as(JavaObject).RunMethod("loadClass",Array(URLClassLoader,ClassName))
    Catch
        ExceptionList.Add(LastException.Message)
        Return Null
    End Try

    mLoaded = True
    Return LoadedClass
 
End Sub

Public Sub JarClose
    URLClassLoader.RunMethod("close",Null)
    Dim URLClassLoader As JavaObject
    mLoaded = False
    Log("Unloaded")
End Sub

Public Sub getIsLoaded As Boolean
    Return mLoaded
End Sub

#if java
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.lang.ClassNotFoundException;
import java.lang.ClassCastException;
import java.lang.NoClassDefFoundError;

public static URLClassLoader loadJar(String jarPath, String className) throws Exception{
 
    URL[] jarURL = new URL[1];
    try{
        jarURL[0] = new URL(jarPath);
    } catch(MalformedURLException e){
        throw new RuntimeException("MalformedURLException");
    }
 
    URLClassLoader urlClassLoader = new URLClassLoader(jarURL);
 
    return urlClassLoader;
}

public static Object loadClass(URLClassLoader urlClassLoader, String className) throws Exception{
Class<?> loadedClass = null;
    try{
        loadedClass = urlClassLoader.loadClass(className);
    } catch(ClassNotFoundException e){
        throw new RuntimeException("ClassNotFound");
    } catch(ClassCastException e){
        throw new RuntimeException("ClassCastException");
    }catch(NoClassDefFoundError e) {
        throw new RuntimeException("NoClassDefFound");
    }
    return loadedClass;
}

#End If

Check the exception list once complete. It took a while to figure out the exception handling.

I did it as two calls so I could get the URLClassLoader object that needs to be closed when you have finished with the jar.
 
Last edited:
Upvote 0

T201016

Active Member
Licensed User
Longtime User
I've literally just written code to load a jar and a class from the jar, I don't know what will happen if you load 2 versions of the jar though. You'll have to try that.
I was just starting this problem when I looked at your post. It seems to be good in my project. I will pay attention to the problem of using two different versions of JAR. This example works for me, thanks!
 
Upvote 0

T201016

Active Member
Licensed User
Longtime User
I was just starting this problem when I looked at your post. It seems to be good in my project. I will pay attention to the problem of using two different versions of JAR. This example works for me, thanks!

During the compilation of an example project, two types of error were captured:
1. first: without using #AdditionalJar

Compilation of the generated Java code. Error
Javac 1.8.0_441
SRC \ B4J \ Example \ CLSPDFVVIEWER.Java: 7: Error: Package org.apache.pdfbox.pdmodel Dos not Exist
Import org.apache.pdfbox.pdmodel.pddocument;
^
1 error

2. second:
- java.lang.runtime.exception: classnotphound

The question is, do I make JarLoader well? And in the right place?
I think that I set the access path correctly ... jarLoader.JarLoad("D:\", "pdfbox-app-2.0.27.jar",lst)
 

Attachments

  • b4JPDFViewer.zip
    40.4 KB · Views: 9
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Without the #AdditionalJar definition, you won't be able to reference anything in code. You will only be able to access the jar using javaobject or reflection. So you would have to rewrite the #if java code to use one of those.

For my use I only want to read the signatures from the class, which is working, mostly. Although the pdDocument is proving elusive.

I think the answer to both issues is probably to instantiate a class directly on the returned class object, which again is not straightforward.

I did see an older library https://www.b4x.com/android/forum/threads/jarloader.81393/#content, have you tried that one?
 
Upvote 0

T201016

Active Member
Licensed User
Longtime User
I did see an older library https://www.b4x.com/android/forum/threads/jarloader.81393/#content, have you tried that one?
Regarding the old version, I used it and seems to be done without any mistakes. I loaded even two JAR files without a problem.
Only that I miss in this older version of the closing function used in the JAR project.

But I have something that closes them:

Close all JAR::
------- close all .jar

public class MyURLClassLoader extends URLClassLoader {

public PluginClassLoader(URL[] urls, ClassLoader parent) {
    super(urls, parent);
}

    /**
     * Closes all open jar files
     */
    public void close() {
        try {
            Class clazz = java.net.URLClassLoader.class;
            Field ucp = clazz.getDeclaredField("ucp");
            ucp.setAccessible(true);
            Object sunMiscURLClassPath = ucp.get(this);
            Field loaders = sunMiscURLClassPath.getClass().getDeclaredField("loaders");
            loaders.setAccessible(true);
            Object collection = loaders.get(sunMiscURLClassPath);
            for (Object sunMiscURLClassPathJarLoader : ((Collection) collection).toArray()) {
                try {
                    Field loader = sunMiscURLClassPathJarLoader.getClass().getDeclaredField("jar");
                    loader.setAccessible(true);
                    Object jarFile = loader.get(sunMiscURLClassPathJarLoader);
                    ((JarFile) jarFile).close();
                } catch (Throwable t) {
                    // if we got this far, this is probably not a JAR loader so skip it
                }
            }
        } catch (Throwable t) {
            // probably not a SUN VM
        }
        return;
    }
}
 
Upvote 0

T201016

Active Member
Licensed User
Longtime User
Yeah, I don't think it will work on anything later. It's certainly not working on 14.
They write on the internet that a large staircase starts from version 9, I don't know if it's true. I will look on other versions until I come across.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Longtime User
Isn't it true that MyURLClassLoader only works in Java 8 because the JDK 9 release notes state: "The application class loader is no longer an instance of java.net.URLClassLoader (an implementation detail never specified in previous releases)?"
 
Upvote 0
Top