Как запустить фоновый процесс из popen под win64?

Ссылка скопирована
1 ответ

Несколько странная задача:
Есть библиотека на C под Windows 64-bit, в которой есть функцияprocess(char *command) которая запускает процесс следующим образом:

f = popen(command, "r"); fread(f, ......); pclose(f);

f = popen(command, "r"); fread(f, ......); pclose(f);

Соотвественно, command будет выполнена через cmd.exe

Задача следующая: запустить некое приложение myapp, чтобы оно запустилось после(!) того, как произойдёт возврат из функции process.

Грубо говоря, нужно запустить фоновый процесс, а из него приложение myapp с задержкой.

Пробовал 3 метода:

  1. Передавать в качестве command такую строку start "" cmd /c "timeout 3 && myapp" -- не работает, всё равно происходит ожидание, так как cmd не завершается до окончания запущенной задачи
  2. Запускать powershell, а из него Start-Job -- не работает, powershell не завершается до окончания фоновой задача, т.е. всё равно происходит ожидание
  3. Использовать schtasks /sc once -- как-то работает, но запускать может только в целое число минут, нельзя указать секунды

Условие такое: библеотеку менять нельзя, запускать процесс можно только через process().
Винда голая, есть только базовые приложения.

Дополнительно:

Что возвращает (какой тип) функция process из этой библиотеки?

  • MVV, тип void
  • Ищите по имени процесса его хэндл. Потом через WaitForSingleObject дожидаетесь его завершения.
  • Александр Ананьев, Нужно как раз не ждать завершения.
  • redcircle, так, а в чем проблема запустить новый процесс из другого потока?
  • Александр Ананьев, API только одно: функция process, описанная в условии. Считайте, что другого API нет.
    При этом строку command в качестве параметра можно передавать любую.
  • redcircle, т.е. надо через process запусить две программы? А этот process может запустить bat скрипт?
  • redcircle,

    Нужно как раз не ждать завершения.

    На сколько я понимаю, функция process запускает процесс и завершается после завершения процесса, т.к. в конце дескриптор канала закрывается. Поэтому после завершения функции можно считать, что и запущенного процесса уже нет.
    Думаю можно сделать примерно так: в process запускать батник примерно следующего содержания (схематично):

    :: process1.bat start "" cmd.exe /c process2.bat program1.exe

    :: process1.bat start "" cmd.exe /c process2.bat program1.exe

    Батник сначала запускает второй батник (process2.bat), причем второй батник должен запуститься в другом процессе cmd.exe и в другом консольном окне и не нужно ждать завершения второго батника, поэтому второй батник запускаем через start.
    После запуска второго батника стартуем тот процесс, который нужно стартовать изначально (programm1.exe)

    :: process2.bat timeout /t 2 program2.exe

    :: process2.bat timeout /t 2 program2.exe

    Второй батник process2.bat сначала просто ждет заданное время (у меня 2 секунды), это нужно, чтобы первый батник успел запустить приложение program1.exe. Затем стартует ваше второе приложение, которое вам надо запустить после первого. Правда есть шанс, что пока стартанет второе приложение, первое уже закроется :)

  • Александр Ананьев, Запустить надо одну, но так чтобы она запустилась после выхода из process (i.e. после pclose). Можно запускать вспомогательные программы, батники, итп
  • res2001, Проверил, нет, так не работает, process ожидает завершения первого батника.

    При этом мне только одну программу надо запускать, а не 2.

    Если это был бы Linux, то всё работало бы, если бы запускал такую строчку: "nohup ./script.sh &"

    Где script.sh:

    #!/bin/bash sleep 3 myapp

    #!/bin/bash sleep 3 myapp

    С Windows такое почему-то не работает, cmd.exe всё равно дожидается выполения фоновых процессов почему-то

  • redcircle,

    При этом мне только одну программу надо запускать, а не 2.

    Одну вы запускаете изначально для чего вызываете функцию process(). Вторую вы хотите запустить параллельно первой.
    Если вторую надо запустить после возврата из первой, тогда все упрощается:

    program1.exe start "" program2.exe

    program1.exe start "" program2.exe

    С Windows такое почему-то не работает, cmd.exe всё равно дожидается выполения фоновых процессов почему-то

    В винде, если запускать программу через start, то ожидания завершения процесса не происходит.
    Для примера, запустите в консоли это:
    (start "" cmd.exe /k) && timeout /t 30

  • res2001, Из консоли если это запускать, поведение одно, а если из popen/pclose вызывать -- другое.

    В вашем случае popen запустит cmd /c '(start "" cmd.exe /k) && timeout /t 30'
    И несмотря на вроде как параллельный запуск второго cmd.exe через start, первый cmd.exe почему-то не завершается, пока не завершится второй cmd.exe вызыванный через start. Уже проверял это не один десяток раз.

    Update: либо альтернативный вариант -- первый cmd всё-таки завершается, но pclose почему-то ждёт и второй cmd.
    Других объяснений такому поведению я не вижу

  • redcircle,

    И несмотря на вроде как параллельный запуск второго cmd.exe через start, первый cmd.exe почему-то не завершается, пока не завершится второй cmd.exe вызыванный через start. Уже проверял это не один десяток раз.

    Тогда попутные вопросы по приведенному примеру с
    cmd /c '(start "" cmd.exe /k) && timeout /t 30'
    После запуска второго окна cmd команда timeout стартует сразу? Что происходит после того как timeout закончится? Остается висеть первое окно cmd?
    Если добавить еще команду exit после timeout будет так же?

    Вы писали, что функция process() выполняет команду в cmd.exe, т.е. судя по всему она сама запускает cmd.
    Передав в process() вышеприведенную строку в итоге, видимо получилось что-то вроде:

    cmd /c cmd /c '(start "" cmd.exe /k) && timeout /t 30'

    cmd /c cmd /c '(start "" cmd.exe /k) && timeout /t 30'

    Так что, возможно, одна cmd /c лишняя.

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

  • redcircle,

    Нужно как раз не ждать завершения.

    &&

    а из него приложение myapp с задержкой.

    winapi в помощь...
    тебе даже батники не нужны. нужны мозги и умение читать МСДН.. (ты же под виндой хочешь?..
    то что работает в линукс, далеко не всегда будет совпадать с решениями под винду..
    удачи..

  • #, winapi нельзя использовать по условиям задачи
  • redcircle, да ладно )))
    директивы условной компиляции - не, не слышал?
    ок. допустим. бат можно?.. а это не sh...
    мутно все...
    кури start
    start /white
    да и тупую задержку в коде...
  • по условиям задачи учителю по башке и сделайте через
    https://learn.microsoft.com/en-us/dotnet/api/syste...
    [System.Diagnostics.ProcessStartInfo] $si = new-object System.Diagnostics.ProcessStartInfo $si.RedirectStandardOutput = $false $si.WorkingDirectory = $process_workdir $si.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden $si.ErrorDialog = $true $si.FileName = '....' $si.Arguments = '....'  $x = [System.Diagnostics.Process]::Start($si) while (-not $x.HasExited) {   start-sleep -seconds 1 }

    [System.Diagnostics.ProcessStartInfo] $si = new-object System.Diagnostics.ProcessStartInfo $si.RedirectStandardOutput = $false $si.WorkingDirectory = $process_workdir $si.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden $si.ErrorDialog = $true $si.FileName = '....' $si.Arguments = '....' $x = [System.Diagnostics.Process]::Start($si) while (-not $x.HasExited) { start-sleep -seconds 1 }

    в деталях разберитесь это общее место

  • Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Стас DB Ответ

    Для запуска фонового процесса из popen под Windows 64-bit вам потребуется использовать специальные функции и подходы.

    Во-первых, вам нужно учитывать, что в Windows нет нативной поддержки для фоновых процессов, как в UNIX-подобных системах. Однако, вы можете добиться аналогичного эффекта, используя специфические функции Windows.

    Прежде всего, вам нужно создать отдельный поток для выполнения команды popen. Можно воспользоваться функцией `CreateThread` из библиотеки Windows API для создания нового потока. В этом потоке вы можете вызвать функцию `popen` для выполнения команды.

    Пример кода на языке PHP с использованием функций Windows API:

     

    В этом примере мы используем команду `start /B`, которая запускает процесс в фоновом режиме. После вызова `popen` мы закрываем поток с помощью `pclose`.

    Обратите внимание, что использование функций Windows API требует знания специфики работы с ними, поэтому убедитесь, что вы понимаете, как они работают, прежде чем применять их в своем коде.

    Надеюсь, данное решение поможет вам запустить фоновый процесс из popen под Windows 64-bit. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно