views:

973

answers:

4

I wrote a Haskell program that runs backup processes periodically on a Windows machine use rsync. But everytime I run the rsync command, a command window opens up to the top of all the windows. I would like to get rid of this window. What is the simplest way to do this?

A: 

The simplest way I can think of is to run the rsync command from within a Windows Shell script (vbs or cmd).

Apocalisp
A: 

I don't know anything about Haskell, but I had this problem in a C project a few months ago.

The best way to execute an external program without any windows popping up is to use the ShellExecuteEx() API function with the "open" verb. If ShellExecuteEx() is available to you in Haskell, then you should be able to achieve what you want.

The C code looks something like this:

SHELLEXECUTEINFO Info;
BOOL b;

// Execute it
memset (&Info, 0, sizeof (Info));
Info.cbSize = sizeof (Info);
Info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
Info.hwnd = NULL;
Info.lpVerb = "open";
Info.lpFile = "rsync.exe";
Info.lpParameters = "whatever parameters you like";
Info.lpDirectory = NULL;
Info.nShow = SW_HIDE;
b = ShellExecuteEx (&Info);
if (b)
   {
   // Looks good; if there is an instance, wait for it
   if (Info.hProcess)
      {
      // Wait
      WaitForSingleObject (Info.hProcess, INFINITE);
      }
   }
Martin Del Vecchio
I don't believe it is directly, but it's only a small bit of FFI away.
wnoise
+1  A: 

You should really tell us how you are trying to do this currently, but on my system (using linux) the following snippet will run a command without opening a new terminal window. It should work the same way on windows.

module Main where
import System
import System.Process
import Control.Monad

main :: IO ()
main = do
  putStrLn "Running command..."
  pid <- runCommand "mplayer song.mp3" -- or whatever you want
  replicateM_ 10 $ putStrLn "Doing other stuff"
  waitForProcess pid >>= exitWith
Alasdair
scripts that work straight up on the command line in Linux do tend to pop up the cmd window in Windows. I just experienced this pleasure for the first time yesterday.
C Hogg
+4  A: 

Thanks for the responses so far, but I've found my own solution. I did try a lot of different things, from writing a vbs script as suggested to a standalone program called hstart. hstart worked...but it creates a separate process which I didn't like very much because then I can't kill it in the normal way. But I found a simpler solution that required simply Haskell code.

My code from before was a simple call to runCommand, which did popup the window. An alternative function you can use is runProcess which has more options. From peeking at the ghc source code file runProcess.c, I found that the CREATE_NO_WINDOW flag is set when you supply redirects for all of STDIN, STOUT, and STDERR. So that's what you need to do, supply redirects for those. My test program looks like:

import System.Process import System.IO main = do inH

This worked! No command window again! A caveat is that you need an empty file for inH to read in as the STDIN eventhough in my situation it was not needed.

toby