如何确保Inno Setup安装的应用仅运行单个实例?
实现单实例运行的两种可行方案
方案一:在程序内部实现(推荐,最稳定)
这是Windows平台实现单实例程序的标准做法,通过互斥量(Mutex)确保同一时间只有一个程序实例运行,无论用户通过何种方式启动程序都能生效。
以常见编程语言为例:
- C#:在
Program.cs的Main方法中添加互斥量检查逻辑:
using System.Threading; using System.Windows.Forms; using System.Runtime.InteropServices; namespace MyProg { static class Program { [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [STAThread] static void Main() { const string UniqueMutexName = "MyProg_SingleInstance_Mutex"; bool isNewInstance; using (var mutex = new Mutex(true, UniqueMutexName, out isNewInstance)) { if (isNewInstance) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } else { // 激活已有窗口并提示 var mainWindow = FindWindow(null, "MyProg主窗口标题"); if (mainWindow != IntPtr.Zero) { SetForegroundWindow(mainWindow); } MessageBox.Show("程序已在运行中!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } } }
- C++:在
WinMain中添加互斥量检查:
#include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const wchar_t* MutexName = L"MyProg_SingleInstance_Mutex"; HANDLE hMutex = CreateMutexW(nullptr, TRUE, MutexName); if (GetLastError() == ERROR_ALREADY_EXISTS) { // 找到已有窗口并激活 HWND hWnd = FindWindowW(nullptr, L"MyProg主窗口标题"); if (hWnd) { ShowWindow(hWnd, SW_RESTORE); SetForegroundWindow(hWnd); } MessageBoxW(nullptr, L"程序已在运行中!", L"提示", MB_OK | MB_ICONINFORMATION); CloseHandle(hMutex); return 0; } // 正常初始化并运行程序 // ... CloseHandle(hMutex); return 0; }
方案二:通过Inno Setup修改快捷方式(无需修改程序)
如果无法修改MyProg.exe的代码,可以通过Inno Setup生成一个辅助脚本,让快捷方式先检查进程再启动程序。
1. 生成辅助VBScript
在脚本的[Code]段添加代码,安装完成后生成用于检查进程的VBScript:
[Code] procedure CurStepChanged(CurStep: TSetupStep); var VBSPath: string; VBSContent: string; begin if CurStep = ssPostInstall then begin VBSPath := ExpandConstant('{app}\RunMyProgSingle.vbs'); VBSContent := 'Set WMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")' + #13#10 + 'Set Processes = WMI.ExecQuery("SELECT * FROM Win32_Process WHERE Name = ''MyProg.exe''")' + #13#10 + 'If Processes.Count = 0 Then' + #13#10 + ' CreateObject("WScript.Shell").Run """' + ExpandConstant('{app}\MyProg.exe') + '""", 1, False' + #13#10 + 'Else' + #13#10 + ' MsgBox "程序已在运行中!", vbInformation, "提示"' + #13#10 + 'End If'; SaveStringToFile(VBSPath, VBSContent, False); end; end;
2. 修改快捷方式指向脚本
更新[Icons]段,让快捷方式调用wscript.exe运行刚才生成的VBScript:
[Icons] Name: "{group}\MyProg"; Filename: "wscript.exe"; Parameters: """{app}\RunMyProgSingle.vbs"""; IconFilename: "app.ico" Name: "{userdesktop}\MyProg"; Filename: "wscript.exe"; Parameters: """{app}\RunMyProgSingle.vbs"""; IconFilename: "app.ico"
3. 卸载时清理脚本
在[UninstallDelete]段添加,确保卸载时删除辅助脚本:
[UninstallDelete] Type: files; Name: "{app}\RunMyProgSingle.vbs"
注意:这种方法依赖进程名检测,如果存在同名进程会有误判,若程序有唯一窗口标题,可以修改VBScript通过窗口标题检测来提高准确性。
内容的提问来源于stack exchange,提问作者deepika
相关产品推荐
相关产品推荐

