【问题标题】:Scala run process on different working dirScala 在不同的工作目录上运行进程
【发布时间】:2013-09-13 05:01:34
【问题描述】:

我不能使用 Process("dir/e.exe") 因为 e 需要在它自己的目录上执行,否则它不能访问它的资源。但是每当我尝试更改工作目录时都会收到异常:

Process("e.exe", new File(dir)) 
Process("e.exe", new File("\"+ dir))
Process("e.exe", new File(new File(dir).getCanonicalPath()))  

Caused by: java.io.IOException: Cannot run program "e.exe" (in directory ".
\dir"): CreateProcess error=2, The system cannot find the file specified

这些不起作用,它们给了我完全相同的错误。有什么选择吗?

编辑:这是我的目录的外观:

MyFolder:
|-app.jar
|-folderWithExe
  \-e.exe

【问题讨论】:

  • 我没听懂。您想将进程的工作目录设置为dir 还是使用dir\file.exe 启动进程?无论如何,请确保构建正确的目录路径。也许尝试通过完整路径,看看它会把你带到哪里。
  • 问题是,要使可执行文件工作,必须在其目录中调用它。您不能通过“/path/to/exe/e.exe”来调用它,而只能通过“e.exe”来调用它。所以首先我需要将工作目录更改为dir,然后调用exe。我可以按照您描述的方式通过“dir\file.exe”进行操作,但这不是我想要的。我现在这样做的方式引发了我提到的异常。
  • 尝试使用 ProcessBuilder 并通过它的方式设置工作目录:docs.oracle.com/javase/7/docs/api/java/lang/…
  • 谢谢,但问题仍然存在
  • 也许您可以向我们提供您的目录结构,

标签: scala process ioexception


【解决方案1】:

好的,这就是我所拥有的(脏代码,仅用于演示目的)

首先,我的目录结构(subdir是子目录):

cdshines@v3700:~/test|⇒  ls -R
.:
log  pb.scala  subdir

./subdir:
ls

然后是我的代码:

import java.lang.ProcessBuilder
import java.io.File

val pb = new ProcessBuilder("ls", "../")
pb.directory(new File("subdir"))
pb.redirectOutput(ProcessBuilder.Redirect.to(new File("log")))
val p = pb.start
p.waitFor
println(p.exitValue)

让我们看看:

cdshines@v3700:~/test|⇒  scala pb.scala
0
cdshines@v3700:~/test|⇒  cat log
log
pb.scala
subdir

这是您对这段代码的期望吗?我觉得很好。

一般:

1) 使用new ProcessBuilder("application", "arg0", "arg1")创建 ProcessBulder

2) 通过"pb.directory(new File("path/to/dir"))"设置其目录

3) 使用ProcessProcessBuilder 方法获取输出或退出代码等。

在 Scala 中,您可以使用 Source 来加快编写速度(甚至更脏,但足够玩):

scala.io.Source.fromInputStream(
  new ProcessBuilder("ls", "../")
  .directory(new File("subdir"))
  .start
  .getInputStream).getLines.mkString("\n")

【讨论】:

  • 谢谢,但我担心它会给我同样的问题。我的代码是new ProcessBuilder("e.exe","./") .directory(new File(folderWithExe)) .start .waitFor 在我的情况下,我想在 subdir 上执行 exe 而无需将 jar 移到那里。 exe需要从那里加载一些资源:/
  • @WlofrevoKcast,资源在哪里?如果他们在那个folderWithExe 中,那么您只需运行您的new ProcessBuilder("e.exe") .directory(new File("folderWithExe"))。如果文件在您的jar 所在的目录中,那么您可以将该路径作为app.exe 的参数传递。无论如何,这在技术上是正确的方法,如果它不适合你,请向我提供失败的最少完整代码,以便我确定这不是我的错或你的错。
  • 没错,它们在 exe 旁边,在 jar 之外。我无法为您提供更多代码,因为错误是在我之前发布的代码中引发的。就是这样,这就是我所拥有的。可能是特权问题? Caused by: java.security.PrivilegedActionException 但我在 windows xp 下有管理员权限。
  • 请务必注意,将此解决方案与scala.sys.process._ 结合使用需要像java.lang.{ProcessBuilder => jProcessBuilder} 一样导入ProcessBuilder 以防止出现阴影。然后继续使用jProcessBuilder,因为scala ProcessBuilder 只是trait
【解决方案2】:

尝试“./e.exe”或输入“.”在路上。

(为清楚起见进行了编辑。)

事后分析:问题是,如果没有 SO,你能做些什么来快速解决这个问题?你真的想要一条消息说:“尝试这些位置后找不到要运行的程序......”或者甚至可能在-Dprocess.debug之类的东西下,“当前目录中有一个名为foo的文件,但是我无法运行它,因为...”

记录在案:

import sys.process._
import java.io.File

//System setSecurityManager new SecurityManager
Console println Process("./tester", new File("subdir")).lines.toList

表明路径很重要:

apm@mara:~/tmp/cdtest$ echo $PATH
/home/apm/go1.1/go/bin:/home/apm/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
apm@mara:~/tmp/cdtest$ vi runit.scala
apm@mara:~/tmp/cdtest$ scalam runit.scala
java.io.IOException: Cannot run program "tester" (in directory "subdir"): error=2, No such file or directory
apm@mara:~/tmp/cdtest$ grep tester runit.scala 
Console println Process("tester", new File("subdir")).lines.toList
apm@mara:~/tmp/cdtest$ PATH=$PATH:.
apm@mara:~/tmp/cdtest$ scalam runit.scala
List(file1, file2, tester)

【讨论】:

  • 感谢 som-snytt。我像你说的那样尝试过,但它给了我同样的错误。我不明白问题是什么,可能是一些愚蠢的事情。我尝试使用其他文件,但无法打开它。确切的错误是“Cannot run program "e.exe" (in directory ".\foldA"): CreateProcess error=2, The system cannot find the file specified at java.security.AccessController.doPrivileged(Native Method)”跨度>
  • @WlofrevoKcast 可能。尝试发布堆栈跟踪,有时这会使测试的内容一目了然。另外,您使用的是 XP。有 xp.stackexchange.com 吗?回答:可以,但您必须使用文本 tty 登录 9600 波特率调制解调器。 (有一个 stackapp 用于从 tty 读取 stackexchange。)
  • @WlofrevoKcast,为什么是./client.exe?那是ProcessBuilder 的工作来指定环境细节,你只需输入应用程序的名称。试试client.exe
  • 好的 som-snytt 我会在那里发帖。谢谢大家帮助我。
  • @cdshines 如果你 cd 进入 foo 运行 foo/client.exe,那么你打算在那里运行 ./client.exe,独立于 $PATH。
【解决方案3】:

这段代码应该可以解决你的问题

    ProcessBuilder builder = new ProcessBuilder(
            "cmd.exe", "/c", "cd \"D:\\folder\\With\\Exe\" && e.exe");
    Process p = builder.start();
    p.waitFor();

【讨论】:

    猜你喜欢
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 2018-04-25
    • 2011-04-15
    • 2016-04-04
    • 1970-01-01
    相关资源
    最近更新 更多