使用Process.Start重新启动具有不同参数的程序时的无限循环

时间:2018-03-22 11:28:01

标签: .net winforms console-application windows-server-2008 process.start

我重写了一个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

0 个答案:

没有答案