我正在爲TaskDialog使用WindowsAPICodePack。當我嘗試顯示對話框時,它說它需要加載comctl32.dll的版本6。所以我在app.manifest中添加了第6版,並嘗試運行它。仍然沒有運氣。我去了調試文件夾,並運行沒有Visual Studio的程序,它工作正常。我猜Visual Studio沒有使用清單文件...我想知道是否有辦法讓它做到這一點。調試器中的C#:comctl32.dll版本6
6
A
回答
9
Rob pol86,您的代碼正在拋出SEHExceptions,因爲ActivateActCtx和DeactivateActCtx的簽名不正確。您必須使用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;
}
}
}
0
本頁面介紹如何添加自定義清單到您的項目,以告訴Windows加載新的comctl32.dll(版本6.0):
您是否有表現comctl32.dll的正確依賴關係?你嵌入了創建的清單嗎?
1
我在調試模式下遇到與Visual Studio相同的問題。到目前爲止,我還沒有找到解決方法,它在發佈模式下工作正常。
4
我最近遇到這個問題時CodePack中的TaskDialogDemo調試代碼。這是我如何修復它。使用這個的問題是,如果我打開兩個或三個對話框,它會拋出一個SEHException,我還沒有想出如何解決。所以買家要小心。
添加核心\互操作\ 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 核心\互操作\ 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);
}
相關問題
- 1. TaskDialog觸發異常:需要版本6中的comctl32.dll
- 2. 調試從C#調用VC++ 6 DLL#
- 3. C++調試版本
- 4. 在.NET中檢測COMCTL32版本
- 5. 在C++中使用調試/發行版本DLL
- 6. C++ DLL調試
- 7. Azure dll版本調試難度
- 8. 在VS2005中調試DLL(C++)
- 9. 在C中調試DLL#
- 10. 調試版本找不到調試運行時DLL
- 11. 如何繼承win32控件並保持與舊版本comctl32.dll的兼容性?
- 12. C#調試器攔截來自本地DLL的WriteConsole事件
- 13. 調試版運行,但版本提供0xc000007b - 缺少dll?
- 14. C#DLL版本衝突
- 15. C#版本控制dll/api
- 16. 調試安裝的版本 - C#
- 17. 如何調試C++ dll調用C++ DllImport
- 18. 調試底層C++ DLL中的問題
- 19. Ordinal未找到在XP上的ComCtl32.dll C++
- 20. 試用版6
- 21. 無法將「comctl32.dll」DLL加載到內存中,同時冒充
- 22. 從C#調試CUDA Dll#
- 23. 用C語言調試dll
- 24. JNA C DLL調試指南?
- 25. 的Qt發佈版本需要調試的DLL
- 26. 如何調試C++ dll的ctypes調用?
- 27. 輸入HTML版本的Facebook調試器
- 28. C#項目使用的C++ DLL調試
- 29. 使用不同的DLL進行調試和發佈版本
- 30. 發佈版本依賴於來自MFC的調試DLL
歡呼聲,這是正確的答案。沒有必要用這個來改變清單。 – 2014-05-20 15:16:48
+1正確答案。爲了將來的參考,我從這篇msdn知識庫文章中得到了一個類似的破解uint cookie實現:https://support.microsoft.com/en-us/kb/830033只是爲了清楚:我可以創建範圍,但後來我得到了一個SEH DeactivateActCtx異常。進一步的調試發現它是錯誤代碼6,這是ERROR_INVALID_HANDLE,因爲由於錯誤的類型,cookie不能用於正確地停用上下文。 – Samuel 2015-11-25 07:46:53
謝謝!我在發佈ClickOnce時遇到了comctl32.dll問題,並解決了這個問題 – dariusc 2016-04-25 17:20:56