Почему при запуске .bat файла, созданного с помощью PyInstaller, не выполняется команда start?

Я собрал свой проект, используя команду pyinstaller --onefile --clean main.py, и получил файл main.exe. Этот файл проверяет наличие обновлений на сервере: если обновление доступно, он скачивает main_new.exe, создает и запускает .bat файл, который удаляет main.exe и переименовывает main_new.exe в main.exe, а также должен запускать main.exe для автоперезапуска программы. Однако, при выполнении .bat файла происходит удаление и переименование, но программа не запускается. Вот код, который я использую:

```python
def get_script_path():
    script_path = os.path.abspath(sys.argv[0])
    script_directory = os.path.dirname(script_path)
    return script_directory

with open('autoupdater.bat', 'w', encoding='utf-8') as file:
    file.write(rf"""
timeout /t 2 /nobreak
del "{get_script_path()}\main.exe" || echo Ошибка удаления main.exe >> error.log
rename "{get_script_path()}\main_new.exe" "main.exe" || echo Ошибка переименования main_new.exe >> error.log
start /d "{get_script_path()}\main.exe" {get_script_path()}\main.exe
""")
process = subprocess.Popen(
    ['autoupdater.bat'],
    creationflags=subprocess.CREATE_NEW_CONSOLE
)
sys.exit()
```

При этом, если заменить Popen на run, программа работает, но в этом случае возникнут проблемы с заменой main.exe. Как правильно настроить выполнение .bat файла, чтобы он корректно запускал main.exe после обновления?
  • 5 сентября 2024 г. 19:32
Ответы на вопрос 2
Ваш код выглядит в целом правильно, но есть несколько моментов, которые могут вызывать проблемы с запуском `main.exe` из вашего `.bat` файла. Изменения, которые помогут пожарить это отсутствие запуска, следующими шагами:

1. **Используйте оператор `start` правильно**: При использовании команды `start` в `.bat` файле нужно указывать имя задачи (title), иначе она может не сработать, так как Windows ожидает его. Например, вы можете указать имя текущей программы:

   ```bat
   start "" "{get_script_path()}\main.exe"
   ```

   Обратите внимание, что я добавил пустую строку `""`, которая представляет собой title для нового окна.

2. **Путь к исполняемому файлу**: Убедитесь, что путь к `main.exe` правильно передается в команду `start`. Ваша формулировка выглядит правильно, но вам нужно убедиться, что в этот момент `main.exe` уже существует.

3. **Задержки**: Есть вероятность, что `autoupdater.bat` завершается слишком быстро и не имеет времени для завершения предыдущих команд (удаление и переименование). Вы уже используете `timeout`, что является хорошим подходом, но вы также можете попробовать использовать дополнительную задержку перед командой `start`.

Изменяя ваше `autoupdater.bat` на что-то вроде этого:

```bat
timeout /t 2 /nobreak
del "{get_script_path()}\main.exe" || echo Ошибка удаления main.exe >> error.log
rename "{get_script_path()}\main_new.exe" "main.exe" || echo Ошибка переименования main_new.exe >> error.log
timeout /t 1 /nobreak
start "" "{get_script_path()}\main.exe"
```

Таким образом, вы гарантируете, что удаление и переименование произойдет до запуска новой версии вашего приложения.

4. **Используйте `cmd.exe /c` при запуске .bat**: Если даже после этих изменений `main.exe` не будет запускаться, вы можете попробовать изменить способ запуска `.bat` файла. Запустите `cmd.exe` с параметром `/c`, чтобы останавливать выполнение после завершения, что может помочь вам избежать конфликтов:

```python
process = subprocess.Popen(['cmd.exe', '/c', 'autoupdater.bat'],
                           creationflags=subprocess.CREATE_NEW_CONSOLE)
```

Сделав эти правки, вы должны быть в состоянии корректно запускать `main.exe` после обновления. Убедитесь, что все пути прописаны правильно, и файлы доступные на диске в момент выполнения.
Пути указаны точно правильно, оно просто не хочет start выполнять...
Похожие вопросы