问题
edit: My issue was never quite resolved, but the answer below provided an interesting result.
The app will eventually be called by a powershell script and in this situation, I don't have the issue explained below. No additional {ENTER} is required in the PS console, so no more issue! I couldn't care less if an extra ENTER is required when my app is launched manually via cmd.exe
Problem: In a VB.NET form app, I'm unable to get the console back to it's "default" state after the code is finished running. I need to press enter manually.
My app can also be executed from command line (in this case, no form is opened. Code is being executed automatically and output sent to console for user to see what happens)
I call AttachConsole(-1)
, run some code, and when everything's finished I see my latest message in console, but it's as if the process wasn't quite finished.
I have tried SendKeys.SendWait("{ENTER}")
. It works well, but only when the console is the current focus. If I click outside the console while the code is running, the ENTER key is sent to whichever window I made active.
So I tried to make the console the current window:
Dim bProcess As Process = Process.GetProcessesByName("cmd").FirstOrDefault()
SetForegroundWindow(bProcess.MainWindowHandle)
// I also tried AppActivate(bProcess.Id)
SendKeys.SendWait("{ENTER}")
FreeConsole()
Nope, the ENTER key will still be sent somewhere else and not to the console. But it does make the console blink orange, so SetForegroundWindow
seems to do something...
Any help will be greatly appreciated :)
EDIT
In response to @TnTinMn's answer:
FreeConsole()
// SendKeys.SendWait("test")
PieceOfCodeFromTnTinMn()
Same behavior as I've had so far: This will send the SendKeys.SendWait("~")
command "outside" the console if it loses focus while the code is running.
BUT with the 2nd line above un-commented, "test" is sent outside the console and SendKeys.SendWait("~")
is sent to the console, as expected.
I'm still trying to figure out what is happening here...
回答1:
You can use the VB Interaction.AppActivate Method to activate the parent console prior to calling SendKeys.SendWait
. This requires that you obtain the ProcessID of the console window that is the parent process of your application.
One way to do this is using Windows Management Instrumentation (WMI). The following is not pretty, but it appears to work. You would execute this after calling 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
来源:https://stackoverflow.com/questions/62027134/send-enter-key-to-console-in-form-application-in-vb-net