有什么方法可以在后台运行进程吗?

时间:2009-07-12 01:16:23

标签: c# .net nohup

有任何命令行或.NET方法在后台运行一个进程,隐藏它试图打开的任何窗口吗?

已经尝试过:

 var process = new Process()
 {
      StartInfo = new ProcessStartInfo()
      {
          CreateNoWindow = true,
          WindowStyle = ProcessWindowStyle.Hidden,
          FileName = TheRealExecutableFileNameHere
      }
 }
 process.Start();

到目前为止没有成功

14 个答案:

答案 0 :(得分:15)

我查看了我的代码,它与您的代码几乎相同:

ProcessStartInfo psi = new ProcessStartInfo(fileName, arguments)
{
   CreateNoWindow = true,
   WindowStyle = ProcessWindowStyle.Hidden,
   UseShellExecute = false,
   RedirectStandardOutput = true                                               
};

Process process = Process.Start(psi);

唯一值得注意的区别(格式化和我们选择的PSI构造函数除外)是我使用UseShellExecute和RedirectStandardOutput,因为我需要读取运行过程的结果。

我发现上面的代码始终在XP和Vista上运行隐藏进程。但是,我也发现,你可能会遇到同样的问题,一个隐藏的进程可能会启动另一个默认情况下不被隐藏的进程。换句话说,如果您启动隐藏的流程A和流程A,则启动流程B,您无法控制流程B的显示方式。可能会显示您无法控制的Windows。

我希望这会有所帮助。祝你好运。

答案 1 :(得分:7)

查看Matlab Engine

如果这种方法符合您的需求,CodeProject上甚至会有一个有趣的article

答案 2 :(得分:5)

您是否尝试过使用带有 / B 开关的Microsoft DOS 开始命令?

Microsoft DOS start command

例如,

START /B cmd.exe

答案 3 :(得分:3)

没有我不知道纯粹的.Net方式来实现这一点。

然后我考虑了内核Job Objects,但在UI restrictions中找不到类似的选项。

因此,下一个(尚未验证的)想法是创建比暂停的进程create a windows hook然后,它将监视CallWndProc并过滤掉WM_SHOW消息。 (然后,当然,恢复进程,在一个单独的线程中等待,直到它终止,删除钩子)

答案 4 :(得分:2)

如果您还没有尝试.Net Framework中的BackgroundWorker Class,可能需要尝试。{3}}。它用于在单独的线程上执行长时间运行的进程,以防止它们阻碍UI。看看吧。

答案 5 :(得分:2)

我意识到这已经得到了回答,但您可以通过对FindWindow和ShowWindow的非托管调用来强制隐藏窗口。

[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

psi = new ProcessStartInfo(); // etc..
some_process = Process.Start(psi);
System.Threading.Thread.Sleep(50); // need give the window a chance to be created
IntPtr hWnd = FindWindow(null, "name of the window");
if (hWnd != IntPtr.Zero) ShowWindow(hWnd, 0); // 0 = SW_HIDE

相当kludgy。

答案 6 :(得分:1)

这取决于您是否要最小化启动应用程序,但是如果需要,允许它与用户交互,或者如果您想要禁止与用户进行所有访问,无论发生什么情况。

如果是后者,您可以在不同的桌面上下文中为当前用户运行该过程。

例如,通过“登录”对话框和Vista UAC使用不同的桌面上下文 - 在一个桌面上下文中发生的任何内容都独立于其他内容。

虽然可能是解决问题的大锤。

答案 7 :(得分:1)

我注意到如果CreateNoWindow = false在Filename指向Windows可执行文件时什么都不做,如果您有权访问winform应用程序的源代码,那么您可能能够提供一个控制默认值的命令行参数表单的可见性,并在Winform App启动代码中执行类似的操作:

static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Form1 form1 = new Form1();

        form1.Load += new EventHandler((s,o) =>
            {
              //check if the form should be shown based on command line arg
                if (args.Contains("dontShowWindow"))
                {
                    //hide it
                    form1.ShowInTaskbar = false;
                    form1.Visible = form1.ShowInTaskbar = false;
                }
            }
        );
        Application.Run(form1);
    }

在调用代码时,您现在可以将“dontShowWindow”指定为进程参数:

 ProcessStartInfo info = new ProcessStartInfo
        {
            CreateNoWindow = false, 
            WindowStyle = ProcessWindowStyle.Hidden,
            UseShellExecute = false, 
            FileName = @"C:\temp\testWinForm.exe",
            Arguments = "dontShowWindow"
        };
        Process.Start(info);

希望这有帮助

答案 8 :(得分:1)

实现此目的的一种非常简单的方法是创建服务帐户并通过Windows任务计划程序在服务帐户用户的上下文中运行可执行文件。

您可以使用此CodeProject来设置计划任务:

http://www.codeproject.com/KB/cs/tsnewlib.aspx

您可以使用C#在域或本地计算机上以编程方式创建服务帐户。

http://www.codeproject.com/KB/system/OSUserMangement.aspx http://support.microsoft.com/kb/306273

除非该用户已登录,否则在另一个用户的上下文中按计划任务运行的进程不会以交互方式显示;因此使用服务帐户。

答案 9 :(得分:1)

public Form1()
    {
        InitializeComponent();
        Form1 fm = new Form1();
        fm.ShowInTaskbar = false;
        fm.Visible = fm.ShowInTaskbar = false;
    }

效果很好!

答案 10 :(得分:0)

我假设你想要一个在运行时对用户不可见的进程。

您可以尝试以下操作来查看这是否是您想要的。

  1. 创建一个保持运行的简单控制台应用程序(并启动它进行测试)。
  2. 右键点击Project - >属性 - >应用程序选项卡 - >输出类型 - >将其从“控制台应用程序”更改为Windows应用程序。
  3. 再次启动相同的应用程序(看看这是否是你想要的)。
  4. 通过Windows任务管理器关闭应用程序:)
  5. 似乎该过程出现在任务管理器中,但在任务栏中不可见。 Alt + TAB无法启动此过程。

    我希望您不会制作任何恶意应用程序,但是:)

答案 11 :(得分:0)

我认为您可能想要尝试的是创建一个新的Windows Station。查看这篇文章,在msdn上解释一下它们。

http://msdn.microsoft.com/en-us/library/ms681928(VS.85).aspx

答案 12 :(得分:0)

你可以制作一个Windows'服务。服务尝试打开的任何窗口都在会话0中运行,这意味着没有用户可以看到它。这适用于所有窗户,所以也许这不是你正在寻找的。

答案 13 :(得分:0)

以下代码对我有用: 之前的过程(记事本)用于在桌面屏幕上闪烁记事本以进行打印,但它会分散用户的注意力,因此下面的代码会在背景中隐藏记事本过程。

                System.Windows.Forms.PrintDialog printDialog = new PrintDialog();
                System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(Application.StartupPath + "/PrintingDocketFile/PrintCustomerOrder.txt");
                psi.Verb = "PRINT";

                //Process.Start(psi);
                //psi.CreateNoWindow = true;
                psi.UseShellExecute = false;
                //---------------------------------------------------

                psi.CreateNoWindow = false;
                psi.UseShellExecute = true;
                psi.FileName = Application.StartupPath + "/PrintingDocketFile/PrintCustomerOrder.txt";
                psi.WindowStyle = ProcessWindowStyle.Hidden;
                psi.Arguments =  @"%windir%\system32\notepad.exe"; 
                //Process.Start(psi);
                //------------------------------------------------------

                /////////////////////----------------------------------

                printProcess.StartInfo = psi;
                /////psi.CreateNoWindow = true;

                //psi.FileName = "Application.StartupPath" + "/PrintingDocketFile/PrintCustomerOrder.txt";
                //p.StartInfo.FileName = "Notepad.EXE";
                //p.StartInfo.Arguments = "/i /q \"" + installationPackages[i] + "\"";

                printProcess.Start();

                /////////////////////////-------------------------------
                while (!printProcess.HasExited) ;


                if (!printProcess.HasExited)
                {
                    printProcess.Close();
                }