我想在控制台应用程序的任务栏按钮中显示进度,就像复制文件时 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);
但这也行不通。
我做错了什么?
正如往常一样,发布问题 5 分钟后我就得到了答案。
我不知道为什么
GetStdHandle(STD_OUTPUT_HANDLE)
和 Process.GetCurrentProcess().MainWindowHandle
都不起作用,但起作用的是:
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
IntPtr handle = GetConsoleWindow();
一旦窗口句柄正确,一切就OK了。