在没有可见控制台窗口的窗口中创建后台进程

时间:2020-03-05 18:49:45  来源:igfitidea点击:

如何在不创建可见命令窗口的情况下在Windows上使用Haskell创建后台进程?

我编写了一个Haskell程序,该程序定期运行备份进程,但是每次运行该程序时,都会在所有窗口的顶部打开一个命令窗口。我想摆脱这个窗口。最简单的方法是什么?

解决方案

回答

我能想到的最简单的方法是从Windows Shell脚本(vbs或者cmd)中运行rsync命令。

回答

我对Haskell一无所知,但是几个月前我在C项目中遇到了这个问题。

在不弹出任何窗口的情况下执行外部程序的最佳方法是将ShellExecuteEx()API函数与" open"动词配合使用。如果在Haskell中可以使用ShellExecuteEx(),那么我们应该能够实现所需的功能。

C代码看起来像这样:

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);
      }
   }

回答

我们应该真正告诉我们我们当前的尝试方式,但是在我的系统上(使用linux),以下代码段将在不打开新终端窗口的情况下运行命令。它在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

回答

到目前为止,感谢答复,但是我已经找到了自己的解决方案。我确实尝试了许多不同的事情,从建议的编写vbs脚本到名为hstart的独立程序。 hstart起作用了...但是它创建了一个我不太喜欢的单独进程,因为那样我就无法以正常方式将其杀死。但是我找到了一个更简单的解决方案,只需要Haskell代码即可。

我之前的代码是对runCommand的简单调用,它确实弹出了窗口。我们可以使用的替代功能是runProcess,它具有更多选项。通过查看ghc源代码文件runProcess.c,我发现在为所有STDIN,STOUT和STDERR提供重定向时,会设置CREATE_NO_WINDOW标志。这就是我们需要做的,为这些提供重定向。我的测试程序如下所示:

import System.Process
import System.IO
main = do
  inH <- openFile "in" ReadMode
  outH <- openFile "out" WriteMode
  runProcess "rsync.bat" [] Nothing Nothing (Just inH) (Just outH) (Just outH)

这行得通!再次没有命令窗口!需要注意的是,即使在我的情况下,也不需要inH作为STDIN读入inH,但我们需要一个空文件。