通过 w32-shell-execute 打开文件夹会冻结 Emacs

在 Windows 10 上的 Emacs, 通过w32-shell-execute 打开文件夹冻结 Emacs,测试过 Emacs 29 和 Emacs 30,都有问题。

重现步骤:

  1. 通过 emacs -Q 启动 Emacs
  2. M-: 执行下面的代码(用什么文件夹没关系),Emacs 就会卡死,无法进行任何操作,C-g也没法恢复:
(w32-shell-execute "open" "~/.emacs.d/")

其实受这个问题困扰很久了,最近给 Emacs 报Bug后,才发现可能和 PowerToys 有关。

因为 Eli Zaretskii 也没法重现我的问题,于是我到另外一台Windows 机器尝试重现,结果也没法重现了。然后想起来这机器没安装过 PowerToys,通过 winget install Microsoft.PowerToys 安装上PowerToys以后,再试就能重现问题了。

气人的是卸载 PowerToys 后也还是能重现。

想问问大家是不能重现这个问题? 还有如何把 PowerToys 卸载干净,恢复原来的设置,让 w32-shell-execute 可以正常使用?

目前的临时解决方法是第一个参数用 nil:

(w32-shell-execute nil "~/.emacs.d/")

参考 bug#67006: 30.0.50; w32-shell-execute will freeze Emacs on Windows 10

1 个赞

这个问题我也忍了很久了,每次尝试从 Emacs 内打开 explorer.exe 的时候都会卡死或者需要等很长一段时间

你安装了 PowerToys 吗?我不确定是否 100% 和它有关。

我之前好像是有时好用,有时不好用。最近是直接完全不能用了。

没有安装,确实是有时能用有时也不行

之前我使用下面的代码让 org-mode 在打开本地目录的 link 时启动资源管理器:

(require 'org)
(setq org-file-apps
      (cl-substitute-if '(directory . default) (lambda (x) (eq (car x) 'directory)) org-file-apps))

执行上面的代码,然后在 Emacs 的 org-mode buffer 内找一个本地目录链接并 C-c C-o,然后我的 Emacs 就卡住了,且无法通过 C-g 恢复。

我使用的是 Windows 10 22H2 19045.3570,Emacs 版本是官方提供的 GNU Emacs 29.1 (build 2, x86_64-w64-mingw32) of 2023-07-31

(注,以上操作均在 emacs -Q 下执行)

用的win10+emacs29.1,用以下函数打开文件夹很正常,而且试了 (w32-shell-execute nil "~/.emacs.d/")(w32-shell-execute "open" "~/.emacs.d/") 打开也是正常的。


(defun eye/open-explorer ()
  "Open explorer of current buffer directory."
  (interactive)
  (when (and default-directory (file-directory-p default-directory)
	     (eq system-type 'windows-nt))
    (let ((dir default-directory)
	  (explorer (replace-regexp-in-string "/" "\\\\" (executable-find "C:/Windows/SysWOW64/explorer")))
	  (command))
      (setq dir (encode-coding-string
		 (replace-regexp-in-string "/" "\\\\" dir) 'gbk-dos))
      (setq command (concat explorer " " dir))
      (shell-command command nil nil)
      (message command))
    ))
1 个赞

我用你的 eye/open-explorer 函数确实可以用。

很奇怪,试了一次 eye/open-explorer 后,(w32-shell-execute "open" "~/.emacs.d/") 也正常了。

我这个安装过 PowerToys 的机器又没法重现问题了。

新发现:

执行一次 下面的代码后

(executable-find "C:/Windows/SysWOW64/explorer")

再执行下面的代码就能正常打开文件夹了:

(w32-shell-execute "open" "C:/Windows/SysWOW64/")

然后就都正常了。

不过重启机器后,问题依旧。

msys2 下装的 emacs 也遇到类似的情况。las-bridge 怎么也调用不了 epc

也是这个函数 w32-shell-execute 问题?lsp-bridge 调用不了 epc 应该和 w32-shell-execute 不相关吧。 可以问问在 Windows 上用 lsp-bridge的大佬。

不是 w32-shell-execute 的问题,不过症状相似 :smile:

在 early-init.el 中加入下面的配置可以临时解决问题:

(add-to-list 'exec-path "C:/Windows/SysWOW64")

学到了,还有 w32-shell-execute 这样一个方法。之前都是通过 call-process-shell-command 直接开explorer 的。

不过主楼的这个问题在 win11 上不存在,powertoys 也是装了的。

多谢提供信息,可惜我的老机器都升级不了 Windows 11.

我主要是想用 embark 的一个打开外部文件的函数 embark-open-externally。按完 embark-act (我邦定到C-.) 后,接 x 就可以打开外部文件了。

1 个赞

我是win10 emacs 30 也安装了powertoy,但是没这个问题(emacs -Q和加载自己的配置时都没有),不过我对于exec-path也做了特殊处理,每次启动emacs的时候手动把exec-path用PATH的值覆盖。

我还没注意过这方面,Emacs 的exec-path 在Windows上不是直接继承了系统的 Path 和 当前用户的 Path吗?

msys2默认不继承windows的PATH变量,当从msys2的任意终端环境下启动emacs的时候,exec-path只会包含PATH的一部分,而且是只有一小部分。可以把msys2改成继承windows的PATH,但是每次大更新都会恢复默认,所以我干脆把几个关键路径用setenv硬编码然后覆盖exec-path

:+1: 用 msys2的终端启动确实是你说的这样的。

我用在 Windows下只是用 msys2编译 Emacs ,然后安装Emacs到其他位置。启动时是直接通过 runemacs.exe 启动,所以是默认继承了系统环境变量和用户环境变量。和你的情况正好相反,我需要手动加 msys2的环境路径(“C:/msys64/mingw64/bin” 和"C:/msys64/usr/bin")到 exec-path中,或者加到用户环境变量中。