1

我有一个小型启动程序,它在自己的线程上加载启动画面并显示它。如果满足一组条件,则需要启动另一个应用程序并保持启动屏幕可见,直到另一个应用程序说可以关闭启动屏幕。

在此处输入图像描述

Launcher 的生命周期总是在 Child App 之前开始,在 Child App 关闭之后结束。

这是一些相关代码的片段

常用DLL:

namespace Example.Common
{
    public partial class SplashScreen : Form
    {
        public SplashScreen()
        {
            InitializeComponent();
        }

        static SplashScreen splashScreen = null;
        static Thread thread = null;

        static public void ShowSplashScreen()
        {
            // Make sure it is only launched once.
            if (splashScreen != null)
                return;

            thread = new Thread(new ThreadStart(SplashScreen.ShowForm));
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        // A static entry point to launch SplashScreen.
        static private void ShowForm()
        {
            splashScreen = new SplashScreen();
            Application.Run(splashScreen);
        }

        // A static method to close the SplashScreen
        static public void CloseForm()
        {
            splashScreen.Close();
        }
    }
}

初始启动器:

/// <summary>
/// This application is a small launcher to launch the real graphical launcher. It is small and lightweight and should be rarely be updated.
/// It will call the ProgramLauncher, the program launcher will return in it's status code the PID of the instance it launched or -1
/// if no subsequent program was started.
/// </summary>
[STAThread]
static void Main()
{
    //Show the Splash screen;
    Example.Common.SplashScreen.ShowSplashScreen();

    //(Snip)

    if (rights == UserRights.None)
    {
        SplashScreen.CloseForm();
        MessageBox.Show("Your user does not have permission to connect to the server.", "Unable to logon", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
    //If the user has full desktop access, give it to them and launch a new instance of the launcher.
    else if (rights.HasFlag(UserRights.FullDesktopAccess))
    {
        Process explorer = new Process();
        explorer.StartInfo.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "explorer.exe");
        if (explorer.Start() == false)
        {
            MessageBox.Show("Explorer failed to start.");
        }
        else
        {
            //Close the splash screen.
            SplashScreen.CloseForm();

            //If the user can shadow start a new instance of the launcher inside explorer.
            if (rights.HasFlag(UserRights.ShadowNormalUser) || rights.HasFlag(UserRights.ShadowDemoUser))
            {
                //Start a new copy of the program so people can use it to shadow easily.
                var shadowProc = new Process();
                shadowProc.StartInfo.FileName = "ProgramLauncher.exe";
                shadowProc.StartInfo.UseShellExecute = false;
                shadowProc.Start();
            }
            explorer.WaitForExit();
        }
    }
    else
    {
        Process programLauncher = new Process();
        programLauncher.StartInfo.FileName = "ProgramLauncher.exe";
        programLauncher.StartInfo.UseShellExecute = false;

        //Launch the graphical launcher.
        programLauncher.Start();
        programLauncher.WaitForExit();

        //Check to see if the graphical launcher launched some other process.
        if (programLauncher.ExitCode >= 0)
        {
            //If there was a pid, don't close the micro launcher till after it closes.
            Process runningProcess = Process.GetProcessById(programLauncher.ExitCode);
            runningProcess.WaitForExit();
        }

    }
}

让 ProgramLauncher 关闭 MicroLauncher 创建的 SplashScreen 实例的最简单方法是什么?

4

3 回答 3

1

有很多方法可以做到这一点,各有利弊。可能最简单的方法是从您的 ProgramLauncher 进程重定向标准输出并将其连接到 MicroLauncher 应用程序中的事件(请参见此处的示例)。从您的 ProgramLauncher 程序中,您将某个消息写入标准输出。当 MicroLauncher 收到该消息时,您关闭窗口。

另一种选择是将初始屏幕的 HWND 作为命令行参数传递给 ProgramLauncher,然后 ProgramLauncher 可以使用 SendMessage(WM_SYSCOMMAND, SC_CLOSE) 关闭窗口(参见此处的示例)。

您还可以研究 IPC 方法、发送自定义 Windows 消息或可能有上千种其他可能性,但这两个想法可能会让您入门。

于 2012-06-22T17:00:32.107 回答
1

您需要SplashScreen将其窗口句柄 (HWND) 传递给ProgramLauncher. 然后,ProgramLauncher可以使用winapi函数向目标窗口SendMessage发送消息:WM_SYSCOMMAND

public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);

在 WinForms 中,您可以使用Handle. 平台调用代码SendMessage这里

至少我现在没有看到更简单的方法,但我认为它比任何 IPC 机制都更容易。

于 2012-06-22T16:55:17.007 回答
0

我能想到的最简单的方法:让子应用程序创建一个命名互斥体,让父应用程序等到有人创建它,不时检查。

不是很优雅并且容易被滥用(另一个应用程序故意创建一个同名的互斥锁),但在实践中,我怀疑这会是一个问题。

于 2012-06-22T16:57:12.283 回答