www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - regarding spawnProcess and parameters in Windows

reply Hugo Florentino <hugo acdam.cu> writes:
Hello,

I am trying to do a small launcher for a Windows application which (in 
order to be portable) requires a specific parameter, and I am getting 
this error when I try to run it in Windows 7 SP1:

"std.process.ProcessException std\process.d(518): Failed to spawn new 
process (Access denied.)"

This is the code I am trying to use:

import std.stdio, std.file, std.path, std.string, std.process;

static auto appname = "myapp";

int main(string[] args) {
   auto appath = dirName(thisExePath());
   auto appexe = buildPath(appath, appname ~ ".exe");
   auto appini = buildPath(appath, appname ~ ".ini");
   auto applaunchpars = format(`"%s" /ini="%s"`, appexe, appini);
   if (exists(appexe)) {
     auto appPid = spawnProcess(applaunchpars, ["" : ""], 
Config.suppressConsole);
     scope(failure) return -1;
   }
   return 0;
}

The ugly ["" : ""] hack is because I haven't been able to invoke 
spawnProcess otherwise, at least withouth specifying stdin and stdout 
(which I don't really need right now). Actually, I was thinking in 
making my own wrapper for ShellExecuteA (I don't find spawnProcess 
particularly intuitive), but I would prefer "the D way".

Anyway, Where could the problem be?

Regards, Hugo
Dec 15 2013
parent reply "Danny Arends" <Danny.Arends gmail.com> writes:
On Sunday, 15 December 2013 at 23:14:45 UTC, Hugo Florentino 
wrote:
 Hello,

 I am trying to do a small launcher for a Windows application 
 which (in order to be portable) requires a specific parameter, 
 and I am getting this error when I try to run it in Windows 7 
 SP1:

 "std.process.ProcessException std\process.d(518): Failed to 
 spawn new process (Access denied.)"

 This is the code I am trying to use:

 import std.stdio, std.file, std.path, std.string, std.process;

 static auto appname = "myapp";

 int main(string[] args) {
   auto appath = dirName(thisExePath());
   auto appexe = buildPath(appath, appname ~ ".exe");
   auto appini = buildPath(appath, appname ~ ".ini");
   auto applaunchpars = format(`"%s" /ini="%s"`, appexe, appini);
   if (exists(appexe)) {
     auto appPid = spawnProcess(applaunchpars, ["" : ""], 
 Config.suppressConsole);
     scope(failure) return -1;
   }
   return 0;
 }

 The ugly ["" : ""] hack is because I haven't been able to 
 invoke spawnProcess otherwise, at least withouth specifying 
 stdin and stdout (which I don't really need right now). 
 Actually, I was thinking in making my own wrapper for 
 ShellExecuteA (I don't find spawnProcess particularly 
 intuitive), but I would prefer "the D way".

 Anyway, Where could the problem be?

 Regards, Hugo
You need to pass the INI parameters separately see: http://dlang.org/phobos/std_process.html#.spawnProcess spawnProcess([appexe,format("/INI=%s")], ["",""], Config.suppressConsole); Gr, Danny Arends http://www.dannyarends.nl
Dec 15 2013
parent reply "Danny Arends" <Danny.Arends gmail.com> writes:
On Monday, 16 December 2013 at 00:59:51 UTC, Danny Arends wrote:
 On Sunday, 15 December 2013 at 23:14:45 UTC, Hugo Florentino 
 wrote:
 Hello,

 I am trying to do a small launcher for a Windows application 
 which (in order to be portable) requires a specific parameter, 
 and I am getting this error when I try to run it in Windows 7 
 SP1:

 "std.process.ProcessException std\process.d(518): Failed to 
 spawn new process (Access denied.)"

 This is the code I am trying to use:

 import std.stdio, std.file, std.path, std.string, std.process;

 static auto appname = "myapp";

 int main(string[] args) {
  auto appath = dirName(thisExePath());
  auto appexe = buildPath(appath, appname ~ ".exe");
  auto appini = buildPath(appath, appname ~ ".ini");
  auto applaunchpars = format(`"%s" /ini="%s"`, appexe, appini);
  if (exists(appexe)) {
    auto appPid = spawnProcess(applaunchpars, ["" : ""], 
 Config.suppressConsole);
    scope(failure) return -1;
  }
  return 0;
 }

 The ugly ["" : ""] hack is because I haven't been able to 
 invoke spawnProcess otherwise, at least withouth specifying 
 stdin and stdout (which I don't really need right now). 
 Actually, I was thinking in making my own wrapper for 
 ShellExecuteA (I don't find spawnProcess particularly 
 intuitive), but I would prefer "the D way".

 Anyway, Where could the problem be?

 Regards, Hugo
You need to pass the INI parameters separately see: http://dlang.org/phobos/std_process.html#.spawnProcess spawnProcess([appexe,format("/INI=%s")], ["",""], Config.suppressConsole); Gr, Danny Arends http://www.dannyarends.nl
Pressed send too fast: 1) Separately = As an array 2) And I also forgot the appini variable So I think this should work: spawnProcess([appexe,format("/INI=%s",appini)], ["",""],Config.suppressConsole); Gr, Danny Arends http://www.dannyarends.nl
Dec 15 2013
next sibling parent reply Hugo Florentino <hugo acdam.cu> writes:
On Mon, 16 Dec 2013 02:04:10 +0100, Danny Arends wrote:
 ...
 So I think this should work:

 spawnProcess([appexe,format("/INI=%s",appini)],
 ["",""],Config.suppressConsole);
Hmm... that did not work either, it complained that the parameter was not correct. Actually, the syntax I was using should have worked (according to documentation, second overload of spawnProcess), and I also (unsuccessfully) tried with function execute. Anyway, since my launcher will only be run from Windows, finally I decided to call ShellExecuteA directly (I find it less cumbersome to use and actually more elegant). However, something is bothering me: when running the launcher, it opens a console temporarily before launching the other process (even when I am not using std.stdio) and I cannot get rid of this behavior. This is the code I am now using: import std.file: exists, getcwd; import std.path: buildPath, dirName; import std.string: format, toStringz; import core.sys.windows.windows; immutable static auto appname = "myapp"; extern(Windows) HANDLE ShellExecuteA(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, int); int main(string[] args) { auto appath = getcwd(); auto appexe = buildPath(appath, appname ~ ".exe"); if (exists(appexe)) { auto param = format(`/ini="%s"`, buildPath(appath, appname ~ ".ini")); ShellExecuteA(null, "", toStringz(appexe), toStringz(param), "", SW_SHOWMAXIMIZED); scope(failure) return -1; } return 0; } Why does the console window appear and how can I prevent this? Regards, Hugo
Dec 16 2013
parent reply Mike Parker <aldacron gmail.com> writes:
On 12/16/2013 6:33 PM, Hugo Florentino wrote:
 On Mon, 16 Dec 2013 02:04:10 +0100, Danny Arends wrote:
 However, something is bothering me: when running the launcher, it opens
 a console temporarily before launching the other process (even when I am
 not using std.stdio) and I cannot get rid of this behavior.

 This is the code I am now using:

 import std.file: exists, getcwd;
 import std.path: buildPath, dirName;
 import std.string: format, toStringz;
 import core.sys.windows.windows;

 immutable static auto appname = "myapp";

 extern(Windows) HANDLE ShellExecuteA(HWND, LPCSTR, LPCSTR, LPCSTR,
 LPCSTR, int);

 int main(string[] args) {
    auto appath = getcwd();
    auto appexe = buildPath(appath, appname ~ ".exe");
    if (exists(appexe)) {
      auto param = format(`/ini="%s"`, buildPath(appath, appname ~ ".ini"));
      ShellExecuteA(null, "", toStringz(appexe), toStringz(param), "",
 SW_SHOWMAXIMIZED);
      scope(failure) return -1;
    }
    return 0;
 }

 Why does the console window appear and how can I prevent this?
This is how Windows works. There are a couple of ways to eliminate the console. One is to use WinMain instead of main. That requires some boilerplate, though, as it bypasses the main function in DRuntime, so you have to initialize the runtime manually. It has the benefit of being portable across compilers. Another way, which is what I always do, is to add this to the command line (assuming DMD with OPTLINK): -L/SUBSYSTEM:WINDOWS:5.01 Every linker on Windows has some form of this flag. It may even be the same when using the VC toolchain. Also, you can drop the version number at the end. It depends on the minimum version of Windows you target and the target architecture (32-bit vs. 64-bit). Google it if you want to be sure of the details.
Dec 16 2013
next sibling parent Hugo Florentino <hugo acdam.cu> writes:
On Mon, 16 Dec 2013 18:59:52 +0900, Mike Parker wrote:
 On 12/16/2013 6:33 PM, Hugo Florentino wrote:
 ...
 Why does the console window appear and how can I prevent this?
This is how Windows works. There are a couple of ways to eliminate the console. One is to use WinMain instead of main. That requires some boilerplate, though, as it bypasses the main function in DRuntime, so you have to initialize the runtime manually. It has the benefit of being portable across compilers. Another way, which is what I always do, is to add this to the command line (assuming DMD with OPTLINK): -L/SUBSYSTEM:WINDOWS:5.01 Every linker on Windows has some form of this flag. It may even be the same when using the VC toolchain. Also, you can drop the version number at the end. It depends on the minimum version of Windows you target and the target architecture (32-bit vs. 64-bit). Google it if you want to be sure of the details.
That did the trick, thanks. Now, suppose I have two versions of the application (myapp32.exe and myapp64.exe), and I want my launcher to launch either, based on the architecture it detected from the OS being run on. What could I do in this case, which is actually what I need to do? (I just started with the simpler variant)
Dec 16 2013
prev sibling parent Hugo Florentino <hugo acdam.cu> writes:
On Mon, 16 Dec 2013 05:15:24 -0500, Hugo Florentino wrote:
 Now, suppose I have two versions of the application (myapp32.exe and
 myapp64.exe), and I want my launcher to launch either, based on the
 architecture it detected from the OS being run on. What could I do in
 this case, which is actually what I need to do? (I just started with
 the simpler variant)
Disregard that (since Windows 64-bit can run 32-bit applications just fine), I made a new thread regarding the OS architecture detection.
Dec 16 2013
prev sibling parent Hugo Florentino <hugo acdam.cu> writes:
On Mon, 16 Dec 2013 04:33:53 -0500, Hugo Florentino wrote:
 ...
 Why does the console window appear and how can I prevent this?
I forgot to mention that I tried using "int main ()" and even "void main()" and removing returns, but the console window keeps appearing, which is rather annoying for a Windows launcher.
Dec 16 2013