Sign in to follow this  
Followers 0
wangzhengbo

AU3_WinWaitActive has bug in AutoItX 3.3.8.1 and 3.3.10.2

15 posts in this topic

package cn.com.test;

import cn.com.jautoitx.AutoItX;
import cn.com.jautoitx.Misc;
import cn.com.jautoitx.Win;

public class TooltipBug {
    public static void main(String[] args) {
        // display tooltip at position (200, 100)
        AutoItX.tooltip("Hello, AutoIt.", 200, 100);
        Misc.sleep(2000);
        // hide tooltip
        AutoItX.tooltip();

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("#1");
                Win.waitActive("[CLASS:Notepad]");
                System.out.println("#2");
                System.out.println("'" + Win.getActiveTitle() + "'");
                Win.setTitle("[CLASS:Notepad]", "Untitled - Notepad");
                Win.waitActive("Untitled - Notepad");
                System.out.println("#3");
            }
        });
        t.start();
    }
}

AU3_WinWaitActive has bug in AutoItX 3.3.8.1 and 3.3.10.2.

See java example above.

Steps:

1. display tooltip in main thread.

2. hide tooltip.

3. start another thread, in this thread call AU3_WinWaitActive("[CLASS:Notepad]") and

    AU3_WinWaitActive("Untitled - Notepad")

4. Run "notepad.exe" in the windows command line.

Results:

    AU3_WinWaitActive("[CLASS:Notepad]") will return,

    but AU3_WinWaitActive("Untitled - Notepad") is blocked.

I think this is AU3_WinWaitActive's bug.

If you run AU3_Tooltip and AU3_WinWaitActive in the same thread, there will no problem.

You can download the required jars for the above java code from http://code.google.com/p/jautoitx/downloads/list

JAutoItX-3.3.10.2-1.0.0-alpha.jar, commons-lang3-3.1.jar, jna-4.0.0.jar, and jna-platform-4.0.0.jar are required.

Share this post


Link to post
Share on other sites



AutoItX is not threadsafe. This is your problem.

Share this post


Link to post
Share on other sites

AutoItX is not threadsafe. This is your problem.

Win.waitActive("[CLASS:Notepad]"); can work, but why Win.waitActive("Untitled - Notepad"); can not?

Share this post


Link to post
Share on other sites

Does the title version work if you run it within a single thread?

Share this post


Link to post
Share on other sites

Does the title version work if you run it within a single thread?

Yes, it's worked well in single thread.

Share this post


Link to post
Share on other sites

Yes, it's worked well in single thread.

Then the problem is exactly as I said, and you are breaking its standard flow of execution.

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

With all due respect, I'm not sure the thread is the problem.  Consider that all the code runs in the same thread - I would only expect the problem to manifest if the AutoItX code spanned more than one thread.  After all, the JVM has to be running in some thread.

wangzhengbo: I was unable to figure out which library you are using for your Java to AutoItX code.  So I can't duplicate your problem exactly.  However, I whipped up a quick test using Jacob and AutoX4Java and it works regardless of threading (link http://code.google.com/p/autoitx4java/ ):

import java.io.File;

import autoitx4java.AutoItX;

import com.jacob.com.LibraryLoader;


public class WaitActiveTest
implements Runnable {
    
    public static void main(String[] args) {
        WaitActiveTest wat = new WaitActiveTest();
        wat.notepad();
        Thread t = new Thread(wat);
        t.start();
    }

    public void run() {
        try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
        notepad();
    }
    
    private void notepad() {
        File file = new File("jacob-1.17-x86.dll");
        System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
        
        AutoItX x = new AutoItX();
        String notepad = "Untitled - Notepad";
        String testString = "this is a test.";
        x.run("notepad.exe");
        x.winActivate(notepad);
        x.winWaitActive(notepad);
        x.send(testString);
        x.winClose(notepad, testString);
        x.winWaitActive("Notepad");
        x.send("{ALT}n");
    }

}
Edited by mrider

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites

 

With all due respect, I'm not sure the thread is the problem.  Consider that all the code runs in the same thread - I would only expect the problem to manifest if the AutoItX code spanned more than one thread.  After all, the JVM has to be running in some thread.

wangzhengbo: I was unable to figure out which library you are using for your Java to AutoItX code.  So I can't duplicate your problem exactly.  However, I whipped up a quick test using Jacob and AutoX4Java and it works regardless of threading (link http://code.google.com/p/autoitx4java/ ):

import java.io.File;

import autoitx4java.AutoItX;

import com.jacob.com.LibraryLoader;


public class WaitActiveTest
implements Runnable {
    
    public static void main(String[] args) {
        WaitActiveTest wat = new WaitActiveTest();
        wat.notepad();
        Thread t = new Thread(wat);
        t.start();
    }

    public void run() {
        try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
        notepad();
    }
    
    private void notepad() {
        File file = new File("jacob-1.17-x86.dll");
        System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
        
        AutoItX x = new AutoItX();
        String notepad = "Untitled - Notepad";
        String testString = "this is a test.";
        x.run("notepad.exe");
        x.winActivate(notepad);
        x.winWaitActive(notepad);
        x.send(testString);
        x.winClose(notepad, testString);
        x.winWaitActive("Notepad");
        x.send("{ALT}n");
    }

}

 

If you run Tooltip in one thread, and then run WinWaitActive in another thread, there will be a problem as i said above.

Share this post


Link to post
Share on other sites

As I say, I can't quite figure out what libraries you have, so I can't run code identical to what you are running.  However, I converted my code to look like the following, and still have no problems.  I've never actually used AutoItX from Java in any form, so I know very little about any of the libraries (either yours or mine).  But I suspect that the problem in your code is the combination of the fact that the AutoItX stuff is static combined with your thread.  Is there some sort of "de-initialize" function in that library?  If not, you may wish to try a different library.  Or if you are the author, you might wish to forego the static ness and initialize some actual objects.

My code:

import java.io.File;

import autoitx4java.AutoItX;

import com.jacob.com.LibraryLoader;


public class WaitActiveTest
implements Runnable {
    
    public static void main(String[] args) {
        WaitActiveTest wat = new WaitActiveTest();
        wat.notepad();
        Thread t = new Thread(wat);
        t.start();
    }
    
    private final AutoItX x;
    private WaitActiveTest() {
        File file = new File("jacob-1.17-x86.dll");
        System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
        x = new AutoItX();
        x.toolTip("AutoIt X", 200, 200);
    }

    public void run() {
        try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
        notepad();
    }
    
    private void notepad() {
        System.out.println("Waiting");
        String notepad = "Untitled - Notepad";
        String testString = "this is a test.";
        x.winActivate(notepad);
        x.winWaitActive(notepad);
        x.send(testString);
        x.winClose(notepad, testString);
        x.winWaitActive("Notepad");
        x.send("{ALT}n");
    }

}

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites

Once you call the tooltip in one thread, the object is initialized and owned by that thread.

Share this post


Link to post
Share on other sites

 

Once you call the tooltip in one thread, the object is initialized and owned by that thread.

 

I agree.  However, as I mentioned, I think the fact that the methods are static factors in as well.  Because as you can see, I initialize one object and access it from more than one thread in my later example.


How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites

I agree.  However, as I mentioned, I think the fact that the methods are static factors in as well.  Because as you can see, I initialize one object and access it from more than one thread in my later example.

 

I add a simple demo, see below:

import java.io.File;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;

public class WinWaitActiveTest {
    public static void main(String[] args) {
        int SW_SHOWNORMAL = 1;
        System.load(new File("AutoItX3.dll").getAbsolutePath());

        AutoItX autoItX = (AutoItX) Native.loadLibrary("AutoItX3",
                AutoItX.class);

        /* Display and hide tooltip in one thread */
        autoItX.AU3_ToolTip(new WString("Hello 2014."), 400, 200);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        autoItX.AU3_ToolTip(null, 400, 200);

        /* Call WinWaitActive in another thread */
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                AutoItX autoItX = (AutoItX) Native.loadLibrary("AutoItX3",
                        AutoItX.class);

                System.out.println("#1");
                autoItX.AU3_WinWaitActive(new WString("[CLASS:Notepad]"),
                        new WString(""));
                System.out.println("#2");
                autoItX.AU3_WinWaitActive(new WString("无标题 - 记事本"),
                        new WString(""));
                System.out.println("#3");
            }
        });
        t.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        autoItX.AU3_Run(new WString("notepad.exe"), null, SW_SHOWNORMAL);

    }

    protected static interface AutoItX extends Library {
        public int AU3_Run(final WString fileName, final WString workingDir,
                final Integer showFlag);

        public void AU3_ToolTip(final WString text, final Integer x,
                final Integer y);

        public int AU3_WinWaitActive(final WString title, final WString text);
    }
}

You can download WinWaitActiveBug.zip, and import it into eclipse.

In the main thread, i called tooltip, and in another thread i called winWaitActive("[CLASS:Notepad]")

and winWaitActive("无标题 - 记事本"). The first call of winWaitActive will return but the second is not.

If I remove the tooltip call, winWaitActive("无标题 - 记事本") will return too.

If you want to run the example, you must change the notepad title from "无标题 - 记事本" to "Untitled - Notepad" in the

WinWaitActiveTest class.

WinWaitActiveBug.zip

Share this post


Link to post
Share on other sites

Just because it works in one situation doesn't mean it always will. I'm telling you ActiveX is meant to be run in a single thread and there's no way to fix this.

Methods being static doesn't mean they are thread safe.

Share this post


Link to post
Share on other sites

wangzhengbo:

I don't know why the code I first tried (which uses Jacob) works.  I've tried a number of variations on a theme using JNI directly as you have, and it fails as soon as I introduce a thread.  Take a look at this latest bit where the code couldn't be much more thread safe on the Java side.  As you can see, it still fails to see Notepad by name, it only sees it by class.

You might want to dig through Jacob's source to see what they do (see my first post).  I have little doubt that it's possible to correct this on the AutoItX side, but as Richard Robertson has mentioned several times, AutoItX does not support threads, so it's unlikely the AutoItX code will be altered.  You'll just have to make do with keeping AutoItX all in the same thread. 

I haven't tested what happens if you spawn a thread and initialize the dll inside that.  It may be that AutoItX will work as long as everything is in the same thread, or it may be that it has all be the main thread and no other.  I don't know.  Sorry.

import java.io.File;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;

public class WinWaitActiveTest implements Runnable {
    
    private static final int SW_SHOWNORMAL = 1;
    private final AutoItX aux;
    private final WString notepad = new WString("Untitled - Notepad");
    private final WString cnotepad = new WString("[CLASS:Notepad]");
    
    private WinWaitActiveTest() {
        System.load(new File("AutoItX3.dll").getAbsolutePath());
        aux = (AutoItX)Native.loadLibrary("AutoItX3",
                AutoItX.class);
    }
        
    public synchronized void run() {
        //this.waitFor(notepad, new WString("")); // <- FAILS 
        this.waitFor(cnotepad, new WString(""));  // <- WORKS
    }
    
    private void waitFor(final WString title, final WString text) {
        System.out.println("Waiting for " + title);
        aux.AU3_WinWaitActive(title, text);
        System.out.println("Found " + title);
    }
    
    public static void main(String[] args) {
        WinWaitActiveTest wat = new WinWaitActiveTest();
        wat.aux.AU3_ToolTip(new WString("Hello 2014."), 400, 200);
        try { Thread.sleep(2000); } catch (InterruptedException ignored) {}
        wat.aux.AU3_ToolTip(null, 400, 200);
        
        Thread t = new Thread(wat);
        t.start();
        try { Thread.sleep(2000); } catch (InterruptedException ignored) {}
        wat.aux.AU3_Run(new WString("notepad.exe"), null, SW_SHOWNORMAL);
    }

    protected static interface AutoItX extends Library {
        public int AU3_Run(final WString fileName, final WString workingDir,
                final Integer showFlag);

        public void AU3_ToolTip(final WString text, final Integer x,
                final Integer y);

        public int AU3_WinWaitActive(final WString title, final WString text);
    }
}

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites

It's not just AutoItX, it's every COM object. They are single threaded by design.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0