在 C# 控制台应用程序的任务栏按钮中显示进度栏

Show progress bar in C# console application's taskbar button

提问人:Inbox 提问时间:11/2/2023 更新时间:11/2/2023 访问量:40

问:

我想在控制台应用程序的任务栏按钮中显示进度,就像复制文件时 Windows 资源管理器一样。

对于“任务栏按钮”,我指的是任务栏上代表打开程序的空间。

我指的不是控制台窗口中进度条本身的文本表示形式。

我使用的是 .Net 7,而不是使用 WPF 或 WinForms。

我阅读了以下问题,这些问题没有回答我的:

我有以下代码,我发誓几年前曾经工作过:

public enum TaskbarStates
{
    NoProgress = 0,
    Indeterminate = 0x1,
    Normal = 0x2,
    Error = 0x4,
    Paused = 0x8
}

[ComImport()]
[Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ITaskbarList3
{
    // ITaskbarList
    [PreserveSig]
    void HrInit();
    [PreserveSig]
    void AddTab(IntPtr hwnd);
    [PreserveSig]
    void DeleteTab(IntPtr hwnd);
    [PreserveSig]
    void ActivateTab(IntPtr hwnd);
    [PreserveSig]
    void SetActiveAlt(IntPtr hwnd);

    // ITaskbarList2
    [PreserveSig]
    void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);

    // ITaskbarList3
    [PreserveSig]
    void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);

    [PreserveSig]
    void SetProgressState(IntPtr hwnd, TaskbarStates state);
}

[ComImport()]
[Guid("56fdf344-fd6d-11d0-958a-006097c9a090")]
[ClassInterface(ClassInterfaceType.None)]
private class TaskbarInstance { }

private static readonly ITaskbarList3 taskbarInstance = (ITaskbarList3)new TaskbarInstance();
private static readonly bool taskbarSupported = Environment.OSVersion.Version >= new Version(6, 1);

public static void SetState(TaskbarStates taskbarState)
{
    IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
    if (taskbarSupported)
        taskbarInstance.SetProgressState(handle, taskbarState);
}

public static void SetValue(double progressValue, double progressMax)
{
    IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
    if (taskbarSupported)
        taskbarInstance.SetProgressValue(handle, (ulong)progressValue, (ulong)progressMax);
}

我会像这样使用代码:

SetState(TaskbarStates.Normal);
SetValue(20, 30);

但是,现在这什么也没做。我尝试了所有状态和值,并等待按键以确保消息已发布,并且不会因我在代码中设置断点而扭曲。

考虑到可能是句柄没有被正确捕获,我也尝试将句柄替换为:IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;

const int STD_OUTPUT_HANDLE = -11;

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);

IntPtr handle = GetStdHandle(STD_OUTPUT_HANDLE);

但这也行不通。

我做错了什么?

C# 控制台应用程序 任务栏 窗口句柄

评论


答:

2赞 Inbox 11/2/2023 #1

像往常一样,在发布问题 5 分钟后,我得到了答案。

我不知道为什么既没有工作也没有工作,但确实有效是:GetStdHandle(STD_OUTPUT_HANDLE)Process.GetCurrentProcess().MainWindowHandle

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

IntPtr handle = GetConsoleWindow();

一旦窗户把手正确,一切都很好。