C#中的应用程序启动

时间:2009-09-30 16:54:07

标签: c#

我们有一个小C#启动应用程序,用户启动它从网络共享运行我们的主要C#WinForms应用程序的最新版本。这是一种简化的ClickOnce安排(我们的IT人员不允许我们使用ClickOnce)。

启动应用程序在调用Process.Start(“MainApplication.exe”)后退出,但主应用程序可能需要几秒钟才能显示,使用户显示空白。

有没有一种方法可以让starup应用程序轮询操作系统,以确定主应用程序在退出之前是否正在运行?或者其他一些方法来处理这个问题?

7 个答案:

答案 0 :(得分:11)

您可以使用Process.WaitForInputIdle()等待应用程序进入空闲状态。

Process appProcess = Process.Start("MainApplication.exe");
appProcess.WaitForInputIdle();

来自MSDN:

  

...你刚刚开始了一个过程   想要使用它的主窗口句柄,   考虑使用WaitForInputIdle   允许该过程完成的方法   开始,确保主力   窗口句柄已创建

备注来自Process.MainWindowHandle属性的部分。

答案 1 :(得分:7)

您可以致电Process.GetProcessByName查看是否已创建新流程。另一个选择是让主应用程序在加载完成后终止它。

答案 2 :(得分:5)

使用Davids的建议,或者您可以在主应用程序中添加splash screen。它只是一个简单的Form,其中一个图像在一个单独的工作线程上运行。把它作为启动时调用的第一个项目。您的应用可以继续初始化主线程&几秒钟后或在主应用程序完成初始化之前杀死工作线程。

答案 3 :(得分:1)

解决此问题的一种方法是使用全局事件向启动应用程序发出主应用程序已达到预定状态的信号。为此,在启动应用程序中创建一个命名事件句柄,并等待它发出信号:

static void Main(string[] args)
{
    const string globalName = "MyProgramName";//something unique

    bool isNew = false;

    ManualResetEvent mreExited = new ManualResetEvent(false);
    EventWaitHandle mreStarted = new EventWaitHandle(false, EventResetMode.ManualReset, globalName, out isNew);

    try
    {
        if (!isNew)//already running, just exit?
            return;

        //start and monitor for exit
        Process pstarted = Process.Start("...");
        pstarted.Exited += delegate(object o, EventArgs e) { mreExited.Set(); };
        pstarted.EnableRaisingEvents = true;

        int index = WaitHandle.WaitAny(new WaitHandle[] { mreExited, mreStarted });

        if (index == 0)//mreExited signaled
            throw new ApplicationException("Failed to start application.");
    }
    finally
    {
        mreExited.Close();
        mreStarted.Close();
    }
}

然后在主程序中,一旦准备启动应用程序退出,就会发出事件信号:

static void Main(string[] args)
{
    const string globalName = "MyProgramName";//same unique name

    bool isNew = false;
    EventWaitHandle mreStarted = new EventWaitHandle(false, EventResetMode.ManualReset, globalName, out isNew);
    try
    {
        if (!isNew)
            mreStarted.Set();

        Application.Run(new Form());
    }
    finally
    {
        mreStarted.Close();
    }
}

答案 4 :(得分:0)

我认为大卫的第二个选择是去这里的方式。该进程可能正在运行,但还没有可见的UI。因此,一旦主要表单显示在第二个应用程序中,就终止第一个进程。您可以想象,当您启动新流程时,可以通过StartInfo传递原始流程的流程ID。

答案 5 :(得分:0)

many trade-offs涉及此问题,但您可以通过NGEN使启动时间足够快,从而使此问题无法实现。

答案 6 :(得分:0)

我的建议是将Splash Screen放在你的应用程序中它给你一个很好的感觉,而不是你不想使用Splash屏幕然后在加载完成后终止进程。或者您可以使用 Process.GetProcessByName()

对于Splash Screen,只需创建一个Window Screen,在启动类中只从 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase 继承该类,该类为您提供方法 OnCreateSplashScreen()覆盖这样的方法是这样的: -

protected override void OnCreateSplashScreen()
{
    base.OnCreateSplashScreen();
    //yourSplashScreen is the screen you made as a window form either it would be a image or form
    SplashScreen = yourSplashScreen();
}

谢谢... Saurabh Singh乐于编码