6

I can't use Process("dir/e.exe") because e needs to be executed on its own directory, if not it can't access to its resources. But i receive an exception whenever i try to change the working directory:

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

These do not work, they give me exactly the same error. Any alternative?

EDIT: This is how looks my directory:

MyFolder:
|-app.jar
|-folderWithExe
  \-e.exe
Wlofrevo Kcast
  • 629
  • 1
  • 6
  • 11
  • I didn't get it. Do you want to set working directory of process to `dir` or do you want to launch process with `dir\file.exe`? Anyway, make sure you construct correct directory path. Maybe try to pass the full path and see where it gets you. – tkroman Sep 09 '13 at 19:00
  • The thing is, to make the executable work it must be called in its directory. You can't call it by "/path/to/exe/e.exe", but just "e.exe". So first i need to change the working directory to dir, and then call the exe. I can do it the way you described, by "dir\file.exe" but that's not what i want. The way i'm doing it right now throws me the mentioned exception. – Wlofrevo Kcast Sep 09 '13 at 19:06
  • Try using ProcessBuilder and setting working directory by its means: http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory(java.io.File) – tkroman Sep 09 '13 at 19:14
  • Thanks, but the problem persists – Wlofrevo Kcast Sep 09 '13 at 20:17
  • Maybe you could provide us with your directory structure, *please*? – tkroman Sep 09 '13 at 20:27
  • My bad! i'm going to write it. – Wlofrevo Kcast Sep 09 '13 at 20:39

3 Answers3

3

Okay, that's what I have (dirty code, just for demo purposes)

First, my directory structure (subdir is a subdirectory):

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

./subdir:
ls

Then my code:

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)

Let's see:

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

Is that what you expect from this code? Looks fine to me.

In general:

1) create ProcessBulder using new ProcessBuilder("application", "arg0", "arg1")

2) set its directory by "pb.directory(new File("path/to/dir"))"

3) get output or exit codes and so on with either Process or ProcessBuilder methods.

With Scala, you may use Source to make it a little bit faster to write (even more dirtier, but is good enough to play around):

scala.io.Source.fromInputStream(
  new ProcessBuilder("ls", "../")
  .directory(new File("subdir"))
  .start
  .getInputStream).getLines.mkString("\n")
tkroman
  • 4,811
  • 1
  • 26
  • 46
  • Thanks, but i fear it gives me the same problem. My code is `new ProcessBuilder("e.exe","./") .directory(new File(folderWithExe)) .start .waitFor` In my case, i want to execute the exe on subdir without moving the jar there. The exe needs to load some resources from there :/ – Wlofrevo Kcast Sep 09 '13 at 21:55
  • @WlofrevoKcast, where are the resources? If they are in that `folderWithExe`, than you just run your `new ProcessBuilder("e.exe") .directory(new File("folderWithExe"))`. If files are in the directory with your `jar`, than you may pass that path as an argument of `app.exe`. ANyway, that's technically correct way and if it doesn't work for you, provide me with you minimal complete piece of code that fails, please, so that I'll be sure that it's not mine or yours fault. – tkroman Sep 09 '13 at 22:08
  • Exactly, they are next to the exe, outside the jar. I cannot provide you more code, because the error is thrown in the code i posted before. That's it, that's all i have. Could be a problem with priviledges? `Caused by: java.security.PrivilegedActionException` but i have admin priviledges under windows xp. – Wlofrevo Kcast Sep 09 '13 at 22:52
  • it is important to note that to combine this solution with `scala.sys.process._` you need to import the `ProcessBuilder` like `java.lang.{ProcessBuilder => jProcessBuilder}` to prevent shadowing. Then keep using `jProcessBuilder`, as the scala `ProcessBuilder` is only a `trait`. – Sim Oct 08 '21 at 12:51
2

Try "./e.exe" or put "." on the path.

(Edited for clarity.)

Postmortem: the question is, what could you do to solve this quickly without SO? You really want a message that says: "Couldn't find the program to run after trying these locations..." Or even, perhaps under something like -Dprocess.debug, "There is a file named foo in the current directory but I can't run it because..."

For the record:

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

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

Showing that path matters:

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
  • 39,429
  • 2
  • 47
  • 129
  • Thanks som-snytt. I tried like you said, but it gives me the same error. I dont get what the problem is, probably something stupid. I tried with a different file, and it is unable to open it. The exactly error is "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)" – Wlofrevo Kcast Sep 09 '13 at 20:23
  • @WlofrevoKcast Probably. Try posting the stack trace, sometimes that makes it obvious exactly what is getting tested. Plus you're on XP. Is there an xp.stackexchange.com? Answer: Yes, but you have to log in over a 9600 baud modem with a text tty. (There is a stackapp for reading stackexchange from a tty.) – som-snytt Sep 09 '13 at 23:38
  • @WlofrevoKcast, why `./client.exe`? That's a `ProcessBuilder`'s job to specify environment details, you just put the name of app. Try just `client.exe` – tkroman Sep 10 '13 at 12:12
  • Ok som-snytt i'll post over there. Thanks everybody for helping me. – Wlofrevo Kcast Sep 10 '13 at 12:34
  • @cdshines If you cd into foo to run foo/client.exe, then you intend to run ./client.exe there, independent of $PATH. – som-snytt Sep 10 '13 at 19:28
  • @WlofrevoKcast So we're in a swing app (but not an applet?). I have an old jpeg resizer I wrote for emailing, I still start it from eclipse because drag'n'drop isn't enabled standalone (on Windows). This is ancient knowledge to me at this point, but I'll refresh myself on security enablement later on and let you know if I remember anything useful. – som-snytt Sep 10 '13 at 19:35
  • @som-snytt, but there is no `./` in my example and it still works. – tkroman Sep 10 '13 at 19:44
  • @cdshines I'm not omniscient or testing it on windows but I added my example on linux. – som-snytt Sep 10 '13 at 19:59
  • @som-snytt, that's the point. Look at what I've shown - no `./` needed. I copied `ls` brom `/bin` and got it working without `./` just as planned. I think, OP's problem is in his code, but since he doesn't want to share the details, that's up to him. – tkroman Sep 11 '13 at 14:33
0

This code should solve your problem

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