I'm trying to run QGIS from the command-line on Windows. QGIS provides a batch file for this, "C:\Program Files\QGIS 3.20.3\bin\qgis.bat". When I run this from within Emacs shell, the load hangs when QGIS tries to load it's Python interpreter.

To reproduce, start a new shell in Emacs with M-x shell and call "C:\Program Files\QGIS 3.20.3\bin\qgis.bat". If instead you first call start (to load a new prompt) and then call "C:\Program Files\QGIS 3.20.3\bin\qgis.bat" in that, QGIS loads.

Looking at qgis.bat, it calls several other batch files and also sets many environment variables. My guess is that some necessary variables aren't set when called directly from shell.

Is there a way to call the batch directly from Emacs shell so that QGIS loads?

  • When I enter M-x shell in emacs, I'm in bash. What are you in? cmd /C qgis.bat at the shell prompt would do it, but likely you still will get the popped up cmd window. GNU Emacs 29.0.50 (build 1, x86_64-w64-mingw32) of 2021-10-12 Windows 10 Pro Oct 19, 2021 at 19:08
  • Yes, I'm in cmd. I'm not running from MSYS2 or Cygwin or mingw. Oct 19, 2021 at 19:10
  • You set explicit-shell-file-name or shell-file-name to cmd.exe? Because otherwise, you are not at the DOS prompt. You are in a shell produced by Emacs' cmdproxy.exe. Oct 19, 2021 at 19:14
  • No, I have not set those. Indeed, shell-file-name is "C:/emacs-27.1-x86_64/libexec/emacs/27.1/x86_64-w64-mingw32/cmdproxy.exe". (I guess at some level I am running mingw). Oct 19, 2021 at 19:21
  • That's your answer. start is just running cmd.exe and that's why it works. Oct 19, 2021 at 19:23

1 Answer 1


This is a workaround to run, kill, and rerun QGIS:

(defun rerun-qgis ()
  ;; kill any running instance of QGIS
  (shell-command "taskkill /f /fi \"IMAGENAME eq qgis-bin.exe\"")
  ;; kill any lingering command window
  (shell-command "taskkill /f /t /fi \"WINDOWTITLE eq \\qgis\\ \"")
  ;; start QGIS; opens a command window which isn't needed beyond the
  ;; load. Retitle it "\qgis\" (because shell quoting is unfun and
  ;; that's what I got to work) so that we can kill it directly with
  ;; taskkill after load.
  (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "\"qgis\"" "cmd.exe" "/K" "C:\\Program Files\\QGIS 3.20.3\\bin\\qgis.bat")))
    (set-process-query-on-exit-flag proc nil))
  ;; assume qgis loads in 3 seconds and kill the lingering command
  ;; window; I couldn't get a sentinel to work
  (run-at-time "3 sec" nil #'(lambda () (shell-command "taskkill /f /fi \"WINDOWTITLE eq \\qgis\\ \""))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.