Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
TaskbarJumpList.cs145 linesDownload Raw Back to WindowsTaskbarJumpList
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Diagnostics;6using System.Management.Automation;7using System.Reflection;8using System.Threading;9 10using static Microsoft.PowerShell.ComInterfaces;11 12namespace Microsoft.PowerShell13{14    internal static class TaskbarJumpList15    {16        // Creating a JumpList entry takes around 55ms when the PowerShell process is interactive and17        // owns the current window (otherwise it does a fast exit anyway). Since there is no 'GET' like API,18        // we always have to execute this call because we do not know if it has been created yet.19        // The JumpList does persist as long as the filepath of the executable does not change but there20        // could be disruptions to it like e.g. the bi-annual Windows update, we decided to21        // not over-optimize this and always create the JumpList as a non-blocking background STA thread instead.22        internal static void CreateRunAsAdministratorJumpList()23        {24            // The STA apartment state is not supported on NanoServer and Windows IoT.25            // Plus, there is not need to create jump list in those environment anyways.26            if (!Platform.IsWindowsDesktop)27            {28                return;29            }30 31            // Some COM APIs are implicitly STA only, therefore the executing thread must run in STA.32            var thread = new Thread(() =>33            {34                try35                {36                    CreateElevatedEntry(ConsoleHostStrings.RunAsAdministrator);37                }38                catch (Exception)39                {40                    // Due to COM threading complexity there might still be sporadic failures but they can be41                    // ignored as creating the JumpList is not critical and persists after its first creation.42                }43            });44 45            try46            {47                thread.SetApartmentState(ApartmentState.STA);48                thread.Start();49            }50            catch (ThreadStartException)51            {52                // STA may not be supported on some platforms53            }54        }55 56        private static void CreateElevatedEntry(string title)57        {58            // Check startupInfo first to know if the current shell is interactive and owns a window before proceeding59            // This check is fast (less than 1ms) and allows for quick-exit60            GetStartupInfo(out StartUpInfo startupInfo);61            const uint STARTF_USESHOWWINDOW = 0x00000001;62            const ushort SW_HIDE = 0;63            if (((startupInfo.dwFlags & STARTF_USESHOWWINDOW) == 1) && (startupInfo.wShowWindow != SW_HIDE))64            {65                string cmdPath = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe");66 67                // Check for maximum available slots in JumpList and start creating the custom Destination List68                var CLSID_DestinationList = new Guid(@"77f10cf0-3db5-4966-b520-b7c54fd35ed6");69                const uint CLSCTX_INPROC_SERVER = 1;70                var IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");71                var hResult = CoCreateInstance(ref CLSID_DestinationList, null, CLSCTX_INPROC_SERVER, ref IID_IUnknown, out object pCustDestListobj);72                if (hResult < 0)73                {74                    Debug.Fail($"Creating ICustomDestinationList failed with HResult '{hResult}'.");75                    return;76                }77 78                var pCustDestList = (ICustomDestinationList)pCustDestListobj;79                hResult = pCustDestList.BeginList(out uint uMaxSlots, new Guid(@"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9"), out object pRemovedItems);80                if (hResult < 0)81                {82                    Debug.Fail($"BeginList on ICustomDestinationList failed with HResult '{hResult}'.");83                    return;84                }85 86                if (uMaxSlots >= 1)87                {88                    // Create JumpListLink89                    var nativeShellLink = (IShellLinkW)new CShellLink();90                    var nativePropertyStore = (IPropertyStore)nativeShellLink;91                    nativeShellLink.SetPath(cmdPath);92                    nativeShellLink.SetShowCmd(0);93                    var shellLinkDataList = (IShellLinkDataListW)nativeShellLink;94                    shellLinkDataList.GetFlags(out uint flags);95                    flags |= 0x00800000; // SLDF_ALLOW_LINK_TO_LINK96                    flags |= 0x00002000; // SLDF_RUNAS_USER97                    shellLinkDataList.SetFlags(flags);98                    var PKEY_TITLE = new PropertyKey(new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 2);99                    hResult = nativePropertyStore.SetValue(in PKEY_TITLE, new PropVariant(title));100                    if (hResult < 0)101                    {102                        pCustDestList.AbortList();103                        Debug.Fail($"SetValue on IPropertyStore with title '{title}' failed with HResult '{hResult}'.");104                        return;105                    }106 107                    hResult = nativePropertyStore.Commit();108                    if (hResult < 0)109                    {110                        pCustDestList.AbortList();111                        Debug.Fail($"Commit on IPropertyStore failed with HResult '{hResult}'.");112                        return;113                    }114 115                    // Create collection and add JumpListLink116                    var CLSID_EnumerableObjectCollection = new Guid(@"2d3468c1-36a7-43b6-ac24-d3f02fd9607a");117                    const uint CLSCTX_INPROC_HANDLER = 2;118                    const uint CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER;119                    hResult = CoCreateInstance(ref CLSID_EnumerableObjectCollection, null, CLSCTX_INPROC, ref IID_IUnknown, out object instance);120                    if (hResult < 0)121                    {122                        pCustDestList.AbortList();123                        Debug.Fail($"Creating IObjectCollection failed with HResult '{hResult}'.");124                        return;125                    }126 127                    var pShortCutCollection = (IObjectCollection)instance;128                    pShortCutCollection.AddObject((IShellLinkW)nativePropertyStore);129 130                    // Add collection to custom destination list and commit the result131                    hResult = pCustDestList.AddUserTasks((IObjectArray)pShortCutCollection);132                    if (hResult < 0)133                    {134                        pCustDestList.AbortList();135                        Debug.Fail($"AddUserTasks on ICustomDestinationList failed with HResult '{hResult}'.");136                        return;137                    }138 139                    pCustDestList.CommitList();140                }141            }142        }143    }144}145