2009-12-15 5 views
0

J'ai réussi à créer un mutex .net comme ceci: SingleIns = new Mutex (true, AppName); pendant un moment. Cela fonctionne dans XP, Vista, mais apparemment pas dans Windows7. J'ai donc besoin de faire un appel interop à une bibliothèque Win32 pour que d'autres composants Com puissent identifier le mutex. J'ai trouvé le code suivant, mais le Win32Calls. n'est pas trouvé ... existe-t-il un assemblage ou une référence dont j'ai besoin? Merci à l'avance,Comment appeler win32 CreateMutex à partir de .Net

code trouvé de: http://www.pinvoke.net/default.aspx/kernel32/CreateMutex.html

utilisant System.Runtime.InteropServices;

[DllImport("kernel32.dll")] 
    public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName); 


     // create IntPtrs for use with CreateMutex() 
     IntPtr ipMutexAttr = new IntPtr(0); 
     IntPtr ipHMutex = new IntPtr(0); 

     try 
     { 
      // Create the mutex and verify its status BEFORE construction 
      // of the main form. 

      ipHMutex = Win32Calls.CreateMutex(ipMutexAttr, 
       true, "CompanyName_AppName_MUTEX"); 

      if (ipHMutex != (IntPtr)0) 
      { 
       // check GetLastError value (MUST use this call. See MSDN) 

       int iGLE = Marshal.GetLastWin32Error(); 

       // if we get the ERROR_ALREADY_EXISTS value, there is 
       // already another instance of this application running. 

       if (iGLE == Win32Calls.ERROR_ALREADY_EXISTS) 
        // So, don't allow this instance to run. 
        return; 
      } 
      else  
      { // CreateMutex() failed. 
       // once the app is up and running, I log the failure from 
       // within the frmMain constructor. 
       bool m_bMutexFailed = true; 
      } 

      // construct the main form object and 
      //form = new frmMain(); 

      // run the app. 
      //Application.Run(form); 

     } 
     catch(Exception oEx) 
     { 
      //...handle it... 
     } 
     finally 
     { 
      // release the mutex 
      if (ipHMutex != (IntPtr)0) 
       Win32Calls.ReleaseMutex(ipHMutex); 

      // cleanup the main form object instance. 
      if (form != null) { 
       form.Dispose(); 
      } 
     } 
    } 
+0

Hmm. Je viens de supprimer la partie Win32Calls de Win32Calls.CreateMutex et appelé directement CreateMutex ... il semble que cela pourrait fonctionner – mytwocents

+0

Êtes-vous sur une version 64 bits de Windows 7? Un .NET 'Mutex' devrait essentiellement fonctionner de la même manière dans Windows 7 que dans les versions précédentes. –

+0

Ceci est une meilleure référence ... http://msdn.microsoft.com/fr-fr/library/microsoft.win32.safehandles.safewaithandle.aspx – mytwocents

Répondre

2

Il ne fonctionne pas est parce que vous déclaration CreateMutex est pas dans l'espace de noms Win32Calls. Votre problème suivant est que cela ne fonctionnera toujours pas car vous avez oublié de définir la propriété SetLastError dans l'attribut [DllImport]. Obligatoire pour que Marshal.GetLastWin32Error() renvoie l'erreur.

Rembobiner un bit, en utilisant la classe Mutex dans Win7 devrait fonctionner sans problème. Le seul mode de défaillance auquel je peux penser n'est pas de préfixer le nom de mutex avec "Global", donc le mutex est visible dans toutes les sessions. C'est un peu distant.

Plus précisément, vous essayez de faire quelque chose qui est déjà très bien supporté dans le framework .NET. Projet + Ajouter une référence, sélectionnez Microsoft.VisualBasic. Faites votre code Program.cs ressembler à ceci:

using System; 
using System.Windows.Forms; 
using Microsoft.VisualBasic.ApplicationServices; 

namespace WindowsFormsApplication1 { 
    class Program : WindowsFormsApplicationBase { 
    [STAThread] 
    static void Main(string[] args) { 
     var prog = new Program(); 
     prog.EnableVisualStyles = true; 
     prog.IsSingleInstance = true; 
     prog.MainForm = new Form1(); 
     prog.Run(args); 
    } 
    } 
} 

goodies bonus avec cette approche est qu'il règle automatiquement la mise au point à l'instance en cours d'exécution de votre programme lorsque l'utilisateur commence à nouveau. Et vous pouvez remplacer la méthode OnStartupNextInstance pour savoir quels arguments de ligne de commande ont été utilisés et répondre en conséquence.

1

Dans le cas où cela pourrait vous aider, le .NET Framework fournit déjà un wrapper de l'objet Win32 mutex. Voir System.Threading.Mutex. Toutes les principales fonctionnalités sont là, y compris la possibilité d'utiliser des préfixes comme "Global".

+0

Le problème est le .Net Mutex qui fonctionne pour XP et Vista, n'est pas détecté par un programme non géré (C++) pour Windows 7. Sur Windows 7, GetLastError() renvoie toujours ERROR_SUCCESS si le mutex existe ou non. Donc, j'essaye de changer la façon dont j'appelle le mutex pour accommoder le code C++ natif. NOTE: le .net mutex to .net fonctionne bien sur Windows 7. Le mutex .Net pour interopérer C++ mutex est ce qui échoue ... pourrait être du côté C++. – mytwocents

+0

Je pense que le problème n'est pas que le mutex n'est pas créé de manière globalement reconnue dans Windows 7 depuis qu'un service le crée. J'ai ajouté "Global \" au nom du mutex, car certains messages indiquaient que cela fonctionnait pour eux. Cependant, cela ne fonctionne pas pour moi non plus. (Le mutex créé par le service n'apparaît pas dans le handle de find de ProcessExplorer, mais je sais qu'il est là parce que si je cours le même programme, le mutex est déjà créé.) Microsoft, que se passe-t-il avec les services et les mutextes? – mytwocents

Questions connexes