Around and About .NET World

Il blog di Marco Minerva
posts - 1671, comments - 2232, trackbacks - 2135

My Links

News

Contattami su Live Messenger:


MCTS: Windows, Web, Distributed Applications & SQL Server

MCPD: Enterprise Applications

Tag Cloud

Archives

Post Categories

Links

Impedire l'esecuzione multipla di un'applicazione

Tavolta si ha l'esigenza di impedire l'esecuzione di più istanze della stessa applicazione. Visual Basic .NET, nella sua ultima versione, consente di aggiungere questa funzionalità semplicemente spuntando un'opzione del progetto. Con C#, invece, è necessario scrivere qualche riga di codice:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

namespace SpecialServices
{
    
//SingleProgamInstance uses a mutex synchronization object
    // to ensure that only one copy of process is running at
    // a particular time.  It also allows for UI identification
    // of the intial process by bring that window to the foreground.
    
public class SingleProgramInstance : IDisposable
    {
        
#region Platform Invoke

        
//Win32 API calls necesary to raise an unowned processs main window
        
[DllImport("user32.dll")] 
        
private static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll")] 
        
private static extern bool ShowWindowAsync(IntPtr hWnd,int nCmdShow);
        [DllImport("user32.dll")] 
        
private static extern bool IsIconic(IntPtr hWnd);

        
private const int SW_RESTORE = 9;

        
#endregion

        private 
Mutex processSync;

        
public SingleProgramInstance()
            : 
this(string.Empty)
        {
        }

        
public SingleProgramInstance(string identifier)
        {    
            processSync = 
new Mutex(false,
                Assembly.GetExecutingAssembly().GetName().Name + identifier);
        }

        ~SingleProgramInstance()
        {
            
//Release mutex (if necessary) 
            //This should have been accomplished using Dispose() 
            
this.Release();
        }

        
public bool IsSingleInstance
        {
            
get
            
{
                
if (processSync.WaitOne(0, false))
                    
return true;
                
else
                    return false
;
            }
        }

        
public void RaiseOtherProcess()
        {
            Process proc = Process.GetCurrentProcess();
            
// Using Process.ProcessName does not function properly when
            // the name exceeds 15 characters. Using the assembly name
            // takes care of this problem and is more accruate than other
            // work arounds.
            
string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
            
foreach (Process otherProc in Process.GetProcessesByName(assemblyName))
            {
                
//ignore this process
                
if (proc.Id != otherProc.Id)
                {
                    
// Found a "same named process".
                    // Assume it is the one we want brought to the foreground.
                    // Use the Win32 API to bring it to the foreground.
                    
IntPtr hWnd = otherProc.MainWindowHandle;
                    
if (IsIconic(hWnd))
                        ShowWindowAsync(hWnd,SW_RESTORE);
                    SetForegroundWindow(hWnd);
                    
return;
                }
            }
        }

        
#region Implementation of IDisposable

        private void 
Release()
        {
            
try
            
{
                
if (processSync.WaitOne(0, false))
                {
                    
//If we own the mutex then release it so that
                    // other "same" processes can now start.
                    
processSync.ReleaseMutex();
                }
                processSync.Close();
            }
            
catch { }
        }

        
public void Dispose()
        {
            
//release mutex (if necessary) and notify 
            // the garbage collector to ignore the destructor
            
this.Release();
            GC.SuppressFinalize(
this);
        }
    
        
#endregion
    
}
}

    

Questo codice fa uso di un oggetto Mutex per evitare che verificare se lo stesso processo è già in esecuzione: in questo caso, fornisce un metodo che consente di riportare la sua finestra in primo piano. Ecco un semplice esempio del suo utilizzo (da inserire nel metodo Main del file Program.cs):

using (SpecialServices.SingleProgramInstance spi = new SpecialServices.SingleProgramInstance())
{
    
if (spi.IsSingleInstance)
    {
        
//E' la prima esecuzione del programma.
        
Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(
false);
        Application.Run(
new Form1());
    }
    
else
    
{
        
//E' già attiva un'altra istanza del programma. La porta in primo piano.
        
spi.RaiseOtherProcess();
    }
}

Questo esempio di codice è stato realizzato prendendo spunto dal suggerimento pubblicato su UgiDotNet all'indirizzo http://www.ugidotnet.org/tips/tips_read.aspx?ID=79 da Gianluca Garucci, a cui va il mio ringraziamento.

powered by IMHO 1.3

Print | posted on Friday, July 7, 2006 10:32 AM | Filed Under [ C# ]

Feedback

Gravatar

# re: Impedire l'esecuzione multipla di un'applicazione

Grazie per la segnalazione! Ho già provveduto ad aggiornare il post con l'informazione corretta circa la sua provenienza!
7/7/2006 12:07 PM | Marco Minerva
Gravatar

# re: Impedire l'esecuzione multipla di un'applicazione

A dire il vero non l'ho mai provato con account che non fosse Administrator. Appena posso ci do un'occhiata, grazie per la segnalazione!
7/7/2006 5:55 PM | Marco Minerva
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET