2009-09-12 12 views
6

Ich verwende die WindowsAPICodePack für TaskDialog. Wenn ich versuche, den Dialog anzuzeigen, sagt es, dass es Version 6 von comctl32.dll laden muss. Also habe ich Version 6 zum app.manifest hinzugefügt und versucht, es auszuführen. Immer noch kein Glück. Ich ging in den Ordner Debug und führte das Programm ohne Visual Studio und es funktioniert gut. Ich nehme an, dass Visual Studio die Manifest-Datei nicht verwendet ... Ich habe mich gefragt, ob es einen Weg gibt, es zu tun.C#: comctl32.dll Version 6 im Debugger

Antwort

9

Rob pol86, Ihr Code wirft SEHExceptions, weil die Signaturen für ActivateActCtx und DeactivateActCtx nicht korrekt sind. Sie müssen UIntPtr anstelle von uint für den lpCookie verwenden.

daher der richtige Code für EnableThemingInScope.cs wäre:

using System; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Security.Permissions; 
using System.Windows.Forms; 

namespace Microsoft.WindowsAPICodePack.Dialogs 
{ 
    /// http://support.microsoft.com/kb/830033 
    /// <devdoc> 
    ///  This class is intended to use with the C# 'using' statement in 
    ///  to activate an activation context for turning on visual theming at 
    ///  the beginning of a scope, and have it automatically deactivated 
    ///  when the scope is exited. 
    /// </devdoc> 

    [SuppressUnmanagedCodeSecurity] 
    internal class EnableThemingInScope : IDisposable 
    { 
     // Private data 
     private UIntPtr cookie; 
     private static ACTCTX enableThemingActivationContext; 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] 
     private static IntPtr hActCtx; 
     private static bool contextCreationSucceeded = false; 

     public EnableThemingInScope(bool enable) 
     { 
      cookie = UIntPtr.Zero; 
      if (enable && OSFeature.Feature.IsPresent(OSFeature.Themes)) 
      { 
       if (EnsureActivateContextCreated()) 
       { 
        if (!ActivateActCtx(hActCtx, out cookie)) 
        { 
         // Be sure cookie always zero if activation failed 
         cookie = UIntPtr.Zero; 
        } 
       } 
      } 
     } 

     ~EnableThemingInScope() 
     { 
      Dispose(); 
     } 

     void IDisposable.Dispose() 
     { 
      Dispose(); 
      GC.SuppressFinalize(this); 
     } 

     private void Dispose() 
     { 
      if (cookie != UIntPtr.Zero) 
      { 
       try 
       { 
        if (DeactivateActCtx(0, cookie)) 
        { 
         // deactivation succeeded... 
         cookie = UIntPtr.Zero; 
        } 
       } 
       catch (SEHException) 
       { 
        //Hopefully solved this exception 
       } 
      } 
     } 

     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")] 
     private static bool EnsureActivateContextCreated() 
     { 
      lock (typeof(EnableThemingInScope)) 
      { 
       if (!contextCreationSucceeded) 
       { 
        // Pull manifest from the .NET Framework install 
        // directory 

        string assemblyLoc = null; 

        FileIOPermission fiop = new FileIOPermission(PermissionState.None); 
        fiop.AllFiles = FileIOPermissionAccess.PathDiscovery; 
        fiop.Assert(); 
        try 
        { 
         assemblyLoc = typeof(Object).Assembly.Location; 
        } 
        finally 
        { 
         CodeAccessPermission.RevertAssert(); 
        } 

        string manifestLoc = null; 
        string installDir = null; 
        if (assemblyLoc != null) 
        { 
         installDir = Path.GetDirectoryName(assemblyLoc); 
         const string manifestName = "XPThemes.manifest"; 
         manifestLoc = Path.Combine(installDir, manifestName); 
        } 

        if (manifestLoc != null && installDir != null) 
        { 
         enableThemingActivationContext = new ACTCTX(); 
         enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX)); 
         enableThemingActivationContext.lpSource = manifestLoc; 

         // Set the lpAssemblyDirectory to the install 
         // directory to prevent Win32 Side by Side from 
         // looking for comctl32 in the application 
         // directory, which could cause a bogus dll to be 
         // placed there and open a security hole. 
         enableThemingActivationContext.lpAssemblyDirectory = installDir; 
         enableThemingActivationContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; 

         // Note this will fail gracefully if file specified 
         // by manifestLoc doesn't exist. 
         hActCtx = CreateActCtx(ref enableThemingActivationContext); 
         contextCreationSucceeded = (hActCtx != new IntPtr(-1)); 
        } 
       } 

       // If we return false, we'll try again on the next call into 
       // EnsureActivateContextCreated(), which is fine. 
       return contextCreationSucceeded; 
      } 
     } 

     // All the pinvoke goo... 
     [DllImport("Kernel32.dll")] 
     private extern static IntPtr CreateActCtx(ref ACTCTX actctx); 
     [DllImport("Kernel32.dll")] 
     private extern static bool ActivateActCtx(IntPtr hActCtx, out UIntPtr lpCookie); 
     [DllImport("Kernel32.dll")] 
     private extern static bool DeactivateActCtx(uint dwFlags, UIntPtr lpCookie); 

     private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004; 

     private struct ACTCTX 
     { 
      public int cbSize; 
      public uint dwFlags; 
      public string lpSource; 
      public ushort wProcessorArchitecture; 
      public ushort wLangId; 
      public string lpAssemblyDirectory; 
      public string lpResourceName; 
      public string lpApplicationName; 
     } 
    } 
} 
+0

Cheers, dann ist dies die richtige Antwort. Keine Notwendigkeit, Manifest damit zu ändern. –

+0

+1 Für die richtige Antwort. Für zukünftige Referenz hatte ich eine ähnliche gebrochene Cookie-Implementierung von diesem msdn Knowledge Base-Artikel: https://support.microsoft.com/en-us/kb/830033 nur aus Gründen der Klarheit: Ich könnte den Umfang erstellen, aber dann habe ich ein SEH Ausnahme auf DeactivateActCtx. Weiteres Debugging ergab, dass es der Fehlercode 6 war, nämlich ERROR_INVALID_HANDLE, da der Cookie nicht dazu verwendet werden konnte, den Kontext aufgrund seines falschen Typs zu deaktivieren. – Samuel

+0

Danke! Ich hatte Probleme mit comctl32.dll beim Veröffentlichen von ClickOnce, und dies löste es – dariusc

0

Diese Seite beschreibt, wie ein benutzerdefiniertes Manifest zu einem Projekt hinzuzufügen, um Windows mitzuteilen, die neue comctl32.dll (Version 6.0) zu laden:

Hat Ihr Manifest haben die richtige Abhängigkeit von comctl32.dll? Hast du das erstellte Manifest eingebettet?

1

Ich habe das gleiche Problem mit Visual Studio im Debug-Modus. Bisher habe ich keine Problemumgehung gefunden, es funktioniert gut im Freigabemodus.

4

Ich bin kürzlich auf dieses Problem beim Debuggen von Code mit dem TaskDialogDemo im CodePack gestoßen. So habe ich es irgendwie behoben. Das Problem bei der Verwendung dieses ist, wenn ich zwei oder drei Dialoge öffne, wirft es eine SEHException, die ich nicht herausgefunden habe, wie man repariert. Also Vorsicht, Vorsicht.

hinzufügen Core \ Interop \ TaskDialogs \ EnableThemingInScope.cs:

using System; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Security.Permissions; 
using System.Windows.Forms; 

namespace Microsoft.WindowsAPICodePack.Dialogs { 
    /// http://support.microsoft.com/kb/830033 
    /// <devdoc> 
    ///  This class is intended to use with the C# 'using' statement in 
    ///  to activate an activation context for turning on visual theming at 
    ///  the beginning of a scope, and have it automatically deactivated 
    ///  when the scope is exited. 
    /// </devdoc> 

    [SuppressUnmanagedCodeSecurity] 
    internal class EnableThemingInScope : IDisposable { 
     // Private data 
     private uint cookie; 
     private static ACTCTX enableThemingActivationContext; 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] 
     private static IntPtr hActCtx; 
     private static bool contextCreationSucceeded = false; 

     public EnableThemingInScope(bool enable) { 
      cookie = 0; 
      if (enable && OSFeature.Feature.IsPresent(OSFeature.Themes)) { 
       if (EnsureActivateContextCreated()) { 
        if (!ActivateActCtx(hActCtx, out cookie)) { 
         // Be sure cookie always zero if activation failed 
         cookie = 0; 
        } 
       } 
      } 
     } 

     ~EnableThemingInScope() { 
      Dispose(); 
     } 

     void IDisposable.Dispose() { 
      Dispose(); 
      GC.SuppressFinalize(this); 
     } 

     private void Dispose() { 
      if (cookie != 0) { 
       try { 
        if (DeactivateActCtx(0, cookie)) { 
         // deactivation succeeded... 
         cookie = 0; 
        } 
       } catch (SEHException) { 
        // Robpol86: I don't know how to fix this! 
       } 
      } 
     } 

     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")] 
     private static bool EnsureActivateContextCreated() { 
      lock (typeof(EnableThemingInScope)) { 
       if (!contextCreationSucceeded) { 
        // Pull manifest from the .NET Framework install 
        // directory 

        string assemblyLoc = null; 

        FileIOPermission fiop = new FileIOPermission(PermissionState.None); 
        fiop.AllFiles = FileIOPermissionAccess.PathDiscovery; 
        fiop.Assert(); 
        try { 
         assemblyLoc = typeof(Object).Assembly.Location; 
        } finally { 
         CodeAccessPermission.RevertAssert(); 
        } 

        string manifestLoc = null; 
        string installDir = null; 
        if (assemblyLoc != null) { 
         installDir = Path.GetDirectoryName(assemblyLoc); 
         const string manifestName = "XPThemes.manifest"; 
         manifestLoc = Path.Combine(installDir, manifestName); 
        } 

        if (manifestLoc != null && installDir != null) { 
         enableThemingActivationContext = new ACTCTX(); 
         enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX)); 
         enableThemingActivationContext.lpSource = manifestLoc; 

         // Set the lpAssemblyDirectory to the install 
         // directory to prevent Win32 Side by Side from 
         // looking for comctl32 in the application 
         // directory, which could cause a bogus dll to be 
         // placed there and open a security hole. 
         enableThemingActivationContext.lpAssemblyDirectory = installDir; 
         enableThemingActivationContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; 

         // Note this will fail gracefully if file specified 
         // by manifestLoc doesn't exist. 
         hActCtx = CreateActCtx(ref enableThemingActivationContext); 
         contextCreationSucceeded = (hActCtx != new IntPtr(-1)); 
        } 
       } 

       // If we return false, we'll try again on the next call into 
       // EnsureActivateContextCreated(), which is fine. 
       return contextCreationSucceeded; 
      } 
     } 

     // All the pinvoke goo... 
     [DllImport("Kernel32.dll")] 
     private extern static IntPtr CreateActCtx(ref ACTCTX actctx); 
     [DllImport("Kernel32.dll")] 
     private extern static bool ActivateActCtx(IntPtr hActCtx, out uint lpCookie); 
     [DllImport("Kernel32.dll")] 
     private extern static bool DeactivateActCtx(uint dwFlags, uint lpCookie); 

     private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004; 

     private struct ACTCTX { 
      public int cbSize; 
      public uint dwFlags; 
      public string lpSource; 
      public ushort wProcessorArchitecture; 
      public ushort wLangId; 
      public string lpAssemblyDirectory; 
      public string lpResourceName; 
      public string lpApplicationName; 
     } 
    } 
} 

Dann in Core \ Interop \ TaskDialogs \ NativeTaskDialog.cs auf der Linie 93 (oben HResult hresult = TaskDialogNativeMethods.TaskDialogIndirect) Lassen Sie die Sektion wie folgt aussehen (am Ende werden Sie drei neue Linien haben):