【问题标题】:Unhide process by its process name?按进程名称取消隐藏进程?
【发布时间】:2014-09-21 16:17:13
【问题描述】:

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

隐藏进程:

1) 在正在运行的进程中查找进程名。

2) 将 MainWindowHandle 添加到容器(在本例中为字典),这对于稍后取消隐藏该过程是必要的。

3) 使用 ShowWindow API 函数隐藏进程。

取消隐藏进程:

1) 在正在运行的进程中查找进程名。

2) 从容器中取出指定进程保存的MainWindowHandle。

3) 使用 ShowWindow API 函数取消隐藏进程。

为什么我使用字典来取消隐藏进程?嗯,因为隐藏进程的 MainWindowHandle 值为零 0,所以这是我发现检索正确句柄以在ShowWindow函数恢复进程。

但我真的不想依赖Hide 方法在隐藏进程之前保存所需的HWND,我想通过知道如何执行取消隐藏操作来改进这一切在 VB.NET 或 C# 中仅通过指定进程名称(例如: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

【问题讨论】:

  • 请在重新标记之前阅读我在问题中所说的话:'我想通过了解如何在 VB.NET 或 C# 中执行取消隐藏操作来改进这一切'
  • 您的问题很广泛。基本上,您是在询问如何做某事,并希望有人能提供完整的工作代码。如果你有一个实际问题,你应该说明它是什么。
  • 我在哪里要求完整代码?,不,我是在要求信息,另外,我提供了自己的代码来演示工作代码,对您来说还不够吗?由于不知道他自己的问题的解决方案,您对需要帮助的 OP 有什么期望?,这个讨论看起来很荒谬,真的,很抱歉,但是......我尽力了。

标签: c# vb.net winforms winapi process


【解决方案1】:

代码:

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 并递增 它在 if 语句中

int count = 0;

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

    count++;
}

FindWindowEx function

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

【讨论】:

  • 请添加文字说明如何回答问题。只包含代码的答案并不是那么有用。
  • 你能解释一下你的解决方案的本质吗?,如果我理解得很好,我需要做的是找到与进程相对应的任何子窗口 HWND?,我根本不明白为什么孩子windows 在像主窗口一样隐藏时没有句柄值 0,但它可以按预期工作!谢谢。
【解决方案2】:

感谢@γηράσκω δ' αεί πολλά διδασκόμε,我为 vb.net 编写了这个解决方案

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

<System.Runtime.InteropServices.DllImport("User32.dll")>
Private Shared Function FindWindowEx(
        ByVal hwndParent As IntPtr,
        ByVal hwndChildAfter As IntPtr,
        ByVal strClassName As String,
        ByVal strWindowName As String
) As IntPtr
End Function

<System.Runtime.InteropServices.DllImport("user32.dll")>
Private Shared Function GetWindowThreadProcessId(
        ByVal hWnd As IntPtr,
        ByRef ProcessId As Integer
) As Integer
End Function

Public Enum WindowState As Integer

    ''' <summary>
    ''' Hides the window and activates another window.
    ''' </summary>
    Hide = 0I

    ''' <summary>
    ''' Activates and displays a window. 
    ''' If the window is minimized or maximized, the system restores it to its original size and position.
    ''' An application should specify this flag when displaying the window for the first time.
    ''' </summary>
    Normal = 1I

    ''' <summary>
    ''' Activates the window and displays it as a minimized window.
    ''' </summary>
    ShowMinimized = 2I

    ''' <summary>
    ''' Maximizes the specified window.
    ''' </summary>
    Maximize = 3I

    ''' <summary>
    ''' Activates the window and displays it as a maximized window.
    ''' </summary>      
    ShowMaximized = Maximize

    ''' <summary>
    ''' Displays a window in its most recent size and position. 
    ''' This value is similar to <see cref="WindowVisibility.Normal"/>, except the window is not actived.
    ''' </summary>
    ShowNoActivate = 4I

    ''' <summary>
    ''' Activates the window and displays it in its current size and position.
    ''' </summary>
    Show = 5I

    ''' <summary>
    ''' Minimizes the specified window and activates the next top-level window in the Z order.
    ''' </summary>
    Minimize = 6I

    ''' <summary>
    ''' Displays the window as a minimized window. 
    ''' This value is similar to <see cref="WindowVisibility.ShowMinimized"/>, except the window is not activated.
    ''' </summary>
    ShowMinNoActive = 7I

    ''' <summary>
    ''' Displays the window in its current size and position.
    ''' This value is similar to <see cref="WindowVisibility.Show"/>, except the window is not activated.
    ''' </summary>
    ShowNA = 8I

    ''' <summary>
    ''' Activates and displays the window. 
    ''' If the window is minimized or maximized, the system restores it to its original size and position.
    ''' An application should specify this flag when restoring a minimized window.
    ''' </summary>
    Restore = 9I

    ''' <summary>
    ''' Sets the show state based on the SW_* value specified in the STARTUPINFO structure 
    ''' passed to the CreateProcess function by the program that started the application.
    ''' </summary>
    ShowDefault = 10I

    ''' <summary>
    ''' <b>Windows 2000/XP:</b> 
    ''' Minimizes a window, even if the thread that owns the window is not responding. 
    ''' This flag should only be used when minimizing windows from a different thread.
    ''' </summary>
    ForceMinimize = 11I

End Enum

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

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

    Dim pHandle As IntPtr = IntPtr.Zero
    Dim pID As Integer = 0I

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

    ' If any process matching the name is found then...
    If Processes.Count = 0 Then
        Exit Sub
    End If

    For Each p As Process In Processes

        Do Until pID = p.Id ' Check all windows.

            ' Get child handle of window who's handle is "pHandle".
            pHandle = FindWindowEx(IntPtr.Zero, pHandle, Nothing, Nothing)

            ' Get ProcessId from "pHandle".
            GetWindowThreadProcessId(pHandle, pID)

            ' If the ProcessId matches the "pID" then...
            If pID = p.Id Then

                ShowWindow(pHandle, WindowState)

                If Not Recursivity Then
                    Exit For
                End If

            End If

        Loop

    Next p

End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 2011-02-25
    • 2011-06-19
    相关资源
    最近更新 更多