用多种形式打开exe而不会杀死进程

时间:2016-12-08 00:37:55

标签: vb.net winforms

环境:vb.net,赢取表格和VS2010

我有两个应用程序A& B. B有两个从应用程序A打开的表单F1和F2。现在,下面的代码成功打开了应用程序B表单。我有一个非常具体的要求......

如果应用程序B-F1打开并且用户想要打开F2,则应用程序B会出现在前面,但F1仍然显示为当前表单。在下面的代码“IsProcessRunning”中,如果F2未打开,我可以检查并终止应用程序B进程,然后用F2重新打开应用程序B.但我的要求是在不杀死应用程序B进程的情况下打开F2。在应用B中,frmMain(MDI)是主要的切入点。我怎样才能实现这一目标?

如果无法实现上述目标,那么当我杀死应用程序B时,该应用程序B frmMain - 形成关闭事件应该触发,以便我可以处理某些非常重要的操作。

这是当前代码:

''' <summary>
    ''' Click handle to open - all buttons need to call this action 
    ''' </summary>
    ''' <param name="titleArg">Title to be passed to the ScaleApps as Argument </param>
    ''' <param name="windowTitle">The part of the name for the form as showing in the process title under ctrl+alt+del</param>
    ''' <remarks></remarks>
    Private Sub HandleClick(ByVal titleArg As String, ByVal windowTitle As String)
        Dim exeLocation As String = curSettings.ExeLocation
        Dim processName As String = "MyApps" 'EXE name. Do not add .EXE
        Dim isRunning As Boolean = IsProcessRunning(processName, windowTitle, True)
        If Not isRunning Then
            isRunning = OpenProcess(exeLocation, processName, titleArg, windowTitle)
        End If
        BringProcessToFront(processName)
    End Sub
 
 
#Region "Helper Functions"
 
    <System.Runtime.InteropServices.DllImport("User32.dll")> _
    Private Shared Function SetForegroundWindow(handle As IntPtr) As Boolean
    End Function
 
    <System.Runtime.InteropServices.DllImport("User32.dll")> _
    Private Shared Function ShowWindow(handle As IntPtr, nCmdShow As Integer) As Boolean
    End Function
 
    <System.Runtime.InteropServices.DllImport("User32.dll")> _
    Private Shared Function IsIconic(handle As IntPtr) As Boolean
    End Function
 
    ''' <summary>
    ''' Opens the prossess and passes the specified arguments to it
    ''' </summary>
    ''' <param name="exeLocation">EXE full qualified path</param>
    ''' <param name="processName">The process name without .exe</param>
    ''' <param name="titleArg">The title Argumemt getting passed to the EXE</param>
    ''' <param name="windowTitle">The window title showing in processes</param>
    ''' <returns>True/False</returns>
    Private Function OpenProcess(ByVal exeLocation As String, ByVal processName As String, ByVal titleArg As String, ByVal windowTitle As String) As Boolean
        Dim isRunning As Boolean = False
        Try
            If String.IsNullOrEmpty(processName) Then
                Message("Process name missing!", zMsgTypes.Err)
                Return False
            ElseIf String.IsNullOrWhiteSpace(exeLocation) Then
                Message("Exe location not specified in the cfg file!", zMsgTypes.Err)
                Return False
            ElseIf Not File.Exists(exeLocation) Then
                Message("Exe location doesn't exist. Please open cfg file and update setting" & vbCrLf & exeLocation, zMsgTypes.Err)
                Return False
            End If
 
            Dim psi As New ProcessStartInfo
            psi.FileName = exeLocation
            psi.Arguments = titleArg & " " & curStatus.UserID
            psi.UseShellExecute = True
            psi.WindowStyle = ProcessWindowStyle.Normal
            Dim proc As Process = Process.Start(psi)
            'isRunning = IsProcessRunning(processName, windowTitle, False)
            isRunning = True
        Catch ex As Exception
            putHistory("OpenProcess Error:" & ex.Message)
        End Try
        Return isRunning
    End Function
 
    ''' <summary>
    ''' Brings the App to the front
    ''' </summary>
    ''' <param name="processName">The process name without .exe</param>
    Private Sub BringProcessToFront(ByVal processName As String)
        If String.IsNullOrEmpty(processName) Then
            Message("Process name missing!", zMsgTypes.Err)
            Exit Sub
        End If
        Try
            'here we're going to get a list of all running processes on the computer and then will check out process
            Dim pf As Process() = Process.GetProcessesByName(processName)
            If pf.Length > 0 Then
                Dim handle As IntPtr
                For Each procP As Process In pf
                    'check and bring to the front
                    handle = procP.MainWindowHandle
                    If handle <> 0 Then 'Do we have a handle; if only want to being minimized window to front then add IsIconic to the if as well
                        ShowWindow(handle, 9)
                        SetForegroundWindow(handle)
                    End If
                Next
            End If
        Catch ex As Exception
            putHistory("BringProcessToFront Error:" & ex.Message)
        End Try
    End Sub
 
    ''' <summary>
    ''' Checks if the process is running
    ''' </summary>
    ''' <param name="processName">The process name without .exe</param>
    ''' <param name="windowTitle">The window title</param>
    ''' <param name="isKillProcess">Kill process if the windowTitle is not found</param>
    ''' <returns>True/False</returns>
    Private Function IsProcessRunning(ByVal processName As String, ByVal windowTitle As String, ByVal isKillProcess As Boolean) As Boolean
        Try
            If String.IsNullOrEmpty(processName) Then
                Message("Process name missing!", zMsgTypes.Err)
                Return False
            ElseIf String.IsNullOrEmpty(windowTitle) Then
                Message("Window title missing!", zMsgTypes.Err)
                Return False
            End If
 
            Dim myTitle As String = ""
            For Each pf As Process In Process.GetProcesses()
                If pf.ProcessName.ToUpper.StartsWith(processName.ToUpper) Then
                    myTitle = pf.MainWindowTitle.ToUpper
                    If Not myTitle.Contains(windowTitle.ToUpper) Then
                        'Do not kill, find another way to tell the tartget exe to open the new form
                        'If isKillProcess Then
                        '    pf.Kill()
                        'End If
                        'Return False ' do not kill
                        Return True
                    End If
                    If pf.MainWindowTitle.ToUpper.Contains(windowTitle.ToUpper) Then
                        Return True
                    End If
                End If
            Next
        Catch ex As Exception
            putHistory("IsProcessRunning Error:" & ex.Message)
        End Try
        Return False
    End Function
  
#End Region

1 个答案:

答案 0 :(得分:1)

对应用程序“B”使用Make Single Instance Application功能。您可以传递一个命令行参数来指示应该显示哪个表单。这将触发StartupNextInstance事件,您可以据此采取相应措施。