c# - 通过进程名称取消隐藏进程?

标签 c# vb.net winforms winapi process

前段时间我写了一个隐藏/恢复进程窗口的代码,我做的是这样的:

隐藏进程:

1) Find the process name in the running processes.

2) Add the MainWindowHandle to a Container (a Dictionary in this case), this would be necessary to unhide that process later.

3) Hide the process using ShowWindow API function.

取消隐藏进程:

1) Find the process name in the running processes.

2) Retrieve the saved MainWindowHandle of the specified process from the container.

3) Unhide the process using ShowWindow API function.

为什么我使用字典来取消隐藏进程?好吧,因为隐藏进程有一个 MainWindowHandle零值 0 ,所以这是我发现检索要在 ShowWindow 中使用的正确句柄的唯一方法恢复过程的函数。

但我真的不想依赖Hide在隐藏进程之前保存所需的 HWND 的方法,我想通过了解如何在 VB.NETC#< 中执行取消隐藏操作来改进这一切/strong> 仅通过指定进程名称(例如:cmd.exe)而不在 MainWindowHandle 之前保存,这有可能吗?

我展示了代码(在 VB.NET 中),让您了解我为 HideProcess 方法做了什么:

但请注意,这段代码与问题不完全相关,我的问题是如何仅通过指定进程名称来取消隐藏隐藏进程以避免下面编写的代码需要检索已保存句柄以取消隐藏进程。

' Hide-Unhide Process
'
' Usage Examples :
'
' HideProcess(Process.GetCurrentProcess().MainModule.ModuleName)
' HideProcess("notepad.exe", Recursivity:=False)
' HideProcess("notepad", Recursivity:=True)
'
' UnhideProcess(Process.GetCurrentProcess().MainModule.ModuleName)
' UnhideProcess("notepad.exe", Recursivity:=False)
' UnhideProcess("notepad", Recursivity:=True)

Private ProcessHandles As New Dictionary(Of String, IntPtr)

<System.Runtime.InteropServices.DllImport("User32")>
Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As Integer) As Integer
End Function

Private Sub HideProcess(ByVal ProcessName As String, Optional ByVal Recursivity As Boolean = False)

    If ProcessName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) Then
        ProcessName = ProcessName.Remove(ProcessName.Length - ".exe".Length)
    End If

    Dim Processes() As Process = Process.GetProcessesByName(ProcessName)

    Select Case Recursivity

        Case True
            For Each p As Process In Processes
                ProcessHandles.Add(String.Format("{0};{1}", ProcessName, CStr(p.Handle)), p.MainWindowHandle)
                ShowWindow(p.MainWindowHandle, 0)
            Next p

        Case Else
            If Not (Processes.Count = 0) AndAlso Not (Processes(0).MainWindowHandle = 0) Then
                Dim p As Process = Processes(0)
                ProcessHandles.Add(String.Format("{0};{1}", ProcessName, CStr(p.Handle)), p.MainWindowHandle)
                ShowWindow(p.MainWindowHandle, 0)
            End If

    End Select

End Sub

Private Sub UnhideProcess(ByVal ProcessName As String, Optional ByVal Recursivity As Boolean = False)

    If ProcessName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) Then
        ProcessName = ProcessName.Remove(ProcessName.Length - ".exe".Length)
    End If

    Dim TempHandles As New Dictionary(Of String, IntPtr)
    For Each Handle As KeyValuePair(Of String, IntPtr) In ProcessHandles
        TempHandles.Add(Handle.Key, Handle.Value)
    Next Handle

    For Each Handle As KeyValuePair(Of String, IntPtr) In TempHandles

        If Handle.Key.ToLower.Contains(ProcessName.ToLower) Then

            ShowWindow(Handle.Value, 9)
            ProcessHandles.Remove(Handle.Key)

            If Recursivity Then
                Exit For
            End If

        End If

    Next Handle

End Sub

最佳答案

代码:

using System.Diagnostics;
using System.Runtime.InteropServices;

[DllImport("User32")]
private static extern int ShowWindow(IntPtr hwnd, int nCmdShow);

[DllImport("User32.dll")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string strClassName, string strWindowName);

[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);

private const int SW_RESTORE = 9;

private void UnhideProcess(string processName) //Unhide Process
{
    IntPtr handle = IntPtr.Zero;
    int prcsId = 0;

    //an array of all processes with name "processName"
    Process[] localAll = Process.GetProcessesByName(processName);

    //check all open windows (not only the process we are looking) begining from the
    //child of the desktop, handle = IntPtr.Zero initialy.
    do
    {
        //get child handle of window who's handle is "handle".
        handle = FindWindowEx(IntPtr.Zero, handle, null, null);

        GetWindowThreadProcessId(handle, out prcsId); //get ProcessId from "handle"

        //if it matches what we are looking
        if (prcsId == localAll[0].Id)
        {
            ShowWindow(handle, SW_RESTORE); //Show Window

            return;
        }
    } while (handle != IntPtr.Zero);
}

如果有更多同名实例,您可以使用变量,例如 count 和 increment 它在 if 语句中

int count = 0;

if (prcsId == localAll[count].Id)
{
    ShowWindow(handle, SW_RESTORE);

    count++;
}

FindWindowEx function

FindWindowEx()Process.MainWindowHandle() 之间的区别可能在于每个函数的位置 正在寻找句柄。 FindWindowEx() 到处寻找,这与 MainWindowHandle 不同。此外,进程句柄被称为 HANDLE,窗口被称为 HWND

关于c# - 通过进程名称取消隐藏进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25961231/

相关文章:

c# - powerpoint 记录排练时间

java - 如何更改本地机器/以太网IP地址

c# - 控制 ASP.NET 主题 css 链接顺序放置

c# - 在 Visual Studio 2010 中的 C# Windows 应用程序中使用 mysql

mysql - 将 MySQL 连接字符串动态更改为 Crystal Reports

c# - 监控击键

c# - 如何暂停或停止正在播放的音频文件

c# - 索引超出范围c#datagridview

c# - 随着时间的推移保存值(value)的方法

c# - WINAPI/DWMAPI 不规则形状的模糊窗口