Проблема с закрытием приложения с помощью Sikuli

А вот возник еще один вопрос. Сделал пример как в видео показывал Михаил Поляруш.
App spotify = App.open("C:\\Program Files (x86)\\Stamina\\Stamina.exe"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } spotify.close();
Но у меня не срабатывает close() и тест проваливается.
В интернете поискал, нашел еще один вариант
String stamina = "C:\\Program Files (x86)\\Stamina\\Stamina.exe"; App.open(stamina); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } App.close(stamina);
В таком случае тест проходит, но программа все равно не закрывается и в консоле нет [log] App.close
Можете помочь в чем проблема?

Что значит не срабатывает? Случайно не такая вот ошибка?
[error] AttributeError ( 'NoneType' object has no attribute 'close' )

Вот что пишет:
java.lang.NullPointerException at Sikuli.testSikuly(Sikuli.java:22) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

на

означает, что

вернул null.

   * creates an instance for an app with this name and tries to open it
   * @param appName name
   * @return the App instance or null on failure
   */
  public static App open(String appName) {
    return new App("+" + appName).open();
  }

П.С. У вас приложение Stamina то хоть установлено в системе? И почему переменная названа spotify? Видимо, открывать вы собирались совсем не клавиатурный тренажер?

Stamina установлена и она открывается, а spotify то просто старое название осталось, не поменял.

Ок, а что сам сикули в логе пишет? Он должен что-то выводить при попытке открытия приложения.

Вот все что пишет
фев 01, 2016 10:52:17 PM org.bridj.BridJ log INFO: Registering type org.sikuli.util.SysJNA$WinKernel32 фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.TimeT фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.TimeT$timeval_customizer фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.StructIO$DefaultCustomizer фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.TimeT$timeval фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.StructObject фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.NativeObject фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type org.bridj.AbstractIntegral фев 01, 2016 10:52:18 PM org.bridj.BridJ log INFO: Registering type java.lang.Number [log] App.open [4904:]

Cмотрю в исходники. Там весьма суровый конструктор у App. В вашем случае путь разрезается по пробелам, что в итоге приводит к полной каше.

Во-первых, попробуйте запустить что-то такое, что не содержит пробелов в пути (чисто эксперимента ради).
Во-вторых, попробуйте создать объект App напрямую, а затем вызвать open:

App app = new App("path").open();

У них там в статическом методе open на кой-то конкатенируется + к имени, после чего вы попадаете в страшный if/else в конструкторе, беспощадно разрезающий ваш путь. Но если вызывать конструктор напрямую, вы должны миновать эти страшные if'ы и уйти в нативные API.

Попробуйте оба варианта. Сейчас под рукой нет сикули, чтобы проверить.

UPDATE: все пути ведут к этому коду:

        } else {
          parts = name.split(" ");
          if (parts.length > 1) {
            options = name.substring(parts[0].length() + 1);
            name = parts[0];
          }

По ходу какая-то подстава выходит с путями с пробелом. Не хочу копаться, если честно. Попробуйте без пробелов для начала. Если не поможет, спрошу у главного разработчика об этой хитрой логике.

1 лайк

Спасибо, да проблема была в пробелах, без них все работает. Я недавно тоже сталкивался с подобной проблемой.