2014-09-21 62 views
3

我前段時間寫的代碼隱藏/恢復過程窗口,我做的事是這樣的:通過進程名稱取消隱藏進程?

要隱藏的過程:

1)在正在運行的進程查找進程名。 2)將MainWindowHandle添加到一個Container(在這種情況下是一個Dictionary),這將有必要稍後取消隱藏該進程。

3)使用ShowWindow API函數隱藏進程。

要取消隱藏進程:

1)在正在運行的進程查找進程名。

2)從容器中檢索保存的指定進程的MainWindowHandle。

3)使用ShowWindow API函數取消隱藏進程。

爲什麼我用字典來取消隱藏進程?好,因爲隱藏進程具有零0MainWindowHandle值,所以這是我發現檢索正確的手柄在ShowWindow使用的唯一途徑函數來恢復進程。

但我真的不希望依賴於Hide方法hidding過程之前保存所需的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 
+0

請,讀什麼我在重新標記之前在問題中說:'我想通過知道如何在VB.NET或C#中執行取消隱藏操作來改進這一切' – ElektroStudios 2014-09-21 16:19:50

+0

您的問題很廣泛。基本上,你問的是如何做一些事情,並希望有人會給出完整的工作代碼。如果你有一個實際的問題,你應該說明它是什麼。 – 2014-09-21 16:22:13

+0

我在哪裏要求完整的代碼?不,我要求提供信息,並且我提供了自己的代碼來演示有效的代碼,對您來說還不夠嗎?你希望從OP得到什麼更多的工作需要幫助,因爲不知道他自己的問題的解決方案?,這個討論看起來很荒謬,真的很抱歉,但是......我盡力了。 – ElektroStudios 2014-09-21 16:23:13

回答

4

代碼:

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); 
} 

如果存在具有相同名稱的多個實例,你可以使用一個變量如計數並增加 它在if語句

int count = 0; 

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

    count++; 
} 

FindWindowEx function

)和Process.MainWindowHandle()也許是其中每個功能 正在尋找手柄FindWindowEx(之間的差。FindWindowEx()看起來無處不像MainWindowHandle。還需要一個過程手柄下文稱HANDLE和窗口中的一個作爲HWND

+0

請添加文字說明如何回答問題。只包含代碼的答案並不是真的有用。 – 2014-09-21 20:12:14

+0

你能解釋一下你的解決方案的本質嗎?如果我理解得很好,我需要做的是找到任何對應於進程的子窗口HWND ?,我根本不明白爲什麼子窗口沒有處理值0的時候像主窗口一樣隱藏起來,但是它按預期工作!謝謝。 – ElektroStudios 2014-09-22 07:28:08

+1

@ElektroStudios查看編輯的代碼。 – 2014-09-22 10:56:04

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