Wise Indian
Wise Indian

Reputation: 91

Opening and Reopening exe file

I am trying to reopen an exe file (that I have previously opened) in this way: If it is open, then DO NOT reopen it but just bring that file into foucs. If it is not open, then open it. (Right now - the exe file keeps reopening.)

Anyone have a clue how to do this? (It works for powerpoint files, word files, excel files, movie files, pdf files)

This is my code:

    Dim file3dopen As New ProcessStartInfo()
    With file3dopen
        .FileName = Add3DFolder & cmbx3D.Text
        .UseShellExecute = True
        'Minimizes this form and unhides other form
        Minimize()
        FormMain.Show()
        FormMain.TopMost = True
    End With
    Process.Start(file3dopen)

Upvotes: 1

Views: 1063

Answers (1)

Steve
Steve

Reputation: 216302

If you own the code for the application that you want to start, then the best thing to do is to change that application startup code to not allow two instances of the same application. This could be done using the Mutex object in this way

<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

<STAThread()> _
Shared Sub Main()
    Dim createdNew As Boolean = true;
    Using mutes = new Mutex(true, "MyApplicationName", createdNew)
        if createdNew Then
            Application.EnableVisualStyles()
            Application.SetCompatibleTextRenderingDefault(false)
            Application.Run(new MainForm())
        else
            Dim current = Process.GetCurrentProcess();
            for each process in Process.GetProcessesByName(current.ProcessName)
                if process.Id <> current.Id Then
                    SetForegroundWindow(process.MainWindowHandle)
                    Exit For
                End If
            Next
        End If
    End Using    

After this, your other app can launch the first app without any check because in the called app the code above discover another copy of itself and switch the control to the copy found. There will never be two copies of the same application running at one time.

Instead, if you don't own the application to be started, then you can only work on your code adding a test to see if the application Process Name is present in the list of the current running processes For example:

Private Sub TestIfRunningIE
    if IsApplicationRunning("IEXPLORE") Then
        Console.WriteLine("Internet Explorer is running")
    Else
        Console.WriteLine("Internet Explorer is NOT running")
    End If
End Sub


Public Function IsApplicationRunning(ByVal appName As String) As Boolean
   For Each aProcess in Process.GetProcesses()   
        If aProcess.ProcessName.StartsWith(appName, StringComparisong.CurrentCultureIgnoreCase) Then
            Return true  
        End If
   Next
   Return False
End Function

Of course this requires that you know the process name, but you can easily find that name using one of the innumerable free process utility available.

EDIT To bring the process found to the foreground we need a bit of help from WinAPI. First, change the IsApplicationRunning to return the process found

Public Function IsApplicationRunning(ByVal appName As String) As Process
   For Each aProcess in Process.GetProcesses()   
        If aProcess.ProcessName.StartsWith(appName, StringComparisong.CurrentCultureIgnoreCase) Then
            Return aProcess  
        End If
   Next
   Return Nothing
End Function

then build a class that contains the declaration of two WinAPI contained in user32.dll

Public Class Win32Helper
    <System.Runtime.InteropServices.DllImport("user32.dll", _
    EntryPoint:="SetForegroundWindow", _
    CallingConvention:=Runtime.InteropServices.CallingConvention.StdCall, _
    CharSet:=Runtime.InteropServices.CharSet.Unicode, SetLastError:=True)> _
    Public Shared Function _
    SetForegroundWindow(ByVal handle As IntPtr) As Boolean
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll", _
    EntryPoint:="ShowWindow", _
    CallingConvention:=Runtime.InteropServices.CallingConvention.StdCall, _
    CharSet:=Runtime.InteropServices.CharSet.Unicode, SetLastError:=True)> _
    Public Shared Function ShowWindow(ByVal handle As IntPtr, ByVal nCmd As Int32) As Boolean
    End Function
End Class

and now in your main code write this

Dim proc = IsApplicationRunning("your_process_name")
if proc isnot Nothing then 
    Dim handle As IntPtr = proc.MainWindowHandle
    Dim Win32Help As New Win32Helper
    If Not IntPtr.Zero.Equals(handle) Then
        Win32Helper.ShowWindow(handle, 1)
        Win32Helper.SetForegroundWindow(handle)
    End If
else
    Console.WriteLine("Process not found")
End if

As a reference, I have found the code to implement the Win32Helper class here

Upvotes: 1

Related Questions