2018年9月12日 星期三

[點網] process.MainWindowHandle == 0


## 原因
為了拿到 process 的 MainWindowHandle 作隱藏/顯示。
但是在隱藏之後,process 的 MainWindowHandle 會等於 0


## 使用 AttachConsole GetConsoleWindow FreeConsole
其中一個方法是針對 console app 的作法是接到 console,拿到其 consolewindow 要到 ID,再離開。
使用 AttachConsole GetConsoleWindow FreeConsole

宣告需要:
```
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();
int GetSmsdMainWindowHandle(int procID)
    Int32 tryHandle = 0;
    try
    {
        AttachConsole((uint)procID);
        tryHandle = GetConsoleWindow().ToInt32();
        FreeConsole();
    }
    catch (Exception)
    {
        //pass
    }
    finally
    {
        FreeConsole();
    }
    return tryHandle;
}
```

使用方法:
```
int smsdMainWindowHandle = GetSmsdMainWindowHandle(xProc.Id);
```


## 使用 EnumChildWindows GetWindowThreadProcessId
另一個方法是列舉所有 子window 再拿到其 window thread 的 process ID。
使用 EnumChildWindows GetWindowThreadProcessId

宣告需要:
```
private struct SearchData
{
    // You can put any vars in here...         
    public int currentTaskID;
    public IntPtr currenthWnd;
}
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);
bool EnumProc(IntPtr hWnd, ref SearchData data)
{
    int lProcID;
    GetWindowThreadProcessId(hWnd,out lProcID);
    if (lProcID == data.currentTaskID)
    {
        data.currenthWnd = hWnd;
    }
    return true;
}
```

使用方法:
```
SearchData n = new SearchData();
n.currentTaskID = xProc.Id;
EnumChildWindows(IntPtr.Zero,new EnumWindowsProc(EnumProc),ref n);
int smsdMainWindowHandle = (int)n.currenthWnd;
```

這個方法的 VB Code 由 Cyrus 提供:
```
Dim currenthWnd = 0
Public Function fEnumWindowsCallback(ByVal hWnd As Integer, ByVal lpData As Integer) As Integer
    fEnumWindowsCallback = 1
    Dim lProcID As Integer
    Call GetWindowThreadProcessId(hWnd, lProcID)
    If lProcID = currentTaskID Then
        currenthWnd = hWnd
    End If
End Function

Call EnumChildWindows(0&, AddressOf fEnumWindowsCallback, 0&)
If currenthWnd <> 0 Then
    If goSECSInterface.GEMObject.HideSMSD = True Then
        ShowWindow(currenthWnd, SW_HIDE)
    Else
        ShowWindow(currenthWnd, SW_NORMAL)
    End If
End If
```

## 參考:

  • * https://stackoverflow.com/questions/8949652/do-windows-api-enumwindows-and-enumchildwindows-functions-behave-differently-in

沒有留言:

張貼留言