1

我正在尝试以这种方式重新打开一个 exe 文件(我以前打开过):如果它已打开,则不要重新打开它,而只需将该文件放入 foucs 中。如果没有打开,那就打开它。(现在 - exe 文件不断重新打开。)

任何人都知道如何做到这一点?(适用于 powerpoint 文件、word 文件、excel 文件、电影文件、pdf 文件)

这是我的代码:

    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)
4

1 回答 1

1

如果您拥有要启动的应用程序的代码,那么最好的办法是更改该应用程序启动代码以不允许同一应用程序的两个实例。这可以通过这种方式使用 Mutex 对象来完成

<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    

在此之后,您的其他应用程序无需任何检查即可启动第一个应用程序,因为在被调用的应用程序中,上面的代码发现了自身的另一个副本并将控件切换到找到的副本。永远不会有同一应用程序的两个副本同时运行。

相反,如果您不拥有要启动的应用程序,那么您只能在代码上添加测试以查看应用程序进程名称是否存在于当前正在运行的进程列表中例如:

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

当然,这要求您知道进程名称,但您可以使用无数可用的免费进程实用程序之一轻松找到该名称。

编辑 要将发现的进程带到前台,我们需要 WinAPI 的一些帮助。首先,更改 IsApplicationRunning 以返回找到的进程

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

然后构建一个类,其中包含两个 WinAPI 的声明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

现在在你的主要代码中写这个

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

作为参考,我在这里找到了实现 Win32Helper 类的代码

于 2013-04-21T10:46:10.940 回答