65.9K
CodeProject 正在变化。 阅读更多。
Home

父进程窗口

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.50/5 (4投票s)

2008年3月15日

CPOL

2分钟阅读

viewsIcon

42080

downloadIcon

476

演示如何获取进程 ID 并在父进程窗口上显示模态窗口。

引言

本文展示了如何针对父进程窗口显示模态对话框/窗体。

下载文件包含一个演示解决方案,展示了如何使用此处显示的所有代码。
重要的代码被封装在一个类中,这使得维护工作更容易!

背景

这种情况并不经常发生,但我最近需要创建一个 Windows 服务,该服务需要在安装过程中显示一个对话框窗口以收集一些用户信息。在开发安装项目的过程中,我开始思考如何确保数据收集窗体不被隐藏,并且在用户未完成必要细节的情况下,安装不会继续进行。

我记得过去曾使用 MFC 和 WIN32 做过类似的事情,但这次我需要针对基于 .NET 的解决方案。我决定做一些研究。

在 CodeProject 资源中,我找到了一个解决方案,它展示了如何使用 WIN32 获取父进程,并且我还找到了将 IntPtr 句柄封装到 IWin32Window 中的方法!

这是将检索父进程的函数

Process GetParentProcess()
{
    int iParentPid = 0;
    int iCurrentPid = Process.GetCurrentProcess().Id;

    IntPtr oHnd = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if(oHnd == IntPtr.Zero)
        return null;

    PROCESSENTRY32 oProcInfo = new PROCESSENTRY32();

    oProcInfo.dwSize =
        (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(PROCESSENTRY32));

    if(Process32First(oHnd, ref oProcInfo) == false)
        return null;

    do
    {
        if(iCurrentPid == oProcInfo.th32ProcessID)
        iParentPid = (int)oProcInfo.th32ParentProcessID;
    }
    while(iParentPid == 0 && Process32Next(oHnd, ref oProcInfo));

    if(iParentPid > 0)
        return Process.GetProcessById(iParentPid);
    else
        return null;    
}

这是 PInvoke 定义

#region WIN32 Definitions
    static uint TH32CS_SNAPPROCESS = 2;

    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESSENTRY32
    {
        public uint dwSize;
         public uint cntUsage;
    public uint th32ProcessID;
         public IntPtr th32DefaultHeapID;
         public uint th32ModuleID;
         public uint cntThreads;
         public uint th32ParentProcessID;
         public int pcPriClassBase;
         public uint dwFlags;
         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
         public string szExeFile;
    };

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);

    [DllImport("kernel32.dll")]
    static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [DllImport("kernel32.dll")]
    static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
#endregion

同样重要的是 IWin32Window 的实现

// Implementation of IWin32Window
// ----------------------------------------
class WinWrapper : System.Windows.Forms.IWin32Window
{
     public WinWrapper(IntPtr oHandle)
    {
        _oHwnd = oHandle;
    }

    public IntPtr Handle
    {
        get { return _oHwnd; }
    }

    private IntPtr _oHwnd;
}

全部使用

假设父进程是基于窗体的,而子进程是控制台应用程序。子进程需要显示一个对话框,它可以这样做

Process oParent = GetParentProcess();
WinWrapper oParentHandle = new WinWrapper(oParent.MainWindowHandle);
MessageBox.Show(oParentHandle, "Hello Child Parent proc world!");

关注点

有趣的是,窗口 IntPtr 句柄必须封装在 IWin32Window 中,它只是返回相同的内容。我尝试了 NativeWindow 类,但它没有帮助!

祝你好运,希望有人觉得这段代码有用,并感谢所有在 Code Project 上发布代码的人!

历史

  • 2008年3月15日:初步发布
© . All rights reserved.