我想獲得給定用戶系統上可用的所有控制面板小程式,以便我可以顯示每個小程式的串列并讓用戶能夠運行它們。
我一直在考慮簡單地獲取.cpl位于%SYSTEMROOT%\system32(通常C:\Windows\system32)中的每個檔案,但我無法提取這些小程式的標題。此外,在查看
uj5u.com熱心網友回復:
在user2864740的幫助下,我想出了一個基于注冊表的解決方案:
const string APPLETS_LOCATION = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace";
/// <summary>
/// Gets GUIDs for all the installed Control Panel applets.
/// </summary>
/// <returns>A collection of control panel GUIDs.</returns>
static IEnumerable<string> GetAppletGuids(){
using (RegistryKey reg32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(APPLETS_LOCATION)) {
using (RegistryKey reg64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(APPLETS_LOCATION)) {
return reg32.GetSubKeyNames()
.Concat(reg64.GetSubKeyNames())
.Distinct() // Both the 32-bit registry and the 64-bit registry can contain duplicates - lets skip them
.Where(x => x.StartsWith("{") && x.EndsWith("}")); // Contain only GUIDs
}
}
}
/// <summary>
/// Gets the name of an applet by its GUID.
/// </summary>
/// <param name="guid">The GUID of an applet.</param>
/// <returns>The name of the applet, or <see langword="null"/> if the applet couldn't be found.</returns>
static string GetNameForApplet(string guid)
{
using (RegistryKey appletKey32 = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry32).OpenSubKey(@"CLSID\" guid)) {
// Try looking in the 32-bit registry first
if (appletKey32 != null)
return (string)appletKey32.GetValue("");
else {
// No such applet in the 32-bit registry, try the 64-bit one
using(RegistryKey appletKey64 = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64).OpenSubKey(@"CLSID\" guid)) {
if (appletKey64 != null)
return (string)appletKey64.GetValue("");
else
// No applet in both registries
return null;
}
}
}
}
然后可以使用這些方法:
var applets = GetAppletGuids();
foreach (string guid in applets) {
Console.WriteLine("Applet: " GetNameForApplet(guid) ", GUID: " guid);
}
...這提供了以下輸出(片段):
Applet: Taskbar, GUID: {0DF44EAA-FF21-4412-828E-260A8728E7F1}
Applet: Credential Manager, GUID: {1206F5F1-0569-412C-8FEC-3204630DFB70}
Applet: Set User Defaults, GUID: {17cd9488-1228-4b2f-88ce-4298e93e0966}
Applet: Workspaces Center, GUID: {241D7C96-F8BF-4F85-B01F-E2B043341A4B}
Applet: , GUID: {38A98528-6CBF-4CA9-8DC0-B1E1D10F7B1B}
Applet: Phone and Modem Control Panel, GUID: {40419485-C444-4567-851A-2DD7BFA1684D}
Applet: User Accounts, GUID: {60632754-c523-4b62-b45c-4172da012619}
Applet: Region and Language, GUID: {62D8ED13-C9D0-4CE8-A914-47DD628FB1B0}
有時名稱設定為空字串,從我的測驗來看,嘗試呼叫這些小程式不會產生任何結果 - 沒有錯誤、沒有視窗、沒有行程,所以我認為最好忽略這些小程式。
為了使用其 GUID 呼叫小程式,您可以使用資源管理器:
// Open Power Options
string guid = "{025A5937-A6BE-4686-A844-36FE4BEC8B6D}";
Process.Start("explorer", "shell:::" guid);
uj5u.com熱心網友回復:
控制面板小程式來自兩個地方,注冊表和 system32 目錄中的 .cpl 檔案。每個 .cpl 檔案在控制面板中提供 1 個或多個條目。
雖然有一個與 .cpl 檔案互動的API,但它通常更容易使用,IShellFolder因為它為您提供與 Explorer 完全相同的串列。
using System;
using System.Runtime.InteropServices;
namespace Test { class TestApp {
public class WAPI
{
public const int CSIDL_CONTROLS = 0x03;
[DllImport("shell32.dll")] public static extern int ILFree(IntPtr p);
[DllImport("shell32.dll")] public static extern int SHGetFolderLocation(IntPtr hwnd, int csidl, IntPtr hToken, uint reserved, out IntPtr pidl);
[StructLayout(LayoutKind.Explicit, Size = 520)] public struct STRRETinternal { [FieldOffset(0)] public IntPtr pOleStr; [FieldOffset(0)] public IntPtr pStr; [FieldOffset(0)] public uint uOffset; }
[StructLayout(LayoutKind.Sequential)] public struct STRRET { public uint uType; public STRRETinternal data; }
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("000214F2-0000-0000-C000-000000000046")]
public interface IEnumIDList {
[PreserveSig] int Next(uint celt, IntPtr rgelt, out uint pceltFetched);
}
public static Guid IID_IShellFolder = new Guid("{000214E6-0000-0000-C000-000000000046}");
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("000214E6-0000-0000-C000-000000000046")]
public interface IShellFolder {
[PreserveSig] void ParseDisplayName();
[PreserveSig] int EnumObjects(IntPtr hwnd, int grfFlags, out IntPtr ppenumIDList);
[PreserveSig] int BindToObject(IntPtr pidl, IntPtr pbc, [In]ref Guid riid, out IntPtr ppv);
[PreserveSig] void BindToStorage();
[PreserveSig] int CompareIDs();
[PreserveSig] void CreateViewObject();
[PreserveSig] void GetAttributesOf();
[PreserveSig] void GetUIObjectOf();
int GetDisplayNameOf(IntPtr pidl, int uFlags, IntPtr pName);
}
[DllImport("shell32.dll")] public static extern int SHGetDesktopFolder(out IShellFolder shf);
[DllImport("shlwapi.dll")] public static extern int StrRetToBSTR(IntPtr pstr, IntPtr pidl, out IntPtr pbstr);
}
[STAThread]
static void Main(/*string[] args*/)
{
IntPtr pidl = IntPtr.Zero, ptr;
int hr = WAPI.SHGetFolderLocation(IntPtr.Zero, WAPI.CSIDL_CONTROLS, IntPtr.Zero, 0, out pidl);
if (hr != 0) Environment.Exit(hr);
WAPI.IShellFolder root;
hr = WAPI.SHGetDesktopFolder(out root);
if (hr != 0) Environment.Exit(hr);
hr = root.BindToObject(pidl, IntPtr.Zero, ref WAPI.IID_IShellFolder, out ptr);
WAPI.ILFree(pidl);
Marshal.ReleaseComObject(root);
if (hr != 0) Environment.Exit(hr);
root = (WAPI.IShellFolder) Marshal.GetObjectForIUnknown(ptr);
IntPtr enumpidlsptr;
hr = root.EnumObjects(IntPtr.Zero, 0x00060, out enumpidlsptr);
if (hr >= 0 && enumpidlsptr != IntPtr.Zero)
{
WAPI.IEnumIDList enumpidls = (WAPI.IEnumIDList) Marshal.GetObjectForIUnknown(enumpidlsptr);
uint fetch;
IntPtr bytes = Marshal.AllocCoTaskMem(999);
while ((hr = enumpidls.Next((uint) 1, bytes, out fetch)) >= 0 && fetch > 0)
{
IntPtr child = Marshal.ReadIntPtr(bytes);
hr = root.GetDisplayNameOf(child, 0, bytes);
if (hr >= 0)
{
IntPtr bstr;
hr = WAPI.StrRetToBSTR(bytes, child, out bstr);
if (hr >= 0)
{
string name = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);
Console.WriteLine(name);
}
}
Marshal.FreeCoTaskMem(child);
}
Marshal.FreeCoTaskMem(bytes);
Marshal.ReleaseComObject(enumpidls);
}
Marshal.ReleaseComObject(root);
}
}}
要充分利用這一點,您需要閱讀有關shell 命名空間的更多資訊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/401742.html
上一篇:如何將來自Xamarin應用程式的事件接收到我的ASP.NETWeb應用程式中?
下一篇:日期未被識別為有效的日期時間
