C#:调试器中的 comctl32.dll 版本 6

发布于 2024-08-05 00:38:15 字数 299 浏览 10 评论 0原文

我正在为 TaskDialog 使用 WindowsAPICodePack 。当我尝试显示该对话框时,它说需要加载 comctl32.dll 的版本 6。所以我将版本 6 添加到 app.manifest 并尝试运行它。还是没有运气。我进入 Debug 文件夹并在没有 Visual Studio 的情况下运行该程序,它工作正常。我猜测 Visual Studio 没有使用清单文件...我想知道是否有办法让它做到这一点。

I'm using the WindowsAPICodePack for TaskDialog. When I try to show the dialog it says that it needs to load version 6 of comctl32.dll. So I added version 6 to the app.manifest and tried running it. Still no luck. I went to the Debug folder and ran the program without Visual Studio and it works fine. I'm guessing that Visual Studio isn't using the manifest file... I was wondering if there was a way to make it do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

丶情人眼里出诗心の 2024-08-12 00:38:15

Robpol86,您的代码抛出 SEHExceptions,因为 ActivateActCtx 和 DeactivateActCtx 的签名不正确。对于 lpCookie,您必须使用 UIntPtr 而不是 uint

因此,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 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;
        }
    }
}

Robpol86, your code is throwing SEHExceptions, because the signatures for ActivateActCtx and DeactivateActCtx are not correct. You have to use UIntPtr instead of uint for the lpCookie.

Therefore, the correct code for EnableThemingInScope.cs would be:

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;
        }
    }
}
粉红×色少女 2024-08-12 00:38:15

我最近在使用 CodePack 中的 TaskDialogDemo 调试代码时遇到了这个问题。这就是我修复它的方法。使用这个的问题是,如果我打开两个或三个对话框,它会抛出一个 SEHException,我还没有弄清楚如何修复。所以买家要小心。

添加 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;
        }
    }
}

然后在第 93 行的 Core\Interop\TaskDialogs\NativeTaskDialog.cs 中(上方 HResult hresult = TaskDialogNativeMethods.TaskDialogIndirect )使该部分看起来像这样(最后你将有三行新行):

// 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 );
}

I recently ran into this problem when debugging code with the TaskDialogDemo in the CodePack. This is how I kind of fixed it. The problem with using this is if I open two or three dialogs it throws an SEHException, which I haven't figured out how to fix. So buyer beware.

Add 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;
        }
    }
}

Then in Core\Interop\TaskDialogs\NativeTaskDialog.cs on line 93 (above HResult hresult = TaskDialogNativeMethods.TaskDialogIndirect) make the section look like this (in the end you will have three new lines):

// 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 );
}
情话已封尘 2024-08-12 00:38:15

本页介绍如何向项目添加自定义清单,以便告诉 Windows 加载新的 comctl32.dll(版本 6.0):

您的清单是否对 comctl32.dll 具有正确的依赖关系?您是否嵌入了创建的清单?

This page describes how to add a custom manifest to your project in order to tell Windows to load the new comctl32.dll (version 6.0):

Does your manifest have the right dependency on comctl32.dll? Did you embed the created manifest?

三生路 2024-08-12 00:38:15

我在调试模式下使用 Visual Studio 时遇到同样的问题。到目前为止我还没有找到解决方法,它在发布模式下工作得很好。

I have the same issue with Visual Studio in Debug mode. So far I haven't found a workaround, it works fine in Release mode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文