Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Ruby > [Ruby] Запуск документа ассоциированной программой в Windows


Автор: Romtek 09.01.13, 21:11
В Руби программе требуется запустить программу для любого типа документа (mp3, html, pdf, ...) с ожиданием результата от запущенного процесса.

Проблема заключается в том, что программа запускает процесс без ожидания окончания процесса, что недопустимо. Хочу контролировать результат успешности выполнения процесса, чтобы потом, в случае успеха, скопировать документ в хранилище.

Программа должна работать в Windows (XP и может в других).

Пробовал такой вариант:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    document = ARGV[0]
     
    if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin|wince|emx/
      res = system "rundll32.exe url.dll,FileProtocolHandler #{document}"
     
      puts "OK" if res
    end

потом такой, как советовалось в одном форуме, с помощью Thread:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    document = ARGV[0]
     
    if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin|wince|emx/
      command = Thread.new do
        res = system "rundll32.exe url.dll,FileProtocolHandler #{document}"
      end
      command.join
     
      puts "OK" if res
    end
     
    puts "OK" if res


Добавлено
Ruby 1.9.2

Автор: deil 10.01.13, 07:43
Оффтоп: очевидно, что оба исходных кода идентичны :)

Добавлено
Вообще у меня есть подозрение, что виноват rundll, который как раз и не дожидается возврата из ассоциированного приложения.

Автор: Romtek 10.01.13, 12:01
Цитата deil @
оба исходных кода идентичны
Без Thread.new и с ним. Так что не идентичны.


Цитата deil @
у меня есть подозрение, что виноват rundll, который как раз и не дожидается возврата из ассоциированного приложения
Кстати, проверил сейчас в Линуксе:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    res=nil; command = Thread.new { res =system "gnome-open list.txt" }; command.join


Открывается gedit и в консоли тут же сообщается:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    => #<Thread:0xa030e44 dead>

и res возвращает "успех".

Автор: deil 15.01.13, 19:28
Цитата Romtek @
Цитата deil @
оба исходных кода идентичны
Без Thread.new и с ним. Так что не идентичны.


Цитата deil @
у меня есть подозрение, что виноват rundll, который как раз и не дожидается возврата из ассоциированного приложения
Кстати, проверил сейчас в Линуксе:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    res=nil; command = Thread.new { res =system "gnome-open list.txt" }; command.join


Открывается gedit и в консоли тут же сообщается:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    => #<Thread:0xa030e44 dead>

и res возвращает "успех".

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

Автор: Romtek 15.01.13, 22:42
То что результат выполнения одинаков я и так знаю. Мне бы решить вопрос насчёт синхронного вызова процесса.
Повсюду пишут, что метод system является синхронным. А значит, он должен дожидаться окончания процесса. Только мне не понять почему это не срабатывает.

Автор: Мяут-Настоящий 16.01.13, 04:56
Возможно имеет смысл использовать FFI и дергать напрямую WinAPI-шные функции?

Например об этом говорят здесь:
http://habrahabr.ru/post/142172/
и здесь: http://stackoverflow.com/questions/1107601...dowex-from-ruby

ЗЫ. В питоне вообще есть pywin32 8-)

Автор: Romtek 17.01.13, 10:44
В общем, написал я экспериментальную proof of concept реализацию на C#, взяв за основу примеры на http://www.dotnetperls.com/process-start
. Делает всё как мне и надо, с возвратом кода ошибки (если приложение неудачно закрывается). Позже попробую перевести на WinAPI и затем уже приделать привязку к Руби при помощи FFI или без.
Хотя, ещё остаётся вариант вызывать как внешнюю программу системным вызовом. Пока надо подумать как лучше сделать.

P.S. В свободное время пытаюсь воплотить разные идеи.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)