我重写了一个WinForms程序,也可以通过命令行访问和运行。在我的Win10机器上一切正常。双击可执行文件运行窗口版本,并从命令行调用它运行命令行版本。此外,我可以显式设置一个选项,以确保窗口或命令行模式独立于可执行文件的调用方式。
项目设置为控制台应用程序。要启动GUI版本,我关闭控制台应用程序并在没有控制台窗口的情况下重新启动它。 以下代码是我这样做的地方。
<DllImport("kernel32.dll", EntryPoint:="GetConsoleWindow")>
Private Shared Function GetConsoleWindow() As IntPtr
End Function
''' <summary>
''' Init as GUI application by restarting.
''' This might be a little hacky, but there is no other way since otherwise command line input is not working properly.
''' (I tried a lot variatons of attaching to the current cmd, etc.)
''' </summary>
Private Sub InitUI()
Dim consoleHandle As IntPtr = GetConsoleWindow()
If _configuration.IsGUIApplication And consoleHandle <> IntPtr.Zero Then
'' Restart without console, if it's a GUI application
Dim binaryPath As String = Assembly.GetEntryAssembly().Location
Dim processInfo As ProcessStartInfo = New ProcessStartInfo(binaryPath) With {
.CreateNoWindow = True,
.UseShellExecute = False,
.Arguments = Environment.CommandLine,
.WorkingDirectory = Path.GetDirectoryName(binaryPath)
}
Process.Start(processInfo)
'' End current console process
Environment.Exit(0)
End If
End Sub
我现在遇到的问题是,这在Windows Server 2008上不起作用。如果我通过双击启动应用程序似乎没有任何事情发生。查看TaskManager,程序似乎一次又一次地调用自己,因为执行调用类似于Program.exe Program.exe, Program.exe Program.exe ...
我认为consoleHandle
永远不会IntPtr.Zero
,因此它会重新启动并重新启动并重新启动。
我无法在Windows Server 2008上进行调试,但我可能会对程序添加日志消息。 我尝试了一些谷歌搜索,但没有成功就知道了。
编辑我的下一步是检查问题是否仍然发生,如果避免关闭当前的控制台应用程序。在这种情况下,窗口应用程序应该打开,控制台应该作为后台进程运行。
=&GT;我现在尝试了它,它的工作原理。不过我想在后台关闭控制台应用程序,只有窗口应用程序可见。
编辑2 刚刚添加了一些日志消息,我的假设是正确的:consoleHandle
在每次重启时获得一个新值,永远不会IntPtr.Zero
有没有人有想法?
解决方案我没有找到Windows Server 2008处理问题的原因与Win10不同。我解决它的方法是隐藏控制台窗口而不是重新启动实例。我对该解决方案没问题,但这意味着我无法在控制台内启动应用程序而无需保持控制台窗口打开。
<DllImport("kernel32.dll", EntryPoint:="GetConsoleWindow")>
Private Shared Function GetConsoleWindow() As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="ShowWindow")>
Private Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean
End Function
Private Const SW_HIDE As Integer = 0
''' <summary>
''' Returns whether the program was called from a console or not.
''' </summary>
''' <returns></returns>
Private Function IsCalledFromConsole() As Boolean
Dim left = Console.CursorLeft
Dim top = Console.CursorTop
Return Not (left = 0 AndAlso top = 0)
End Function
''' <summary>
''' Init as GUI application by hiding the console window.
''' This might be a little hacky, but there is no other way since otherwise command line input is not working properly.
''' (I tried a lot variatons of attaching to the current cmd, etc.!)
''' </summary>
Private Sub InitUI()
Dim consoleHandle As IntPtr = GetConsoleWindow()
If _configuration.IsGUIApplication And consoleHandle <> IntPtr.Zero And Not IsCalledFromConsole() Then
ShowWindow(consoleHandle, SW_HIDE)
End If
End Sub