TaskDialog fires exception: comctl32.dll in version 6 required
Asked Answered
M

3

7

I´m developing a modern WPF application. I want to use the TaskDialog, but I always get the common error:

TaskDialog feature needs to load version 6 of comctl32.dll but a different version is current loaded in memory.

I tried to add a manifest (which already contains the required dependency for the right comctl32.dll) and set it as default manifest in the project properties.

It still throws this exception :-/

My application is built like this: It´s a startup application (normal Windows application, non-wpf). It only has the "Program.cs" which is the entry point. There it load´s dynamically the real application (which is a library, not a WPF app project). It invokes it´s startup method which starts the application.

Works great, but I always get this exception. I guess it´s because of this startup-system ... but what would be a possible workaround to fix it?

Thanks a lot :)

R

Mention answered 15/4, 2013 at 16:23 Comment(4)
Why are you doing that? Why not just have a regular WPF application that starts by System.Windows.Application instead? I guess the winforms (or whatever you're loading previously) is loading a bunch of ancient crap WPF doesn't care about.Shimmer
Ok this system is a fragment of an bug I had earlier. I just changed the system. It now starts via an real WPF project. It still won´t work. If I activate "System own debugging", I don´t get any execption and the dialog opens. The only bug is: The icon is missing :-/ Could this perhaps be a issue in the MS Api Codepack?Mention
You are correct, it's a bug in the API itself: #22562084Ephrem
Possible duplicate of C#: comctl32.dll version 6 in debuggerEphrem
O
3

Maybe my solution will help you.

My C# "application" is a class library/dll used as a CustomAction for WIX. I wanted a TaskDialog instead of MessageBox but I ran into the same exception as you, and manifest files don't work for C# class libraries as far as I know. I had to use a combination of things to get my code to load the right version of comctl32.dll.

I just got it working so my code is a little messy and fatty.

Sources:

  1. http://truecheaters.com/f51/%5Bc-%5D-taskdialog-9368.html
  2. http://support.microsoft.com/kb/830033

1) Include the EnableThemingInScope class as-is from the second link above.

2) Include this modified TaskDialog enums/class:

[Flags]
public enum TaskDialogButtons {
    OK = 0x0001,
    Cancel = 0x0008,
    Yes = 0x0002,
    No = 0x0004,
    Retry = 0x0010,
    Close = 0x0020
}

public enum TaskDialogIcon {
    Information = UInt16.MaxValue - 2,
    Warning = UInt16.MaxValue,
    Stop = UInt16.MaxValue - 1,
    Question = 0,
    SecurityWarning = UInt16.MaxValue - 5,
    SecurityError = UInt16.MaxValue - 6,
    SecuritySuccess = UInt16.MaxValue - 7,
    SecurityShield = UInt16.MaxValue - 3,
    SecurityShieldBlue = UInt16.MaxValue - 4,
    SecurityShieldGray = UInt16.MaxValue - 8
}

public enum TaskDialogResult {
    None,
    OK,
    Cancel,
    Yes,
    No,
    Retry,
    Close
}

public class StatusDialog {
    #region API
    [DllImport( "comctl32.dll", CharSet = CharSet.Unicode )]
    public static extern int TaskDialog( IntPtr hWndParent, IntPtr hInstance, string pszWindowTitle, string pszMainInstruction, string pszContent, int dwCommonButtons, IntPtr pszIzon, out int pnButton );
    #endregion

    #region Modal
    public static TaskDialogResult Show( IWin32Window owner, string text ) {
        return Show( owner, text, null, null, TaskDialogButtons.OK );
    }

    public static TaskDialogResult Show( IWin32Window owner, string text, string instruction ) {
        return Show( owner, text, instruction, null, TaskDialogButtons.OK, 0 );
    }

    public static TaskDialogResult Show( IWin32Window owner, string text, string instruction, string caption ) {
        return Show( owner, text, instruction, caption, TaskDialogButtons.OK, 0 );
    }

    public static TaskDialogResult Show( IWin32Window owner, string text, string instruction, string caption, TaskDialogButtons buttons ) {
        return Show( owner, text, instruction, caption, buttons, 0 );
    }

    public static TaskDialogResult Show( IWin32Window owner, string text, string instruction, string caption, TaskDialogButtons buttons, TaskDialogIcon icon ) {
        return ShowInternal( owner.Handle, text, instruction, caption, buttons, icon );
    }
    #endregion

    #region Non-Modal
    public static TaskDialogResult Show( string text ) {
        return Show( text, null, null, TaskDialogButtons.OK );
    }

    public static TaskDialogResult Show( string text, string instruction ) {
        return Show( text, instruction, null, TaskDialogButtons.OK, 0 );
    }

    public static TaskDialogResult Show( string text, string instruction, string caption ) {
        return Show( text, instruction, caption, TaskDialogButtons.OK, 0 );
    }

    public static TaskDialogResult Show( string text, string instruction, string caption, TaskDialogButtons buttons ) {
        return Show( text, instruction, caption, buttons, 0 );
    }

    public static TaskDialogResult Show( string text, string instruction, string caption, TaskDialogButtons buttons, TaskDialogIcon icon ) {
        return ShowInternal( IntPtr.Zero, text, instruction, caption, buttons, icon );
    }
    #endregion

    #region Core Implementation
    private static TaskDialogResult ShowInternal( IntPtr owner, string text, string instruction, string caption, TaskDialogButtons buttons, TaskDialogIcon icon ) {
        int p;
        using ( new EnableThemingInScope( true ) ) {
            int resss = TaskDialog( owner, IntPtr.Zero, caption, instruction, text, (int) buttons, new IntPtr( (int) icon ), out p );
            if ( resss != 0 )
                throw new InvalidOperationException( "Something weird has happened." + resss.ToString() );
        }

        switch ( p ) {
            case 1:
                return TaskDialogResult.OK;
            case 2:
                return TaskDialogResult.Cancel;
            case 4:
                return TaskDialogResult.Retry;
            case 6:
                return TaskDialogResult.Yes;
            case 7:
                return TaskDialogResult.No;
            case 8:
                return TaskDialogResult.Close;
            default:
                return TaskDialogResult.None;
        }
    }
    #endregion
}

3. To call it, simply:

try {
    StatusDialog.Show( "About to test this...", "Heading I won't use.", "Dialog Title", TaskDialogButtons.OK );
} catch ( Exception e ) {
    MessageBox.Show( e.ToString(), "Error Found", MessageBoxButtons.OK );
}

4. Result:

enter image description here

Orit answered 11/5, 2013 at 5:45 Comment(4)
I get an exception that the entry point "TaskDialog" was not found in comctl.dll :-/ Also I don´t like the fact that this way locks the possibility to set controls like progress bars or something else :-/ But thanks for the answer :)Mention
Also i found this: #1415770 So maybe it´s a bug of Visual Studio itself. As I said, in Release mode it works fine (the only thing is the missing Icon)...Mention
@Razer for stuff like progress bars you'll have to use TaskDialogIndirect instead. Check out the source of that Windows® API Code Pack in \source\WindowsAPICodePack\Core\Interop\TaskDialogs\TaskDialogNativeMethods.cs. It's a lot more complex though so I don't have a simple solution. As for the exception, not sure what's going on. Make sure your DllImport line is exactly the same as what I have in step 2. If it's already like that... then I'm not sure :( . Youre welcome!Orit
Use the EnableThemingInScope class at https://mcmap.net/q/1424161/-c-comctl32-dll-version-6-in-debugger as it has fixes for what was once found at the now defunct kb/830033 link.Ephrem
S
3

Run the *.exe version of your program, and not the one for Visual Studio *.vshost.exe

To do so in Visual Studio, disable the flag in "Debug / Enable Debuggers / Enable the Visual Studio Hosting Process"

Seigel answered 19/9, 2013 at 13:9 Comment(3)
See also here: #2070440Seigel
Seems to be a logical answer to the problem... As long as I´m still able to debug the application, this should be a possible fix. I´ll test it soon.Mention
OK, that´s strange ... Now it works fine. I didn´t touch the project for about a half year. And now it just runs fine, without having to disable the hosting process. Maybe the problem was fixed with one of the many Windows/Visual Studio updates.Mention
P
0

I have found that if you run with permission "RequireAdministrator" it throws the exception, but does not throw exception if permission "AsInvoker". Just my observation. If your app requires administrator privileges then I am stumped

Palmieri answered 18/11, 2015 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.