C#: Debugger에서 Comctl32.dll 버전 6
-
06-07-2019 - |
문제
나는 사용하고있다 WindowsApicodepack TaskDialog의 경우. 대화 상자를 표시하려고하면 comctl32.dll의 버전 6을로드해야한다고 말합니다. 그래서 나는 app.manifest에 버전 6을 추가하고 실행을 시도했습니다. 여전히 운이 없습니다. 디버그 폴더에 가서 Visual Studio없이 프로그램을 운영했으며 잘 작동합니다. Visual Studio가 Manifest 파일을 사용하지 않는다고 생각합니다 ...이를 수행 할 수있는 방법이 있는지 궁금합니다.
해결책
ROBPOL86, CODE는 ActiveActctx 및 DeactivateActctx의 서명이 올바르지 않기 때문에 sehexceptions를 던지고 있습니다. 당신은 사용해야합니다 UIntPtr
대신에 uint
lpcookie를 위해.
따라서 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;
}
}
}
다른 팁
나는 최근 코드가 코드에서 코드를 디버깅 할 때이 문제를 해결했다. 이것이 내가 그것을 고정시키는 방법입니다. 이것을 사용하는 데있어 문제는 2 ~ 3 개의 대화 상자를 열면 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;
}
}
}
그런 다음 Core Interop TaskDialogs nativetaskdialog.cs 93 행에 (위 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 );
}
디버그 모드에서 Visual Studio와 동일한 문제가 있습니다. 지금까지 나는 해결 방법을 찾지 못했고 릴리스 모드에서 잘 작동합니다.
이 페이지는 Windows에 새로운 comctl32.dll (버전 6.0)을로드하도록 지시하기 위해 프로젝트에 사용자 정의 매니페스트를 추가하는 방법에 대해 설명합니다.
당신의 매니페스트는 comctl32.dll에 올바른 의존성을 가지고 있습니까? 생성 된 매니페스트를 포함 시켰습니까?