在 PowerShell 中分离新表单的任务栏图标

Rob*_*ere 5 powershell winforms

当您在 PowerShell 中创建 Windows 窗体时,即使您更改窗体的图标,它也会与主机控制台窗口分组。

如何将新表单的任务栏图标与 PowerShell 控制台图标分开?

左边发生了什么,右边是期望的效果: 在此输入图像描述

示例代码:

[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(300,200)
$form.ShowInTaskbar = $true
$form.Icon = New-Object system.drawing.icon 'c:\icon.ico'
$form.Text = 'New taskbar icon plz'

$form.BringToFront()
$form.ShowDialog()
Run Code Online (Sandbox Code Playgroud)

我看到的唯一有点帮助的是一个参考,更改“应用程序 ID”会将其分开,但参考都是 C 代码。

https://msdn.microsoft.com/en-us/magazine/dd942846.aspx

请给出 PowerShell 答案,或者如果答案包含 C# 代码或对其他 API 的调用,请解释它们在 PowerShell 中的工作原理。

Tes*_*ler 6

在从互联网上通过 C# 魔法拼凑出大量 P/Invoke 后(大部分来自此处,一些来自此处),我最终通过以下方法添加了一种类型,您可以使用以下方法[PSAppID]::SetAppIdForWindow($form.handle, "Your.AppId")

\n
$signature = @\'\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Runtime.InteropServices.ComTypes;\n\npublic class PSAppID\n{\n    // https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/\n    // IPropertyStore Interface\n    [ComImport,\n        InterfaceType(ComInterfaceType.InterfaceIsIUnknown),\n        Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]\n    private interface IPropertyStore\n    {\n        uint GetCount([Out] out uint cProps);\n        uint GetAt([In] uint iProp, out PropertyKey pkey);\n        uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);\n        uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);\n        uint Commit();\n    }\n\n\n    // PropertyKey Structure\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct PropertyKey\n    {\n        private Guid formatId;    // Unique GUID for property\n        private Int32 propertyId; // Property identifier (PID)\n\n        public Guid FormatId\n        {\n            get\n            {\n                return formatId;\n            }\n        }\n\n        public Int32 PropertyId\n        {\n            get\n            {\n                return propertyId;\n            }\n        }\n\n        public PropertyKey(Guid formatId, Int32 propertyId)\n        {\n            this.formatId = formatId;\n            this.propertyId = propertyId;\n        }\n\n        public PropertyKey(string formatId, Int32 propertyId)\n        {\n            this.formatId = new Guid(formatId);\n            this.propertyId = propertyId;\n        }\n\n    }\n\n\n    // PropVariant Class (only for string value)\n    [StructLayout(LayoutKind.Explicit)]\n    public class PropVariant : IDisposable\n    {\n        [FieldOffset(0)]\n        ushort valueType;     // Value type\n\n        // [FieldOffset(2)]\n        // ushort wReserved1; // Reserved field\n        // [FieldOffset(4)]\n        // ushort wReserved2; // Reserved field\n        // [FieldOffset(6)]\n        // ushort wReserved3; // Reserved field\n\n        [FieldOffset(8)]\n        IntPtr ptr;           // Value\n\n\n        // Value type (System.Runtime.InteropServices.VarEnum)\n        public VarEnum VarType\n        {\n            get { return (VarEnum)valueType; }\n            set { valueType = (ushort)value; }\n        }\n\n        public bool IsNullOrEmpty\n        {\n            get\n            {\n                return (valueType == (ushort)VarEnum.VT_EMPTY ||\n                        valueType == (ushort)VarEnum.VT_NULL);\n            }\n        }\n\n        // Value (only for string value)\n        public string Value\n        {\n            get\n            {\n                return Marshal.PtrToStringUni(ptr);\n            }\n        }\n\n\n        public PropVariant()\n        { }\n\n        public PropVariant(string value)\n        {\n            if (value == null)\n                throw new ArgumentException("Failed to set value.");\n\n            valueType = (ushort)VarEnum.VT_LPWSTR;\n            ptr = Marshal.StringToCoTaskMemUni(value);\n        }\n\n        ~PropVariant()\n        {\n            Dispose();\n        }\n\n        public void Dispose()\n        {\n            PropVariantClear(this);\n            GC.SuppressFinalize(this);\n        }\n\n    }\n\n    [DllImport("Ole32.dll", PreserveSig = false)]\n    private extern static void PropVariantClear([In, Out] PropVariant pvar);\n\n\n    [DllImport("shell32.dll")]\n    private static extern int SHGetPropertyStoreForWindow(\n        IntPtr hwnd,\n        ref Guid iid /*IID_IPropertyStore*/,\n        [Out(), MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);\n\n    public static void SetAppIdForWindow(int handle, string AppId)\n    {\n        Guid iid = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");\n        IPropertyStore prop;\n        int result1 = SHGetPropertyStoreForWindow((IntPtr)handle, ref iid, out prop);\n\n        // Name = System.AppUserModel.ID\n        // ShellPKey = PKEY_AppUserModel_ID\n        // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3\n        // PropID = 5\n        // Type = String (VT_LPWSTR)\n        PropertyKey AppUserModelIDKey = new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);\n    \n        PropVariant pv = new PropVariant(AppId);\n        \n        uint result2 = prop.SetValue(ref AppUserModelIDKey, pv);\n        \n        Marshal.ReleaseComObject(prop);\n    }\n}\n\'@\n\nAdd-Type -TypeDefinition $signature\n
Run Code Online (Sandbox Code Playgroud)\n

然后用你的表格:

\n
[void][Reflection.Assembly]::LoadWithPartialName(\'Microsoft.VisualBasic\')\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type -AssemblyName System.Drawing\n\n$form = New-Object System.Windows.Forms.Form\n$form.Size = New-Object System.Drawing.Size(300,200)\n$form.ShowInTaskbar = $true\n$form.visible = $true\n\n[PSAppID]::SetAppIdForWindow($form.Handle, "YourName.App")\n
Run Code Online (Sandbox Code Playgroud)\n

它分成自己的任务栏条目。

\n
    \n
  • Raymond Chen 的博客称 AppID 的格式应该是“CompanyName.ProductName.SubProduct.VersionInformation其中 Sub\xc2\xadProduct 是可选的,并且仅当您希望应用程序的不同版本被视为不同时才会出现 Version\xc2\xadInformation”。并且不超过 128 个字符。\n\n
  • \n
  • 我认为这Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")应该是 IPropertyStore 的 Windows Shell ID,但我不知道如何在不写入的情况下获取它。
  • \n
  • AppUserModelIDKey也许来自某些 Win32 的神奇 GUID也是如此propkey.h
  • \n
\n

也可以看看:

\n\n