C# 告知是否有登录用户正在运行即将安装/卸载的应用程序
我的程序使用Inno安装程序来安装/卸载它。在我的应用程序代码中,我使用C# 告知是否有登录用户正在运行即将安装/卸载的应用程序,c#,inno-setup,mutex,C#,Inno Setup,Mutex,我的程序使用Inno安装程序来安装/卸载它。在我的应用程序代码中,我使用CreateMutexwindowsapi函数创建了一个Global互斥体。然后在Inno安装程序中,我有以下代码: AppMutex=Global\MyProgramMutex.2A23834B-2919-4007-8C0A-3C7EDCA7186E 函数InitializeSetup():Boolean; 开始 结果:=真; 如果(CreateMutex(0,False,“{SetupSetting('AppId')}”
CreateMutex
windowsapi函数创建了一个Global互斥体。然后在Inno安装程序中,我有以下代码:
AppMutex=Global\MyProgramMutex.2A23834B-2919-4007-8C0A-3C7EDCA7186E
函数InitializeSetup():Boolean;
开始
结果:=真;
如果(CreateMutex(0,False,“{SetupSetting('AppId')}”)0和(DLLGetLastError=ERROR_已经存在),那么
开始
结果:=假;
MsgBox('安装程序的另一个实例已在运行。请关闭它并重试',mbCriticalError,MB_OK);
结束;
如果CheckForMutexes(“{#SetupSetting('AppMutex')}”),则
开始
结果:=假;
MsgBox(“{#SetupSetting('AppName')}”+”似乎正在运行。请在继续之前关闭程序的所有实例。“,mbCriticalError,MB#u OK);
结束;
结束;
正如预期的那样,对于运行Inno安装程序的用户来说,这非常有效。我遇到的问题是:如果我“切换用户”并以其他用户的身份启动应用程序,然后切换回原始用户,则安装程序不会检测到应用程序正在其他用户下运行
我对安装程序是否能检测到正在运行的应用程序还不够了解。如Inno Setup KB中所述: 要检测在其他会话中创建的互斥体,应用程序必须创建两个互斥体:一个带有
Global\
前缀,另一个不带前缀
带有Global\
前缀的互斥体可以从任何用户会话访问。如果由于安全限制或缺乏操作系统支持(4.0终端服务器版之前的Windows NT版本不支持全局\前缀),全局互斥体的创建失败,则还必须在会话名称空间中创建一个类似命名的互斥体(即不带全局\
前缀)
此外,必须在每个CreateMutex()调用中传递一个特殊的安全描述符,以确保不同的用户可以访问互斥体。
要使C#中的所有用户都可以访问互斥,请参阅:总之,C#应用程序中的代码应该如下所示: 常量字符串mutexId=“MyProg”; MutexAccessRule允许每个人= 新MutexAccessRule( 新的SecurityIdentifier(WellKnownSidType.WorldSid,null), MutexRights.FullControl、AccessControlType.Allow); MutexSecurity securitySettings=新的MutexSecurity(); securitySettings.AddAccessRule(AllowEveryoneUrle); 互斥对象globalMutex=null; 尝试 { 布尔创造了新的; globalMutex=新互斥体(false,“Global\\”+mutexId,out createdNew,securitySettings); } 捕获(未经授权的访问例外) { //忽略 } Mutex localMutex=新的互斥(false,mutexId); 尝试 { //在这里运行您的程序 } 最后 { //只有在应用程序(其窗口)关闭后才能调用它们。 //您还可以删除这些调用,让系统释放互斥锁。 if(globalMutex!=null) { globalMutex.Dispose(); } localMutex.Dispose(); }
在Inno设置端,您只需在以下列表中列出两个互斥体:
[设置]
AppMutex=MyProg,全局\MyProg
在
InitializeSetup
函数中,您不需要调用CreateMutex
和CheckForMutexes
。好主意。下面是我在WPF中使用互斥对象的完整解决方案,Inno安装程序将检测到这些对象,即使其他登录用户正在运行WPF应用程序。顺便说一句,我用的是Visual Studio
public partial class App : Application
{
private static readonly string _MutexID = "MyWPFApp"; // or whatever
[STAThread]
public static void Main()
{
var application = new App();
application.InitializeComponent();
MutexAccessRule allowEveryoneRule = new MutexAccessRule(
new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.FullControl,
AccessControlType.Allow);
MutexSecurity securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryone);
Mutex globalMutex = null;
try
{
bool createdNew;
globalMutex = new Mutex(false, "Global\\" + _MutexID, out createdNew, securitySettings);
}
catch (UnauthorizedAccessException)
{
// ignore
}
Mutex localMutex = new Mutex(false, _MutexID);
try
{
MainWindow mainWin = new MainWindow();
application.Run(mainWin);
}
finally
{
if (globalMutex != null)
{
globalMutex.Dispose();
}
localMutex.Dispose();
}
}
}
[Setup]
AppMutex=MyWPFApp,Global\MyWPFApp
我试图用C#为两个互斥体使用
语句来构建代码,但我的大脑被冻结了
或者,还可以创建一个单独的类,其中包含Main
方法,并将上面的代码放在那里。这需要上面的步骤4和5,在步骤2中,将启动对象更改为包含Main
方法的新类
谢谢你,马丁
Bob似乎应该可以正常工作,因为您根据使用了\global作为前缀。上面的代码是来自安装程序集还是应用程序集?您不需要为AppMutex添加代码,我怀疑应用程序中有代码。关于它的知识库条目。是一个关于应用程序方面的问题。马丁,我为误用“答案”功能道歉。我这样做是出于无知。所以,今天早上我很快把你的建议写进了我的申请代码。在Inno设置脚本中,我从“InitializeSetup”函数中删除了互斥代码,并在[Setup]部分修改了我的AppMutex设置。我安装并运行了我的应用程序。然后我再次运行安装程序,但它没有检测到正在运行的应用程序。它确实检测到有一个程序(我的应用程序)正在使用它继续运行所需的文件。我看不出我错过了什么?再次感谢…您的整个程序运行在哪里?
//在这里运行您的程序
注释在哪里?如果我创建一个简单的控制台应用程序,并将console.ReadLine
放在该位置,在另一个会话中运行该应用程序,安装程序会完美地检测到。是的。这是一个WPF应用程序,您已经指出,我有code
MainWindow mainWin=new MainWindow();缅因州