Windows下eXist-db用XQuery process:execute执行外部程序报错排查
解决eXist-db中调用外部Windows程序的路径问题
你遇到的核心问题很明确:eXist-db的process:execute函数需要的是本地文件系统的绝对路径,而不是eXist数据库内部的/db/路径。Windows的CreateProcess根本无法识别eXist的数据库存储路径,所以才会报“找不到文件”的错误。
为什么你的代码不行?
你传入的/db/apps/execute-test/resources/RTIMaker/webGLRtiMaker.exe是eXist内部的资源路径,这个路径只在eXist的数据库上下文里有效,Windows系统完全不知道这个位置对应的磁盘文件在哪里。另外,你用<stdin>传递程序参数的方式也是错误的——stdin是给程序输入标准输入的,不是用来传命令行参数的。
解决方案一:直接使用本地文件系统路径(推荐)
把webGLRtiMaker.exe放在Windows本地的某个目录下(比如C:\exist-external-tools\RTIMaker\webGLRtiMaker.exe),然后用这个本地绝对路径调用process:execute,同时正确传递命令行参数:
xquery version '3.1'; import module namespace process="http://exist-db.org/xquery/process" at "java:org.exist.xquery.modules.process.ProcessModule"; (: 本地文件系统中的exe路径,注意用转义的反斜杠或者正斜杠 :) declare variable $exe-path := 'C:/exist-external-tools/RTIMaker/webGLRtiMaker.exe'; (: 命令行参数,用数组传递 :) declare variable $args := ('C:/exist-apps/test-project/images/image1.rti', '-q', '90'); (: 工作目录也要用本地路径 :) declare variable $options := <options> <workingDir>C:/exist-apps/test-project/images</workingDir> </options>; process:execute($exe-path, $options, $args)
解决方案二:从eXist数据库导出exe到本地临时目录
如果必须把exe存在eXist数据库里,那需要先把二进制文件导出到Windows的临时目录,再调用本地路径:
xquery version '3.1'; import module namespace process="http://exist-db.org/xquery/process" at "java:org.exist.xquery.modules.process.ProcessModule"; import module namespace xmldb="http://exist-db.org/xquery/xmldb"; import module namespace file="http://exist-db.org/xquery/file"; (: 从数据库获取exe的二进制内容 :) declare variable $db-exe-path := '/db/apps/execute-test/resources/RTIMaker/webGLRtiMaker.exe'; declare variable $exe-binary := xmldb:binary-get($db-exe-path); (: 创建本地临时目录,比如系统临时目录下的RTIMaker文件夹 :) declare variable $temp-dir := file:path-to-native(file:system-temp-dir() || '/RTIMaker'); file:create-dir($temp-dir); declare variable $local-exe-path := $temp-dir || '/webGLRtiMaker.exe'; (: 将二进制内容写入本地文件 :) file:write-binary($local-exe-path, $exe-binary); (: 执行外部程序,参数和工作目录用本地路径 :) declare variable $args := ('C:/exist-apps/test-project/images/image1.rti', '-q', '90'); declare variable $options := <options> <workingDir>C:/exist-apps/test-project/images</workingDir> </options>; let $result := process:execute($local-exe-path, $options, $args) (: 可选:执行完成后删除临时文件和目录 :) return ( $result, file:delete($local-exe-path), file:delete($temp-dir) )
额外注意事项
- 权限问题:运行eXist-db的Windows用户需要有:执行该exe的权限、读写临时目录的权限、读写工作目录的权限。
- 参数传递:命令行参数一定要用
process:execute的第三个参数(数组形式),或者在<options>里用<arguments>节点传递,不要用<stdin>。 - 路径格式:Windows路径可以用正斜杠
/,或者转义的反斜杠\\,避免直接用单个反斜杠导致转义错误。
内容的提问来源于stack exchange,提问作者creativeDev
相关产品推荐
相关产品推荐

