gpt4 book ai didi

winforms - 在 PowerShell 中为新窗体分离任务栏图标

转载 作者:行者123 更新时间:2023-12-05 05:10:48 28 4
gpt4 key购买 nike

当您在 PowerShell 中创建窗口窗体时,它会与主机控制台窗口组合在一起,即使您更改了窗体的图标也是如此。

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

左边发生了什么,右边是期望的效果: enter image description here

示例代码:

[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()

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

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

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

最佳答案

通过 C# 魔术从互联网上拼凑大量 P/Invoke 之后,mostly from here还有一些来自 here ,我最后用这个来添加一个类型,你可以使用一种方法,比如 [PSAppID]::SetAppIdForWindow($form.handle, "Your.AppId"):

$signature = @'
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

public class PSAppID
{
// https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
// IPropertyStore Interface
[ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
private interface IPropertyStore
{
uint GetCount([Out] out uint cProps);
uint GetAt([In] uint iProp, out PropertyKey pkey);
uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
uint Commit();
}


// PropertyKey Structure
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct PropertyKey
{
private Guid formatId; // Unique GUID for property
private Int32 propertyId; // Property identifier (PID)

public Guid FormatId
{
get
{
return formatId;
}
}

public Int32 PropertyId
{
get
{
return propertyId;
}
}

public PropertyKey(Guid formatId, Int32 propertyId)
{
this.formatId = formatId;
this.propertyId = propertyId;
}

public PropertyKey(string formatId, Int32 propertyId)
{
this.formatId = new Guid(formatId);
this.propertyId = propertyId;
}

}


// PropVariant Class (only for string value)
[StructLayout(LayoutKind.Explicit)]
public class PropVariant : IDisposable
{
[FieldOffset(0)]
ushort valueType; // Value type

// [FieldOffset(2)]
// ushort wReserved1; // Reserved field
// [FieldOffset(4)]
// ushort wReserved2; // Reserved field
// [FieldOffset(6)]
// ushort wReserved3; // Reserved field

[FieldOffset(8)]
IntPtr ptr; // Value


// Value type (System.Runtime.InteropServices.VarEnum)
public VarEnum VarType
{
get { return (VarEnum)valueType; }
set { valueType = (ushort)value; }
}

public bool IsNullOrEmpty
{
get
{
return (valueType == (ushort)VarEnum.VT_EMPTY ||
valueType == (ushort)VarEnum.VT_NULL);
}
}

// Value (only for string value)
public string Value
{
get
{
return Marshal.PtrToStringUni(ptr);
}
}


public PropVariant()
{ }

public PropVariant(string value)
{
if (value == null)
throw new ArgumentException("Failed to set value.");

valueType = (ushort)VarEnum.VT_LPWSTR;
ptr = Marshal.StringToCoTaskMemUni(value);
}

~PropVariant()
{
Dispose();
}

public void Dispose()
{
PropVariantClear(this);
GC.SuppressFinalize(this);
}

}

[DllImport("Ole32.dll", PreserveSig = false)]
private extern static void PropVariantClear([In, Out] PropVariant pvar);


[DllImport("shell32.dll")]
private static extern int SHGetPropertyStoreForWindow(
IntPtr hwnd,
ref Guid iid /*IID_IPropertyStore*/,
[Out(), MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);

public static void SetAppIdForWindow(int handle, string AppId)
{
Guid iid = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");
IPropertyStore prop;
int result1 = SHGetPropertyStoreForWindow((IntPtr)handle, ref iid, out prop);

// Name = System.AppUserModel.ID
// ShellPKey = PKEY_AppUserModel_ID
// FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
// PropID = 5
// Type = String (VT_LPWSTR)
PropertyKey AppUserModelIDKey = new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);

PropVariant pv = new PropVariant(AppId);

uint result2 = prop.SetValue(ref AppUserModelIDKey, pv);

Marshal.ReleaseComObject(prop);
}
}
'@

Add-Type -TypeDefinition $signature

然后使用您的表单:

[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.visible = $true

[PSAppID]::SetAppIdForWindow($form.Handle, "YourName.App")

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

  • Raymond Chen 的博客说 AppID 的格式应该是“CompanyName.ProductName.SubProduct.VersionInformation”,其中 SubProduct 是可选的,并且 VersionInformation 仅在您希望不同版本的应用程序时出现被视为不同的。”且不超过 128 个字符。
  • 我认为这个 Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99") 应该是 IPropertyStore 的 Windows Shell ID,但我不知道如何在没有它的情况下获取它把它写进去。
  • 对于来自某些 Win32 propkey.hAppUserModelIDKey 魔法 GUID 可能也是如此?

另见:

关于winforms - 在 PowerShell 中为新窗体分离任务栏图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56248774/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com