J'utilise windowsapicodepack pour TaskDialog. Lorsque j'essaie d'afficher la boîte de dialogue, il dit qu'il doit charger la version 6 de comctl32.dll. J'ai donc ajouté la version 6 à l'application.Manifest et essayé de l'exécuter. Toujours pas de chance. Je suis allé au dossier de débogage et j'ai dirigé le programme sans Visual Studio et ça marche bien. Je suppose que Visual Studio n'utilise pas le fichier manifeste ... Je me demandais s'il y avait un moyen de faire cela. P>
4 Réponses :
Cette page explique comment ajouter un manifeste personnalisé à votre projet afin de dire Windows de charger le nouveau comctl32.dll (version 6.0): p>
Votre manifeste a-t-il la bonne dépendance sur le comcl32.dll? Avez-vous incorporé le manifeste créé? P>
J'ai le même problème avec Visual Studio en mode débogage. Jusqu'à présent, je n'ai pas trouvé de solution de contournement, cela fonctionne bien en mode de sortie. P>
J'ai récemment rencontré ce problème lors du débogage du code avec le Taskdialogdemo dans le Codepack. C'est comme ça que je suis un peu corrigé. Le problème avec l'utilisation de ceci est si j'ouvre deux ou trois boîtes de dialogue, il jette une impression SEHException, que je n'ai pas compris comment réparer. Donc, l'acheteur méfiez-vous.
Ajouter // Here is the way we use "vanilla" P/Invoke to call TaskDialogIndirect().
HResult hresult;
using ( new EnableThemingInScope( true ) ) {
hresult = TaskDialogNativeMethods.TaskDialogIndirect(
nativeDialogConfig,
out selectedButtonId,
out selectedRadioButtonId,
out checkBoxChecked );
}
Robpol86, votre code jette des idées SEhExceptions, car les signatures pour ActivateACCTX et DIFCTICTICTICTTEACTX ne sont pas correctes. Vous devez utiliser Par conséquent, le code correct pour Enabletheminginscope.cs serait: P> uintptr code> au lieu de uint code> pour le lpcookie. 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;
}
}
}
Bravo, c'est la bonne réponse. Pas besoin de changer de manifeste avec cela.
+1 pour une réponse correcte. Pour une référence future, j'avais une implémentation similaire de cookie Uint brisée de cet article de la base de connaissances MSDN: Support. microsoft.com/en-us/kb/830033 juste pour la clarté: je pourrais créer la portée, mais j'ai ensuite eu une exception SEH sur DEACTICTIVATEACTXTX. Le débogage supplémentaire a révélé que c'était du code d'erreur 6, qui est ERROR_INVALID_HANDLE, car le cookie n'a pas pu être utilisé pour désactiver le contexte correctement dû au fait son mauvais type.
Merci! J'avais des difficultés avec Comctl32.dll lors de la publication ClickOnce, et cela résouda
Pourrions-nous ajouter le message d'erreur exact dans la question de sorte que Google mène ici pour cela? Cela a eu la bonne réponse pour moi, mais je n'ai trouvé que de vagues les mentions dans d'autres discussions et devait éventuellement chercher "Enabletheminginscope" pour arriver ici. Voici les messages d'erreur pour Google's Crowlers: "La fonctionnalité TaskDialog doit charger la version 6 de comctl32.dll, mais une version différente est chargée en mémoire" avec exception intérieure "Impossible de trouver un point d'entrée nommé" TaskDialogindirect "dans dll 'comctl32.dll '. "