Отправить клавишу ENTER в консоль в приложении формы в VB.NET - PullRequest
1 голос
/ 26 мая 2020

edit: Моя проблема так и не была решена, но ответ ниже дал интересный результат.

Приложение в конечном итоге будет вызываться сценарием PowerShell, и в этой ситуации я не Нет объяснения проблемы ниже. Никаких дополнительных клавиш {ENTER} в консоли PS не требуется, так что больше никаких проблем! Мне все равно, требуется ли дополнительный ENTER, когда мое приложение запускается вручную через cmd.exe


Проблема: в приложении формы VB.NET я не могу вернуть консоль в состояние «по умолчанию» после завершения выполнения кода. Мне нужно нажать ввод вручную.

Мое приложение также можно запустить из командной строки (в этом случае форма не открывается. Код выполняется автоматически, а вывод отправляется на консоль, чтобы пользователь мог увидеть, что происходит)

Я вызываю AttachConsole(-1), запускаю какой-то код, и когда все закончено, я вижу свое последнее сообщение в консоли, но это как будто процесс еще не завершен. enter image description here

Я пробовал SendKeys.SendWait("{ENTER}"). Он работает хорошо, но только тогда, когда в фокусе находится консоль. Если я щелкаю за пределами консоли во время выполнения кода, клавиша ENTER отправляется в то окно, которое я сделал активным.

Итак, я попытался сделать консоль текущим окном:

Dim bProcess As Process = Process.GetProcessesByName("cmd").FirstOrDefault()
SetForegroundWindow(bProcess.MainWindowHandle)
// I also tried AppActivate(bProcess.Id)

SendKeys.SendWait("{ENTER}")

FreeConsole()

Нет, клавиша ENTER все равно будет отправлена ​​в другое место, а не на консоль. Но это заставляет консоль мигать оранжевым, поэтому SetForegroundWindow кажется, что-то делает ...

Любая помощь будет принята с благодарностью :)


EDIT

В ответ на ответ @TnTinMn:

FreeConsole()
// SendKeys.SendWait("test")
PieceOfCodeFromTnTinMn()

То же поведение, что и у меня до сих пор: команда SendKeys.SendWait("~") будет отправлена ​​«за пределы» консоли, если она теряет фокус во время код запущен.

НО со второй строкой выше без комментариев, "test" отправляется за пределы консоли, а SendKeys.SendWait("~") отправляется на консоль, как и ожидалось.

Я все еще пытаюсь понять, что здесь происходит ...

1 Ответ

1 голос
/ 27 мая 2020

Вы можете использовать метод VB Interaction.AppActivate для активации родительской консоли перед вызовом SendKeys.SendWait. Для этого необходимо получить ProcessID окна консоли, которое является родительским процессом вашего приложения.

Один из способов сделать это - использовать Windows Management Instrumentation (WMI). Следующее некрасиво, но, похоже, работает. Вы должны выполнить это после вызова FreeConsole

Using currentProcess As Process = Process.GetCurrentProcess
  Dim query As New SelectQuery()
  Dim props As New StringCollection
  props.Add("ProcessId")
  props.Add("ParentProcessId")
  With query
    .ClassName = "Win32_Process"
    .Condition = $"ProcessId={currentProcess.Id}"
    .SelectedProperties = props
  End With

  Dim parentProcessId As Int32
  Using searcher As New ManagementObjectSearcher(query)
    Using mos As ManagementObjectCollection = searcher.Get
      Using en As ManagementObjectCollection.ManagementObjectEnumerator = mos.GetEnumerator
        If en.MoveNext() Then
          parentProcessId = CInt(en.Current.Item("ParentProcessId"))
        End If
      End Using 'en
    End Using ' mos
  End Using 'searcher

  If parentProcessId <> 0 Then
    AppActivate(parentProcessId)
    SendKeys.SendWait("~")
  End If
End Using 'currentProcess
...