gpt4 book ai didi

c# - 将 "chained process"固定到任务栏

转载 作者:太空宇宙 更新时间:2023-11-03 22:48:52 27 4
gpt4 key购买 nike

假设我有两个名为 launcher.exelaunchee.exe 的程序。启动器显示一个按钮,单击该按钮会启动 launchee.exelaunchee.exe 是一个简单的 hello world 程序。

如果我不采取任何措施来阻止它,当用户将 hello world 程序“固定到任务栏”时,它将固定 launchee.exe 并且不会通过启动器启动应用程序.

告诉 Windows 固定 launcher.exe 而不是 launchee.exe 的最佳方法是什么?

为了使事情更具体,这里有一个用 C# 实现 launcher.exe 的例子:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;

public class Launcher : Form
{
static public void Main ()
{
Application.Run (new Launcher ());
}

public Launcher ()
{
Button b = new Button ();
b.Text = "Launch";
b.Click += new EventHandler (Button_Click);
Controls.Add (b);
}

private void Button_Click (object sender, EventArgs e)
{
Process.Start("launchee.exe");
System.Environment.Exit(0);
}
}

launchee.exe:

using System;
using System.Drawing;
using System.Windows.Forms;

public class Launchee : Form
{
static public void Main ()
{
Application.Run (new Launchee ());
}

public Launchee ()
{
Label b = new Label();
b.Text = "Hello World !";
Controls.Add (b);
}
}

最佳答案

我提出了一个基于绑定(bind)低级 API 来访问 AppUserModelID 的答案。 .我发现这个解决方案脆弱而困惑。它的灵感主要来自 Windows Api CodePack微软好像已经停产了。我希望有人会提出一个更清洁的解决方案。

其目的是将 AppUserId 设置为“Stackoverflow.chain.process.pinning”并手动设置 RelaunchCommand 以及 DisplayName 属性(它们必须根据 AppUserModelID 一起设置)。

要在示例实现中使用它,需要调用 TaskBar.SetupLauncher(this)TaskBar.SetupLaunchee(this)分别在LauncherLaunchee构造函数。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

internal struct PropertyKey
{
Guid formatId;
int propertyId;

internal PropertyKey(Guid guid, int propertyId)
{
this.formatId = guid;
this.propertyId = propertyId;
}
}

[StructLayout(LayoutKind.Explicit)]
internal struct PropVariant
{
[FieldOffset(0)] internal ushort vt;
[FieldOffset(8)] internal IntPtr pv;
[FieldOffset(8)] internal UInt64 padding;

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

internal PropVariant(string value)
{
this.vt = (ushort)VarEnum.VT_LPWSTR;
this.padding = 0;
this.pv = Marshal.StringToCoTaskMemUni(value);
}

internal void Clear()
{
PropVariantClear (ref this);
}
}

[ComImport,
Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPropertyStore
{
int GetCount([Out] out uint propertyCount);
void GetAt([In] uint propertyIndex, [Out, MarshalAs(UnmanagedType.Struct)] out PropertyKey key);
void GetValue([In, MarshalAs(UnmanagedType.Struct)] ref PropertyKey key, [Out, MarshalAs(UnmanagedType.Struct)] out PropVariant pv);
void SetValue([In, MarshalAs(UnmanagedType.Struct)] ref PropertyKey key, [In, MarshalAs(UnmanagedType.Struct)] ref PropVariant pv);
void Commit();
}

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

internal static class Key {
private static Guid propGuid = new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3");
internal static PropertyKey AppId = new PropertyKey(propGuid, 5);
internal static PropertyKey RelaunchCommand = new PropertyKey(propGuid, 2);
internal static PropertyKey DisplayName = new PropertyKey(propGuid, 4);
}

private static void ClearValue(IPropertyStore store, PropertyKey key) {
var prop = new PropVariant();
prop.vt = (ushort)VarEnum.VT_EMPTY;
store.SetValue(ref key, ref prop);
}

private static void SetValue(IPropertyStore store, PropertyKey key, string value) {
var prop = new PropVariant(value);
store.SetValue(ref key, ref prop);
prop.Clear();
}

internal static IPropertyStore Store(IntPtr handle) {
IPropertyStore store;
var store_guid = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");
int rc = SHGetPropertyStoreForWindow(handle, ref store_guid, out store);
if (rc != 0) throw Marshal.GetExceptionForHR(rc);
return store;
}

internal static void SetupLauncher(Form form) {
IntPtr handle = form.Handle;
var store = Store(handle);
SetValue (store, Key.AppId, "Stackoverflow.chain.process.pinning");
form.FormClosed += delegate { Cleanup(handle); };
}

internal static void SetupLaunchee(Form form) {
IntPtr handle = form.Handle;
var store = Store(handle);
SetValue (store, Key.AppId, "Stackoverflow.chain.process.pinning");
string exePath = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "launcher.exe");
SetValue (store, Key.RelaunchCommand, exePath);
SetValue (store, Key.DisplayName, "Test");
form.FormClosed += delegate { Cleanup(handle); };
}

internal static void Cleanup(IntPtr handle) {
var store = Store(handle);
ClearValue (store, Key.AppId);
ClearValue (store, Key.RelaunchCommand);
ClearValue (store, Key.DisplayName);
}
}

关于c# - 将 "chained process"固定到任务栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48539789/

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