C#依据进程名称获取进程的句柄?

本文介绍了一种在C#中通过进程名称获取进程句柄的方法。利用CreateToolhelp32Snapshot等API函数,实现对指定进程句柄的检索,并通过枚举窗口的方式进一步定位到目标进程的主窗口句柄。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C#依据进程名称获取进程的句柄或C#怎样获取其它进程的句柄?

有时候标题名是动态变化的,所以不使用FindWindow方法!



[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 ")]
    public static extern IntPtr CreateToolhelp32Snapshot(uint flags,uint processid);
    [DllImport("KERNEL32.DLL ")]
    public static extern int CloseHandle(IntPtr handle);
    [DllImport("KERNEL32.DLL ")]
    public static extern int Process32First(IntPtr handle,ref   ProcessEntry32 pe);
    [DllImport("KERNEL32.DLL ")]
    public static extern int Process32Next(IntPtr handle,ref   ProcessEntry32 pe);

    [DllImport("User32.dll",EntryPoint="SendMessage")]
    private static extern int SendMessage(int hWnd,int Msg,int wParam,string lParam);



 public IntPtr GetHandleByProcessName(string ProcessName)
    {
      List<ProcessEntry32> list=new List<ProcessEntry32>();
      IntPtr handle=CreateToolhelp32Snapshot(0x2,0);
      IntPtr hh=IntPtr.Zero;
      if((int)handle>0)
      {
        ProcessEntry32 pe32=new ProcessEntry32();
        pe32.dwSize=(uint)Marshal.SizeOf(pe32);
        int bMore=Process32First(handle,ref pe32);
        while(bMore==1)
        {
          IntPtr temp=Marshal.AllocHGlobal((int)pe32.dwSize);
          Marshal.StructureToPtr(pe32,temp,true);
          ProcessEntry32 pe=(ProcessEntry32)Marshal.PtrToStructure(temp,typeof(ProcessEntry32));
          Marshal.FreeHGlobal(temp);
          list.Add(pe);
          if(pe.szExeFile==ProcessName)
          {
            bMore=2;
            hh=GetCurrentWindowHandle(pe.th32ProcessID);
            break;
          }
          bMore=Process32Next(handle,ref pe32);
        }
      }
      return hh;
    }
    public static IntPtr GetCurrentWindowHandle(uint proid)
    {
      IntPtr ptrWnd=IntPtr.Zero;
      uint uiPid=proid;
      object objWnd=processWnd[uiPid];
      if(objWnd!=null)
      {
        ptrWnd=(IntPtr)objWnd;
        if(ptrWnd!=IntPtr.Zero&&IsWindow(ptrWnd))  // 从缓存中获取句柄
        {
          return ptrWnd;
        }
        else
        {
          ptrWnd=IntPtr.Zero;
        }
      }
      bool bResult=EnumWindows(new WNDENUMPROC(EnumWindowsProc),uiPid);
      // 枚举窗体返回 false 而且没有错误号时表明获取成功
      if(!bResult&&Marshal.GetLastWin32Error()==0)
      {
        objWnd=processWnd[uiPid];
        if(objWnd!=null)
        {
          ptrWnd=(IntPtr)objWnd;
        }
      }
      return ptrWnd;
    }


    private static bool EnumWindowsProc(IntPtr hwnd,uint lParam)
    {
      uint uiPid=0;
      if(GetParent(hwnd)==IntPtr.Zero)
      {
        GetWindowThreadProcessId(hwnd,ref uiPid);
        if(uiPid==lParam)    // 找到进程相应的主窗体句柄
        {
          processWnd.Add(uiPid,hwnd);   // 把句柄缓存起来
          SetLastError(0);    // 设置无错误
          return false;   // 返回 false 以终止枚举窗体
        }
      }
      return true;
    }


调用:

     IntPtr hh=GetHandleByProcessName("notepad.exe");
      if(hh!=IntPtr.Zero)
      {
        SendMessage((int)hh,0x000C,0,"A");  //打开记事本,发送字母A
      }


C#中,要根据进程名称获取句柄,你可以利用Windows API中的`CreateToolhelp32Snapshot`、`Process32First`和`Process32Next`等函数,以及`OpenProcess`函数。这是一个典型的遍历进程列表并查找指定进程的过程。以下是一个基本的示例: ```csharp using System; using System.Diagnostics; using System.Runtime.InteropServices; [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId); [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr hObject); [DllImport("kernel32.dll")] public static extern bool QueryFullProcessImageName(uint processHandle, uint threadId, [Out] StringBuilder lpImageFileName, ref uint size); // ... string targetProcessName = "YourProcessName"; // 替换为你要找的进程名 StringBuilder processNameBuffer = new StringBuilder(260); // 假设最长进程名长度为260字节 uint processId; int result = Process.GetProcessesByName(targetProcessName, out processId); if (result > 0) // 查找成功 { IntPtr handle = OpenProcess(ProcessAccessFlags.ProcessAllAccess, false, (uint)processId); if (handle != IntPtr.Zero) { uint fileNameSize = 0; QueryFullProcessImageName(handle, 0, processNameBuffer, ref fileNameSize); if (fileNameSize > 0) { processNameBuffer.Capacity = (int)fileNameSize; QueryFullProcessImageName(handle, 0, processNameBuffer, ref fileNameSize); if (processNameBuffer.ToString() == targetProcessName) { Console.WriteLine($"找到了进程 {targetProcessName} 的句柄: {handle}"); } } CloseHandle(handle); } else { Console.WriteLine($"无法打开进程 {targetProcessName} 的句柄"); } } else { Console.WriteLine($"未找到名为 {targetProcessName} 的进程"); } ``` 在这个例子中,我们首先获取进程ID,然后尝试打开该进程,并使用`QueryFullProcessImageName`检查进程名是否匹配。如果匹配,我们就得到了句柄
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值