org-mode打开windows 外部文件链接的一个bug?

windows10, emacs 27.2(msys64),orgmode 9.4.4。在orgmode中,打开本地文件链接,第一次能打开,第二次会直接导致emacs死掉。经过排查发现 Emacs -Q下也会出现这种问题。

  1. Emacs -Q
  2. 执行下面,问题复现:

(w32-shell-execute "open" "C:/temp.txt") ;; 此处第一次执行没问题,第二次emacs直接卡死,需要结束任务

  1. w32-shell-execute 在orgmode中是用于:
(defconst org-file-apps-windowsnt
  (list '(remote . emacs)
	(cons 'system (lambda (file _path)
			(with-no-warnings (w32-shell-execute "open" file))))
	(cons t (lambda (file _path)
		  (with-no-warnings (w32-shell-execute "open" file)))))
  "Default file applications on a Windows NT system.
The system \"open\" is used for most files.
See `org-file-apps'.")
  1. 能否麻烦哪位相同环境的检查下,看能否复现问题

另外,无意中发现,将 (w32-shell-execute "open" "C:/temp.docx") 改为 (w32-shell-execute 'open "C:/temp.docx") 就能解决问题(包括在 Emacs -Q里)。


但此变量是 defconst org-file-apps-windowsnt 定义的const,不知如何hack。

同样win10,我用的非msys64的27.2,设置org-file-apps,打开docx文件没有这个问题。

defconst不能改,但是你可以改使用这个变量的函数,重定义一下 org–file-default-apps

(defun org--file-default-apps ()
  "Return the default applications for this operating system."
  (pcase system-type
    (`darwin org-file-apps-macos)
    (`windows-nt org-file-apps-windowsnt) ;; 替换 org-file-apps-windowsnt
    (_ org-file-apps-gnu)))

感谢帮忙,刚刚又试了下,不只word文件,普通 txt 文件也会同样问题。

设置org-file-apps,打开docx文件没有这个问题

这里不用设置,我是在 scratch 里面试的,第一次能打开,第二次就没反映了,死掉: law

也许是哪次更新或者哪个软件的冲突。先这样忍着用段时间,过段时间换28试试。

我用 consult-file-externally 打开外部文件,从来没遇到问题。打开后,应该就跟 Emacs 没关系了。

orgmode 中打开链接最终是用 w32-shell-execute这个,看后是调用 C 语言的了。不知道啥原因卡死。杀毒软件换了 360、火绒、默认三个都不行。

Consult-file-externally 也是用你说的这个函数:

(defun consult-file-externally (file)
  "Open FILE externally using the default application of the system."
  (interactive "fOpen externally: ")
  (if (and (eq system-type 'windows-nt)
           (fboundp 'w32-shell-execute))
      (w32-shell-execute "open" file)
    (call-process (pcase system-type
                    ('darwin "open")
                    ('cygwin "cygstart")
                    (_ "xdg-open"))
                  nil 0 nil
                  (expand-file-name file))))

估计是你系统的其他软件冲突造成的。

唉,这就难排查了。 奇怪的是:把 (w32-shell-execute “open” file) 中的字符串换成 'open,它又正常。

windows下的org-mode可以用

[[file+sys:F:/word.docx]]

点击或者C-c C-o都能调用系统默认方式打开。

一样的问题。目前用scoop装的emacs 28.0.95,之前的版本也照样。org应该是9.5。希望这个问题能够解决。

你那也会死掉?我还以为单是我的问题

直接编译一个 Emacs 29 吧,我这 29 一切正常。

对,不是今早就是昨天发生的,之前应该也发生过,记不大清了

最近几天我也碰到了这个问题,最开始是用这个命令打开某个路径出的问题,感觉莫名奇妙

((string-equal system-type "windows-nt")
       (w32-shell-execute "open" default-directory))

去查看emacs的调用线程好像是跟gdiplus里卡死有关系,但我不知道该怎么解决,最后猛然发现李杀大佬最新的xah-show-in-desktop把这段给改掉了

((string-equal system-type "windows-nt")
      (shell-command (format "PowerShell -Command Start-Process Explorer -FilePath %s" (shell-quote-argument default-directory)))
      ;; todo. need to make window highlight the file
      )

那么看来这个函数很可能是有问题的,计划是把.emacs.d底下所有的w32-shell-execute全替换掉,只能先这样了…

看了一下对应的c源代码w32fns.c 里面描述的参数列表,会不会 (w32-shell-execute 'open file) 实际调的是 (w32-shell-execute nil file),也就是默认的调用情况?

DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
       doc: /* Get Windows to perform OPERATION on DOCUMENT.
This is a wrapper around the ShellExecute system function, which
invokes the application registered to handle OPERATION for DOCUMENT.

OPERATION is either nil or a string that names a supported operation.
What operations can be used depends on the particular DOCUMENT and its
handler application, but typically it is one of the following common
operations:

 \"open\"    - open DOCUMENT, which could be a file, a directory, or an
	       executable program (application).  If it is an application,
	       that application is launched in the current buffer's default
	       directory.  Otherwise, the application associated with
	       DOCUMENT is launched in the buffer's default directory.
 \"opennew\" - like \"open\", but instruct the application to open
	       DOCUMENT in a new window.
 \"openas\"  - open the \"Open With\" dialog for DOCUMENT.
 \"print\"   - print DOCUMENT, which must be a file.
 \"printto\" - print DOCUMENT, which must be a file, to a specified printer.
	       The printer should be provided in PARAMETERS, see below.
 \"explore\" - start the Windows Explorer on DOCUMENT.
 \"edit\"    - launch an editor and open DOCUMENT for editing; which
	       editor is launched depends on the association for the
	       specified DOCUMENT.
 \"find\"    - initiate search starting from DOCUMENT, which must specify
	       a directory.
 \"delete\"  - move DOCUMENT, a file or a directory, to Recycle Bin.
 \"copy\"    - copy DOCUMENT, which must be a file or a directory, into
	       the clipboard.
 \"cut\"     - move DOCUMENT, a file or a directory, into the clipboard.
 \"paste\"   - paste the file whose name is in the clipboard into DOCUMENT,
	       which must be a directory.
 \"pastelink\"
	   - create a shortcut in DOCUMENT (which must be a directory)
	       the file or directory whose name is in the clipboard.
 \"runas\"   - run DOCUMENT, which must be an executable file, with
	       elevated privileges (a.k.a. \"as Administrator\").
 \"properties\"
	   - open the property sheet dialog for DOCUMENT.
 nil       - invoke the default OPERATION, or \"open\" if default is
	       not defined or unavailable.

DOCUMENT is typically the name of a document file or a URL, but can
also be an executable program to run, or a directory to open in the
Windows Explorer.  If it is a file or a directory, it must be a local
one; this function does not support remote file names.

If DOCUMENT is an executable program, the optional third arg PARAMETERS
can be a string containing command line parameters, separated by blanks,
that will be passed to the program.  Some values of OPERATION also require
parameters (e.g., \"printto\" requires the printer address).  Otherwise,
PARAMETERS should be nil or unspecified.  Note that double quote characters
in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\".

Optional fourth argument SHOW-FLAG can be used to control how the
application will be displayed when it is invoked.  If SHOW-FLAG is nil
or unspecified, the application is displayed as if SHOW-FLAG of 10 was
specified, otherwise it is an integer between 0 and 11 representing
a ShowWindow flag:

  0 - start hidden
  1 - start as normal-size window
  3 - start in a maximized window
  6 - start in a minimized window
 10 - start as the application itself specifies; this is the default.  */)

我试过调用也不会卡死

(w32-shell-execute nil "d:/new.txt")

是的,这个调用我这也不会卡死。

这句我这也卡死。在 emacs -Q 下。