Чтобы взаимодействовать с чужим окном, вам нужно сначала найти его/подтвердить его существование.
У нас есть разные способы найти окно. Здесь я рассматриваю FindWindowEx и Process.GetProcessesByName(). Автоматизация пользовательского интерфейса и EnumWindows в конечном итоге предоставляет другие варианты.
Сохраните заголовок окна CMD где-нибудь, например, в поле экземпляра (это могут быть настройки проекта или что-то еще, к чему вы можете получить доступ во время выполнения).
Private cmdWindowTitle As String = "The Window Title"
→ FindWindowEx
более полезен, если вы точно знаете, что такое заголовок окна, и он не меняется со временем.
→ Process.GetProcessesByName()
можно использовать для поиска окна по имени процесса, а затем проверить, является ли Process.MainWindowTitle.Contains()
хотя бы частичным известная строка.
Если вместо этого окно консоли принадлежит текущему процессу, вам просто нужно:
Process.GetCurrentProcess().MainWindowHandle
' -- If the Console Window belongs to the current Process: --
Dim cmdWindowHandle = Process.GetCurrentProcess().MainWindowHandle
' -----------------------------------------------------------
' -- Find it when the exact Window title is known: --
Dim cmdWindowHandle As IntPtr = NativeMethods.GetCmdWindowByCaption(cmdWindowTitle)
' -----------------------------------------------------------
' -- Find it when only a partial caption is available: --
Dim cmdWindowHandle As IntPtr = IntPtr.Zero
Dim cmdProc = Process.GetProcessesByName("cmd").
FirstOrDefault(Function(p) p.MainWindowTitle.Contains(cmdWindowTitle))
If cmdProc IsNot Nothing Then
cmdWindowHandle = cmdProc.MainWindowHandle
End If
' -----------------------------------------------------------
' Choose one of the above, then, in any case:
If cmdWindowHanle <> IntPtr.Zero Then
NativeMethods.WindowDisableSysMenu(cmdWindowHandle)
End If
Примечание. Здесь я предполагаю, что имя процесса — cmd
, а имя класса окна — ConsoleWindowClass
. А может и не быть. Измените их по мере необходимости.
Поскольку теперь в Окне нет кнопок SystemMenu или Закрыть (мы просто спрятали их все), его нельзя закрыть с помощью ALT+F4 или любым другим способом, кроме Диспетчера задач (или дождаться его закрытия < em>естественно).
Чтобы закрыть его из приложения, отправьте WM_CLOSE
сообщение:
' -- find the Window as described before --
Dim cmdWindowHandle As IntPtr = NativeMethods.GetCmdWindowByCaption(cmdWindowTitle)
If Not cmdWindowHandle.Equals(IntPtr.Zero) Then
NativeMethods.SendCloseMessage(cmdWindowHandle)
End If
NativeMethods
заявления:
Public Class NativeMethods
Private Const WM_CLOSE As Integer = &H10
Public Enum WinStyles As UInteger
WS_MAXIMIZE = &H1000000
WS_MAXIMIZEBOX = &H10000
WS_MINIMIZE = &H20000000
WS_MINIMIZEBOX = &H20000
WS_SYSMENU = &H80000
End Enum
Public Enum GWL_Flags As Integer
GWL_STYLE = -16
GWL_EXSTYLE = -20
End Enum
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(hWnd As IntPtr, uMsg As WinMessage, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function GetWindowLong(hWnd As IntPtr, nIndex As GWL_Flags) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SetWindowLong(hWnd As IntPtr, nIndex As GWL_Flags, dwNewLong As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function GetWindowLongPtr(hWnd As IntPtr, nIndex As GWL_Flags) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SetWindowLongPtr(hWnd As IntPtr, nIndex As GWL_Flags, dwNewLong As IntPtr) As IntPtr
End Function
' Public wrappers
Public Shared Function GetWindowLongUni(hWnd As IntPtr, nIndex As GWL_Flags) As Integer
If IntPtr.Size = 8 Then
Return GetWindowLongPtr(hWnd, nIndex).ToInt32()
Else
Return GetWindowLong(hWnd, nIndex).ToInt32()
End If
End Function
Public Shared Function SetWindowLongUni(hWnd As IntPtr, nIndex As GWL_Flags, dwNewLong As Integer) As Integer
If IntPtr.Size = 8 Then
Return SetWindowLongPtr(hWnd, nIndex, New IntPtr(dwNewLong)).ToInt32()
Else
Return SetWindowLong(hWnd, nIndex, New IntPtr(dwNewLong)).ToInt32()
End If
End Function
Public Shared Function GetCmdWindowByCaption(cmdCaption As String) As IntPtr
Return FindWindowEx(IntPtr.Zero, IntPtr.Zero, "ConsoleWindowClass", cmdCaption)
End Function
Public Shared Sub WindowDisableSysMenu(windowHandle As IntPtr)
Dim styles As Integer = GetWindowLongUni(windowHandle, GWL_Flags.GWL_STYLE)
styles = styles And Not CInt(WinStyles.WS_SYSMENU)
SetWindowLongUni(windowHandle, GWL_Flags.GWL_STYLE, styles)
End Sub
Public Shared Sub SendCloseMessage(windowHandle As IntPtr)
SendMessage(windowHandle, WM_CLOSE, 0, 0)
End Sub
End Class
person
Jimi
schedule
30.05.2020
CREATE_NO_WINDOW
в качествеdwCreationFlags
при вызове CreateProcess делает это. Без окна консоли вам больше не нужно мешать пользователю взаимодействовать с ним. @cai Нет программы для DOS. В вопросе четко указано, что это 32-битное программное обеспечение. - person IInspectable   schedule 31.05.2020