2016-11-07 4 views
2

내 프로그램에서 Inno Setup을 사용하여 설치/제거합니다. 내 응용 프로그램 코드에서 CreateMutex Windows API 함수를 사용하여 전역 뮤텍스를 만듭니다. 그렇다면 Inno Setup 프로그램에서 다음과 같은 코드를 가지고 있습니다.로그온 한 사용자가 설치/제거하려는 응용 프로그램을 실행 중인지 확인하십시오.

AppMutex=Global\MyProgramMutex.2A23834B-2919-4007-8C0A-3C7EDCA7186E 

function InitializeSetup(): Boolean; 
begin 
    Result := True; 

    if (CreateMutex(0, False, '{#SetupSetting('AppId')}') <> 0) and (DLLGetLastError = ERROR_ALREADY_EXISTS) then 
    begin 
    Result := False; 
    MsgBox('Another instance of the Setup program is already running. Please close it and try again', mbCriticalError, MB_OK); 
    end; 

    if CheckForMutexes('{#SetupSetting('AppMutex')}') then 
    begin 
    Result := False; 
    MsgBox('{#SetupSetting('AppName')} ' + 'appears to be running. Please close all instances of the program before continuing.', mbCriticalError, MB_OK); 
    end; 
end; 

Inno 설치 프로그램을 실행하는 사용자에게는 예상대로 좋았습니다. 내가 가진 질문/문제는 다음과 같습니다. "사용자 전환"을 선택하고 다른 사용자로 응용 프로그램을 시작한 다음 원래 사용자로 다시 전환하면 설치 프로그램이 응용 프로그램이 다른 사용자로 실행되고 있음을 감지하지 못합니다.

설치 프로그램이 실행중인 응용 프로그램을 감지 할 수있는 경우 충분한 정보를 알 수 없습니다. 이노 설치 KB Detect instances running in any user session with AppMutex에 문서화으로

+0

보인다. 위의 코드는 설치 어셈블리 또는 응용 프로그램 어셈블리에서 제공합니까? – Botonomous

+0

AppMutex가 작동하도록 코드를 추가 할 필요는 없습니다. 응용 프로그램의 코드가 의심 스럽습니다. [여기있다] (http://www.jrsoftware.org/iskb.php?mutexsessions) 그것에 대한 kb 엔트리. [Here] (http://stackoverflow.com/q/229565/243614)는 애플리케이션 측면에 대한 질문입니다. –

답변

2

:

는 다른 세션에서 생성 된 뮤텍스를 감지하기 위해 두 개의 뮤텍스를 작성해야합니다 응용 프로그램하십시오 Global\ 접두어 하나없이 다른.

접두사가 Global\ 인 뮤텍스는 모든 사용자 세션에서 액세스 할 수 있습니다. 보안 제한이나 운영 체제 지원 부족으로 글로벌 뮤텍스 생성이 실패한 경우 (예 : Global\ 접두어가없는) 세션 네임 스페이스에도 같은 이름의 뮤텍스를 만들어야합니다 (4.0 Terminal Server Edition 이전의 Windows NT 버전 Global \ 접두사는 지원하지 않습니다.

또한 다른 사용자가 뮤텍스에 액세스 할 수 있도록하려면 각 CreateMutex() 호출에 특수 보안 설명자가 전달되어야합니다. C#에서 모든 사용자가 액세스 할 수있는 뮤텍스를 만들려면

, 참조 :
What is a good pattern for using a Global Mutex in C#?

요컨대, 당신의 C# 응용 프로그램의 코드가 있어야합니다 같은 :

const string mutexId = "MyProg"; 
MutexAccessRule allowEveryoneRule = 
    new MutexAccessRule(
     new SecurityIdentifier(WellKnownSidType.WorldSid, null), 
     MutexRights.FullControl, AccessControlType.Allow); 
MutexSecurity securitySettings = new MutexSecurity(); 
securitySettings.AddAccessRule(allowEveryoneRule); 

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 
{ 
    // Run your program here 
} 
finally 
{ 
    // These have to be called only after the application (its windows) closes. 
    // You can also remove these calls and let the system release the mutexes. 
    if (globalMutex != null) 
    { 
     globalMutex.Dispose(); 
    } 
    localMutex.Dispose(); 
} 

Inno 설치 측에서는 두 개의 뮤텍스를 모두 AppMutex directive에 나열하면됩니다.

[Setup] 
AppMutex=MyProg,Global\MyProg 

CreateMutexCheckForMutexes 전화는 InitializeSetup 기능에서 필요하지 않습니다.

+0

Martin, "답변"기능을 오용 한 것에 대해 사과드립니다. 나는 그것을 무지에서 해냈다. 그래서 오늘 아침에 제 제안서 코드에서 귀하의 제안을 빨리 정리했습니다. 그리고 Inno Setup 스크립트에서 "InitializeSetup"함수에서 mutex 코드를 제거하고 [Setup] 섹션에서 AppMutex 설정을 수정했습니다. 내 응용 프로그램을 설치하고 실행했습니다. 설치 프로그램을 다시 실행했지만 실행중인 응용 프로그램을 찾지 못했습니다. 그것은 계속하기 위해 필요한 파일을 사용하고있는 프로그램 (내 응용 프로그램)이 있음을 감지했습니다. 내가 누락 된 부분을 볼 수 없어? 다시 한 번 감사드립니다 ... – RETierney

+0

전체 프로그램이 어디에서 실행되고 있습니까? '// 프로그램을 실행하십시오'라는 코멘트가 있습니까? 간단한 콘솔 응용 프로그램을 만들고 그곳에'Console.ReadLine'을 넣으면 다른 세션에서 응용 프로그램을 실행하면 설치 프로그램이이를 완벽하게 감지합니다. –

+0

예. 그것은 당신이 지시 한 WPF 애플 리케이션입니다,'code' MainWindow mainWin = new MainWindow(); mainWin.Show();'code' 남자, 나는 엉망이된다. – RETierney

1

위대한 아이디어 마틴. 다음은 WPF에서 뮤텍스 개체를 사용하기위한 완벽한 솔루션입니다. 다른 뮤직 개체가 WPF 앱을 실행 중일 때도 Inno 설치 프로그램이 감지합니다. BTW. 나는 Visual Studio를 사용했다.

  1. 는 WPF 응용 프로그램 및 프로젝트 모두가 호출되는 것을 가정 'MyWPFApp'
  2. MyWPFApp에 대한 프로젝트 속성을 엽니 다; '응용 프로그램'탭에서 시작 개체가 'MyWPFApp.App'인지 확인하십시오.
  3. App.xaml의 Build Action을 ApplicationDefinition에서 Page로 변경하십시오.
  4. App.xaml에서 StartupUri 속성을 제거합니다 (사용중인 경우).
  5. Application.Startup 이벤트가 사용되는 경우 MainWindow를 인스턴스화하고 표시하는 코드를 제거하십시오.
  6. 다음 또는 이와 유사한 코드를 App.xaml.cs에 App 클래스의 일부로 추가하십시오.

    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 번호를 모두 뮤텍스에 대한 using 문을 사용하여 건축가에 코드를 시도,하지만 나는 두뇌를 가지고 얼다.

또는 Main 메서드를 사용하여 별도의 클래스를 만들고 위 코드를 배치 할 수 있습니다. 위의 4 단계와 5 단계가 필요하며 2 단계에서 시작 개체를 Main 메서드가 포함 된 새 클래스로 변경하십시오.

감사합니다. 당신이 https://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx에 따라 \ 세계적으로 접두사 때문에 그것을 잘 작동합니다 같은