以前我问过这个问题,这里解决了:
但是现在,由于未知原因,提供的C#或Vb.Net代码无法正常工作,我不明白为什么不这样做。
我对那里提供的原始代码做了一些修改,但是我测试了原件而没有用。
发生的事情是我无法解决隐藏的过程,我不知道我失败的地方。在第一个视图中,我认为我使用FindWindowEx
得到的句柄并不真正对应于我想要的句柄。
这些是我的P / Invoking函数签名和showwindow枚举:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto,
BestFitMapping:=False, ThrowOnUnmappablechar:=True)>
Friend Shared Function FindWindow(
ByVal lpClassName As String,
ByVal lpWindowName As String
) As IntPtr
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto,
BestFitMapping:=False, ThrowOnUnmappablechar:=True)>
Friend Shared Function FindWindowEx(
ByVal hwndParent As IntPtr,
ByVal hwndChildAfter As IntPtr,
ByVal strClassName As String,
ByVal strWindowName As String
) As IntPtr
End Function
<DllImport("user32.dll")>
Friend Shared Function GetWindowThreadProcessId(
ByVal hWnd As IntPtr,
ByRef processId As Integer
) As Integer
End Function
<DllImport("User32", SetLastError:=False)>
Friend Shared Function ShowWindow(
ByVal hwnd As IntPtr,
ByVal nCmdShow As ProcessUtil.WindowState
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Public Enum WindowState As Integer
Hide = 0
Normal = 1
ShowMinimized = 2
Maximize = 3
ShowMaximized = Maximize
ShowNoActivate = 4
Show = 5
Minimize = 6
ShowMinNoActive = 7
ShowNA = 8
Restore = 9
ShowDefault = 10
ForceMinimize = 11
End Enum
功能:
Public Function SetWindowState(ByVal p As Process,
ByVal windowState As ProcessUtil.WindowState) As Boolean
Dim pHandle As IntPtr = IntPtr.Zero
Dim pid As Integer
' If window is visible then...
If (p.MainWindowHandle <> IntPtr.Zero) Then
Return ProcessUtil.NativeMethods.ShowWindow(p.MainWindowHandle, windowState)
Else ' window is hidden.
' Check all open windows (not only the process we are looking),
' begining from the child of the desktop.
While (pid <> p.Id)
' Get child handle of window who's handle is "pHandle".
pHandle = NativeMethods.FindWindowEx(IntPtr.Zero, pHandle, Nothing, Nothing)
' Get PID from "pHandle".
NativeMethods.GetWindowThreadProcessId(pHandle, pid)
End While
Return NativeMethods.ShowWindow(pHandle, windowState)
End If
End Function
我尝试测试该功能的方式,首先我隐藏了记事本进程的窗口,然后我试着取消隐藏它。
Dim p As Process = Process.GetProcessesByName("notepad").First
ProcessUtil.SetWindowState(p, ProcessUtil.WindowState.Hide)
' I find again the process to renew the "p.MainWindowHandle" as IntPtr.Zero.
p = Process.GetProcessesByName("notepad").First
ProcessUtil.SetWindowState(p, ProcessUtil.WindowState.Restore)
答案 0 :(得分:2)
记事本的问题在于它有3个窗口( spy ++ ,类名):
<强> 1。 “记事本”强>
的 2。 “MSCTFIME UI”
第3。 “IME”强>
你正在掌握第二个(我还是得到了), MSCTFIME UI ,这就是为什么你无法展示它。您需要指定类名记事本才能获得正确的句柄:
pHandle = FindWindowEx(IntPtr.Zero, pHandle, "Notepad", Nothing)
答案 1 :(得分:2)
现在是您开始使用.NET Framework源代码的时候了,这样您就可以发现为什么这样的代码不能自己运行。访问Reference Source web site即可开始使用。
在搜索框中输入&#34; Process.MainWindowHandle&#34;,您将到达this page。很容易看出是完成工作的ProcessManager.GetMainWindowHandle。点击&#34; GetMainWindowHandle&#34;。它非常小,点击&#34; FindMainWindow&#34;。注意它如何枚举窗口,向右滚动一点以查看它&#34; EnumWindowsCallback&#34;完成工作。点击它,很容易看到它&#34; IsMainWindow&#34;决定窗口是否是主窗口。点击它:
bool IsMainWindow(IntPtr handle) {
if (NativeMethods.GetWindow(new HandleRef(this, handle), NativeMethods.GW_OWNER) != (IntPtr)0
|| !NativeMethods.IsWindowVisible(new HandleRef(this, handle)))
return false;
return true;
}
如果它是一个拥有的窗口,那么它就是而不是主窗口句柄。 或者如果它不可见。
后一条当然是你的克星。你隐藏了窗口,现在框架代码不再认为它可以成为主窗口。因此,Process.MainWindowHandle返回IntPtr.Zero,您的代码将无法再运行。
一个明显的解决方法是简单地重写.NET Framework代码并跳过IsWindowVisible()
测试。然而,这是一个重要的测试,它避免了找到几乎任何进程创建的消息窗口#34;它们用于内部管道。另一个答案提到了他们。你可以用Spy ++看到它们,Notepad有两个。如果没有按照使您找到它们的顺序创建,您将首先找到主窗口。这并不能保证在任何过程中都会发生。
正确的解决方法是,您必须不要忘记您对该窗口做了非常不友好的事情。记事本本身从不隐藏其主窗口。你基本上把它变成了僵尸,用户再也无法恢复窗口。剩下的唯一选择是使用任务管理器来终止进程。因此,完全可以让它再次可见。一个你不能忽视的工作,你必须在你的程序退出之前恢复它们。
或者只是不这样做,弄乱用户的窗户就像这样只是一种敌意。