簡體   English   中英

從桌面應用程序獲取“現代”Windows應用程序的圖標?

[英]Getting icon of “modern” Windows app from a desktop application?

我開發了一個函數,它返回給定窗口句柄的窗口圖標。 看起來像這樣。

private static BitmapSource GetWindowIcon(IntPtr windowHandle)
{
    var hIcon = default(IntPtr);
    hIcon = SendMessage(windowHandle, WM_GETICON, ICON_BIG, IntPtr.Zero);

    if (hIcon == IntPtr.Zero)
        hIcon = GetClassLongPtr(windowHandle, GCL_HICON);

    if (hIcon == IntPtr.Zero)
    {
        hIcon = LoadIcon(IntPtr.Zero, (IntPtr)0x7F00/*IDI_APPLICATION*/);
    }

    if (hIcon != IntPtr.Zero)
    {
        return Imaging.CreateBitmapSourceFromHIcon(hIcon, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
    } else {
        throw new InvalidOperationException("Could not load window icon.");
    }
}

我將此函數與GetForegroundWindow結合使用以獲取活動窗口的圖標。

但是,它似乎為通用應用程序產生了相同的暗淡圖標。

是否有可能以某種方式從正在運行的通用應用程序中獲取平鋪圖像或圖標?

以下是一些示例代碼,演示如何完成此操作。 注意:

  1. 你應該運行這個平均值,否則你將無法訪問具有應用程序資源的文件夾(我認為,並沒有真正檢查自己,因為調查我授予自己訪問該文件夾的內容)。
  2. 現代應用程序在ApplicationFrameHost主機進程下運行。 您將需要一些技巧來獲取實際的可執行文件(如Calculator.exe),這些技巧在代碼中被注釋。
  3. 現代應用程序清單包含徽標的路徑,但可能有幾個徽標(黑色,白色,constract白色為例)。 你需要一些邏輯來選擇一個。 我沒有詳細調查這個。
  4. 我在Windows 10中的計算器應用程序上進行了測試,它運行良好。 但是,當然需要更多的應用程序以確保一切正常。

這是代碼:

public static class IconHelper {
    public static BitmapSource GetForegroundWindowIcon() {
        var hwnd = GetForegroundWindow();
        uint pid;
        GetWindowThreadProcessId(hwnd, out pid);
        Process proc = Process.GetProcessById((int) pid);
        // modern apps run under ApplicationFrameHost host process in windows 10
        // don't forget to check if that is true for windows 8 - maybe they use another host there
        if (proc.MainModule.ModuleName == "ApplicationFrameHost.exe") {
            // this should be modern app
            return GetModernAppLogo(hwnd);
        }
        return GetWindowIcon(hwnd);
    }

    public static BitmapSource GetModernAppLogo(IntPtr hwnd) {
        // get folder where actual app resides
        var exePath = GetModernAppProcessPath(hwnd); 
        var dir = System.IO.Path.GetDirectoryName(exePath);
        var manifestPath = System.IO.Path.Combine(dir, "AppxManifest.xml");            
        if (File.Exists(manifestPath)) {
            // this is manifest file
            string pathToLogo;
            using (var fs = File.OpenRead(manifestPath)) {
                var manifest = XDocument.Load(fs);
                const string ns = "http://schemas.microsoft.com/appx/manifest/foundation/windows10";
                // rude parsing - take more care here
                pathToLogo = manifest.Root.Element(XName.Get("Properties", ns)).Element(XName.Get("Logo", ns)).Value;
            }
            // now here it is tricky again - there are several files that match logo, for example
            // black, white, contrast white. Here we choose first, but you might do differently
            string finalLogo = null;
            // serach for all files that match file name in Logo element but with any suffix (like "Logo.black.png, Logo.white.png etc)
            foreach (var logoFile in Directory.GetFiles(System.IO.Path.Combine(dir, System.IO.Path.GetDirectoryName(pathToLogo)),
                System.IO.Path.GetFileNameWithoutExtension(pathToLogo) + "*" + System.IO.Path.GetExtension(pathToLogo))) {
                finalLogo = logoFile;
                break;
            }

            if (System.IO.File.Exists(finalLogo)) {
                using (var fs = File.OpenRead(finalLogo)) {
                    var img = new BitmapImage() {
                    };
                    img.BeginInit();
                    img.StreamSource = fs;
                    img.CacheOption = BitmapCacheOption.OnLoad;
                    img.EndInit();
                    return img;
                }
            }
        }
        return null;
    }

    private static string GetModernAppProcessPath(IntPtr hwnd) {
        uint pid = 0;
        GetWindowThreadProcessId(hwnd, out pid);            
        // now this is a bit tricky. Modern apps are hosted inside ApplicationFrameHost process, so we need to find
        // child window which does NOT belong to this process. This should be the process we need
        var children = GetChildWindows(hwnd);
        foreach (var childHwnd in children) {
            uint childPid = 0;
            GetWindowThreadProcessId(childHwnd, out childPid);
            if (childPid != pid) {
                // here we are
                Process childProc = Process.GetProcessById((int) childPid);
                return childProc.MainModule.FileName;
            }
        }

        throw new Exception("Cannot find a path to Modern App executable file");
    }

    public static BitmapSource GetWindowIcon(IntPtr windowHandle) {
        var hIcon = default(IntPtr);
        hIcon = SendMessage(windowHandle, WM_GETICON, (IntPtr) ICON_BIG, IntPtr.Zero);

        if (hIcon == IntPtr.Zero)
            hIcon = GetClassLongPtr(windowHandle, GCL_HICON);

        if (hIcon == IntPtr.Zero) {
            hIcon = LoadIcon(IntPtr.Zero, (IntPtr) 0x7F00 /*IDI_APPLICATION*/);
        }

        if (hIcon != IntPtr.Zero) {
            return Imaging.CreateBitmapSourceFromHIcon(hIcon, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
        }
        else {
            throw new InvalidOperationException("Could not load window icon.");
        }
    }

    #region Helper methods
    const UInt32 WM_GETICON = 0x007F;
    const int ICON_BIG = 1;
    const int GCL_HICON = -14;

    private static List<IntPtr> GetChildWindows(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
        {
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        }
        list.Add(handle);
        //  You can modify this to check to see if you want to cancel the operation, then return a null here
        return true;
    }

    public delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
    [DllImport("user32.Dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr parentHandle, EnumWindowProc callback, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int GetWindowThreadProcessId(IntPtr handle, out uint processId);

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern IntPtr LoadIcon(IntPtr hInstance, IntPtr lpIconName);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    private static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
    {
        if (IntPtr.Size > 4)
            return GetClassLongPtr64(hWnd, nIndex);
        else
            return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
    }

    [DllImport("user32.dll", EntryPoint = "GetClassLong")]
    public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
    public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
    #endregion

}

用法只是:

var icon = IconHelper.GetForegroundWindowIcon();

可以從官方API查詢大多數“現代應用程序”(或Windows應用商店應用程序或AppX應用程序模型中的應用程序)信息。

您可以從GetPackageFullName函數開始(它獲取指定進程的包全名)。 獲得程序包全名后,可以使用Package Query API獲取更多信息。

這些API是原生的,因此根據我的知識,它們在.NET Framework中沒有等價物。 但是,它們可以通過某種方式從WinRT應用程序訪問(並且您確實可以從標准.NET Framework應用程序訪問某些WinRT API,但這很有用)。

所以,我已經構建了一個實用程序類,允許您從這些應用程序中獲取信息。 下面是一個示例應用程序,它轉儲所有當前加載的Windows應用商店包和應用。

這些應用程序中包含的圖像是特殊的,因為它們被定義為資源(​​資產)鍵,可以使用限定符調整它們以形成最終路徑。 例如,這里記錄了這一點: 如何使用限定符(HTML)命名資源 ,此處: 快速入門:使用文件或圖像資源(HTML)

你可以找到的問題在很大程度上取決於應用程序本身,因此確定你可以使用的圖像並不是很容易,我沒有找到任何API,所以我編寫了一個樣本,可以得到最高比例的圖像。給定資源名稱作為FindHighestScaleQualifiedImagePathFindHighestScaleQualifiedImagePath )。 您可以從此路徑加載WPF BitmapSource(或任何其他成像平台資源)。

    static void Main(string[] args)
    {
        foreach (var p in Process.GetProcesses())
        {
            var package = AppxPackage.FromProcess(p);
            if (package != null)
            {
                Show(0, package);
                Console.WriteLine();
                Console.WriteLine();
            }
        }
    }

    private static void Show(int indent, AppxPackage package)
    {
        string sindent = new string(' ', indent);
        Console.WriteLine(sindent + "FullName               : " + package.FullName);
        Console.WriteLine(sindent + "FamilyName             : " + package.FamilyName);
        Console.WriteLine(sindent + "IsFramework            : " + package.IsFramework);
        Console.WriteLine(sindent + "ApplicationUserModelId : " + package.ApplicationUserModelId);
        Console.WriteLine(sindent + "Path                   : " + package.Path);
        Console.WriteLine(sindent + "Publisher              : " + package.Publisher);
        Console.WriteLine(sindent + "PublisherId            : " + package.PublisherId);
        Console.WriteLine(sindent + "Logo                   : " + package.Logo);
        Console.WriteLine(sindent + "Best Logo Path         : " + package.FindHighestScaleQualifiedImagePath(package.Logo));
        Console.WriteLine(sindent + "ProcessorArchitecture  : " + package.ProcessorArchitecture);
        Console.WriteLine(sindent + "Version                : " + package.Version);
        Console.WriteLine(sindent + "PublisherDisplayName   : " + package.PublisherDisplayName);
        Console.WriteLine(sindent + "   Localized           : " + package.LoadResourceString(package.PublisherDisplayName));
        Console.WriteLine(sindent + "DisplayName            : " + package.DisplayName);
        Console.WriteLine(sindent + "   Localized           : " + package.LoadResourceString(package.DisplayName));
        Console.WriteLine(sindent + "Description            : " + package.Description);
        Console.WriteLine(sindent + "   Localized           : " + package.LoadResourceString(package.Description));

        Console.WriteLine(sindent + "Apps                   :");
        int i = 0;
        foreach (var app in package.Apps)
        {
            Console.WriteLine(sindent + " App [" + i + "] Description       : " + app.Description);
            Console.WriteLine(sindent + "   Localized           : " + package.LoadResourceString(app.Description));
            Console.WriteLine(sindent + " App [" + i + "] DisplayName       : " + app.DisplayName);
            Console.WriteLine(sindent + "   Localized           : " + package.LoadResourceString(app.DisplayName));
            Console.WriteLine(sindent + " App [" + i + "] ShortName         : " + app.ShortName);
            Console.WriteLine(sindent + "   Localized           : " + package.LoadResourceString(app.ShortName));
            Console.WriteLine(sindent + " App [" + i + "] EntryPoint        : " + app.EntryPoint);
            Console.WriteLine(sindent + " App [" + i + "] Executable        : " + app.Executable);
            Console.WriteLine(sindent + " App [" + i + "] Id                : " + app.Id);
            Console.WriteLine(sindent + " App [" + i + "] Logo              : " + app.Logo);
            Console.WriteLine(sindent + " App [" + i + "] SmallLogo         : " + app.SmallLogo);
            Console.WriteLine(sindent + " App [" + i + "] StartPage         : " + app.StartPage);
            Console.WriteLine(sindent + " App [" + i + "] Square150x150Logo : " + app.Square150x150Logo);
            Console.WriteLine(sindent + " App [" + i + "] Square30x30Logo   : " + app.Square30x30Logo);
            Console.WriteLine(sindent + " App [" + i + "] BackgroundColor   : " + app.BackgroundColor);
            Console.WriteLine(sindent + " App [" + i + "] ForegroundText    : " + app.ForegroundText);
            Console.WriteLine(sindent + " App [" + i + "] WideLogo          : " + app.WideLogo);
            Console.WriteLine(sindent + " App [" + i + "] Wide310x310Logo   : " + app.Wide310x310Logo);
            Console.WriteLine(sindent + " App [" + i + "] Square310x310Logo : " + app.Square310x310Logo);
            Console.WriteLine(sindent + " App [" + i + "] Square70x70Logo   : " + app.Square70x70Logo);
            Console.WriteLine(sindent + " App [" + i + "] MinWidth          : " + app.MinWidth);
            Console.WriteLine(sindent + " App [" + i + "] Square71x71Logo   : " + app.GetStringValue("Square71x71Logzo"));
            i++;
        }

        Console.WriteLine(sindent + "Deps                   :");
        foreach (var dep in package.DependencyGraph)
        {
            Show(indent + 1, dep);
        }
    }

public sealed class AppxPackage
{
    private List<AppxApp> _apps = new List<AppxApp>();
    private IAppxManifestProperties _properties;

    private AppxPackage()
    {
    }

    public string FullName { get; private set; }
    public string Path { get; private set; }
    public string Publisher { get; private set; }
    public string PublisherId { get; private set; }
    public string ResourceId { get; private set; }
    public string FamilyName { get; private set; }
    public string ApplicationUserModelId { get; private set; }
    public string Logo { get; private set; }
    public string PublisherDisplayName { get; private set; }
    public string Description { get; private set; }
    public string DisplayName { get; private set; }
    public bool IsFramework { get; private set; }
    public Version Version { get; private set; }
    public AppxPackageArchitecture ProcessorArchitecture { get; private set; }

    public IReadOnlyList<AppxApp> Apps
    {
        get
        {
            return _apps;
        }
    }

    public IEnumerable<AppxPackage> DependencyGraph
    {
        get
        {
            return QueryPackageInfo(FullName, PackageConstants.PACKAGE_FILTER_ALL_LOADED).Where(p => p.FullName != FullName);
        }
    }

    public string FindHighestScaleQualifiedImagePath(string resourceName)
    {
        if (resourceName == null)
            throw new ArgumentNullException("resourceName");

        const string scaleToken = ".scale-";
        var sizes = new List<int>();
        string name = System.IO.Path.GetFileNameWithoutExtension(resourceName);
        string ext = System.IO.Path.GetExtension(resourceName);
        foreach (var file in Directory.EnumerateFiles(System.IO.Path.Combine(Path, System.IO.Path.GetDirectoryName(resourceName)), name + scaleToken + "*" + ext))
        {
            string fileName = System.IO.Path.GetFileNameWithoutExtension(file);
            int pos = fileName.IndexOf(scaleToken) + scaleToken.Length;
            string sizeText = fileName.Substring(pos);
            int size;
            if (int.TryParse(sizeText, out size))
            {
                sizes.Add(size);
            }
        }
        if (sizes.Count == 0)
            return null;

        sizes.Sort();
        return System.IO.Path.Combine(Path, System.IO.Path.GetDirectoryName(resourceName), name + scaleToken + sizes.Last() + ext);
    }

    public override string ToString()
    {
        return FullName;
    }

    public static AppxPackage FromWindow(IntPtr handle)
    {
        int processId;
        GetWindowThreadProcessId(handle, out processId);
        if (processId == 0)
            return null;

        return FromProcess(processId);
    }

    public static AppxPackage FromProcess(Process process)
    {
        if (process == null)
        {
            process = Process.GetCurrentProcess();
        }

        try
        {
            return FromProcess(process.Handle);
        }
        catch
        {
            // probably access denied on .Handle
            return null;
        }
    }

    public static AppxPackage FromProcess(int processId)
    {
        const int QueryLimitedInformation = 0x1000;
        IntPtr hProcess = OpenProcess(QueryLimitedInformation, false, processId);
        try
        {
            return FromProcess(hProcess);
        }
        finally
        {
            if (hProcess != IntPtr.Zero)
            {
                CloseHandle(hProcess);
            }
        }
    }

    public static AppxPackage FromProcess(IntPtr hProcess)
    {
        if (hProcess == IntPtr.Zero)
            return null;

        // hprocess must have been opened with QueryLimitedInformation
        int len = 0;
        GetPackageFullName(hProcess, ref len, null);
        if (len == 0)
            return null;

        var sb = new StringBuilder(len);
        string fullName = GetPackageFullName(hProcess, ref len, sb) == 0 ? sb.ToString() : null;
        if (string.IsNullOrEmpty(fullName)) // not an AppX
            return null;

        var package = QueryPackageInfo(fullName, PackageConstants.PACKAGE_FILTER_HEAD).First();

        len = 0;
        GetApplicationUserModelId(hProcess, ref len, null);
        sb = new StringBuilder(len);
        package.ApplicationUserModelId = GetApplicationUserModelId(hProcess, ref len, sb) == 0 ? sb.ToString() : null;
        return package;
    }

    public string GetPropertyStringValue(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        return GetStringValue(_properties, name);
    }

    public bool GetPropertyBoolValue(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        return GetBoolValue(_properties, name);
    }

    public string LoadResourceString(string resource)
    {
        return LoadResourceString(FullName, resource);
    }

    private static IEnumerable<AppxPackage> QueryPackageInfo(string fullName, PackageConstants flags)
    {
        IntPtr infoRef;
        OpenPackageInfoByFullName(fullName, 0, out infoRef);
        if (infoRef != IntPtr.Zero)
        {
            IntPtr infoBuffer = IntPtr.Zero;
            try
            {
                int len = 0;
                int count;
                GetPackageInfo(infoRef, flags, ref len, IntPtr.Zero, out count);
                if (len > 0)
                {
                    var factory = (IAppxFactory)new AppxFactory();
                    infoBuffer = Marshal.AllocHGlobal(len);
                    int res = GetPackageInfo(infoRef, flags, ref len, infoBuffer, out count);
                    for (int i = 0; i < count; i++)
                    {
                        var info = (PACKAGE_INFO)Marshal.PtrToStructure(infoBuffer + i * Marshal.SizeOf(typeof(PACKAGE_INFO)), typeof(PACKAGE_INFO));
                        var package = new AppxPackage();
                        package.FamilyName = Marshal.PtrToStringUni(info.packageFamilyName);
                        package.FullName = Marshal.PtrToStringUni(info.packageFullName);
                        package.Path = Marshal.PtrToStringUni(info.path);
                        package.Publisher = Marshal.PtrToStringUni(info.packageId.publisher);
                        package.PublisherId = Marshal.PtrToStringUni(info.packageId.publisherId);
                        package.ResourceId = Marshal.PtrToStringUni(info.packageId.resourceId);
                        package.ProcessorArchitecture = info.packageId.processorArchitecture;
                        package.Version = new Version(info.packageId.VersionMajor, info.packageId.VersionMinor, info.packageId.VersionBuild, info.packageId.VersionRevision);

                        // read manifest
                        string manifestPath = System.IO.Path.Combine(package.Path, "AppXManifest.xml");
                        const int STGM_SHARE_DENY_NONE = 0x40;
                        IStream strm;
                        SHCreateStreamOnFileEx(manifestPath, STGM_SHARE_DENY_NONE, 0, false, IntPtr.Zero, out strm);
                        if (strm != null)
                        {
                            var reader = factory.CreateManifestReader(strm);
                            package._properties = reader.GetProperties();
                            package.Description = package.GetPropertyStringValue("Description");
                            package.DisplayName = package.GetPropertyStringValue("DisplayName");
                            package.Logo = package.GetPropertyStringValue("Logo");
                            package.PublisherDisplayName = package.GetPropertyStringValue("PublisherDisplayName");
                            package.IsFramework = package.GetPropertyBoolValue("Framework");

                            var apps = reader.GetApplications();
                            while (apps.GetHasCurrent())
                            {
                                var app = apps.GetCurrent();
                                var appx = new AppxApp(app);
                                appx.Description = GetStringValue(app, "Description");
                                appx.DisplayName = GetStringValue(app, "DisplayName");
                                appx.EntryPoint = GetStringValue(app, "EntryPoint");
                                appx.Executable = GetStringValue(app, "Executable");
                                appx.Id = GetStringValue(app, "Id");
                                appx.Logo = GetStringValue(app, "Logo");
                                appx.SmallLogo = GetStringValue(app, "SmallLogo");
                                appx.StartPage = GetStringValue(app, "StartPage");
                                appx.Square150x150Logo = GetStringValue(app, "Square150x150Logo");
                                appx.Square30x30Logo = GetStringValue(app, "Square30x30Logo");
                                appx.BackgroundColor = GetStringValue(app, "BackgroundColor");
                                appx.ForegroundText = GetStringValue(app, "ForegroundText");
                                appx.WideLogo = GetStringValue(app, "WideLogo");
                                appx.Wide310x310Logo = GetStringValue(app, "Wide310x310Logo");
                                appx.ShortName = GetStringValue(app, "ShortName");
                                appx.Square310x310Logo = GetStringValue(app, "Square310x310Logo");
                                appx.Square70x70Logo = GetStringValue(app, "Square70x70Logo");
                                appx.MinWidth = GetStringValue(app, "MinWidth");
                                package._apps.Add(appx);
                                apps.MoveNext();
                            }
                            Marshal.ReleaseComObject(strm);
                        }
                        yield return package;
                    }
                    Marshal.ReleaseComObject(factory);
                }
            }
            finally
            {
                if (infoBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(infoBuffer);
                }
                ClosePackageInfo(infoRef);
            }
        }
    }

    public static string LoadResourceString(string packageFullName, string resource)
    {
        if (packageFullName == null)
            throw new ArgumentNullException("packageFullName");

        if (string.IsNullOrWhiteSpace(resource))
            return null;

        const string resourceScheme = "ms-resource:";
        if (!resource.StartsWith(resourceScheme))
            return null;

        string part = resource.Substring(resourceScheme.Length);
        string url;

        if (part.StartsWith("/"))
        {
            url = resourceScheme + "//" + part;
        }
        else
        {
            url = resourceScheme + "///resources/" + part;
        }

        string source = string.Format("@{{{0}? {1}}}", packageFullName, url);
        var sb = new StringBuilder(1024);
        int i = SHLoadIndirectString(source, sb, sb.Capacity, IntPtr.Zero);
        if (i != 0)
            return null;

        return sb.ToString();
    }

    private static string GetStringValue(IAppxManifestProperties props, string name)
    {
        if (props == null)
            return null;

        string value;
        props.GetStringValue(name, out value);
        return value;
    }

    private static bool GetBoolValue(IAppxManifestProperties props, string name)
    {
        bool value;
        props.GetBoolValue(name, out value);
        return value;
    }

    internal static string GetStringValue(IAppxManifestApplication app, string name)
    {
        string value;
        app.GetStringValue(name, out value);
        return value;
    }

    [Guid("5842a140-ff9f-4166-8f5c-62f5b7b0c781"), ComImport]
    private class AppxFactory
    {
    }

    [Guid("BEB94909-E451-438B-B5A7-D79E767B75D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IAppxFactory
    {
        void _VtblGap0_2(); // skip 2 methods
        IAppxManifestReader CreateManifestReader(IStream inputStream);
    }

    [Guid("4E1BD148-55A0-4480-A3D1-15544710637C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IAppxManifestReader
    {
        void _VtblGap0_1(); // skip 1 method
        IAppxManifestProperties GetProperties();
        void _VtblGap1_5(); // skip 5 methods
        IAppxManifestApplicationsEnumerator GetApplications();
    }

    [Guid("9EB8A55A-F04B-4D0D-808D-686185D4847A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IAppxManifestApplicationsEnumerator
    {
        IAppxManifestApplication GetCurrent();
        bool GetHasCurrent();
        bool MoveNext();
    }

    [Guid("5DA89BF4-3773-46BE-B650-7E744863B7E8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IAppxManifestApplication
    {
        [PreserveSig]
        int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string vaue);
    }

    [Guid("03FAF64D-F26F-4B2C-AAF7-8FE7789B8BCA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IAppxManifestProperties
    {
        [PreserveSig]
        int GetBoolValue([MarshalAs(UnmanagedType.LPWStr)]string name, out bool value);
        [PreserveSig]
        int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string vaue);
    }

    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved);

    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int SHCreateStreamOnFileEx(string fileName, int grfMode, int attributes, bool create, IntPtr reserved, out IStream stream);

    [DllImport("user32.dll")]
    private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

    [DllImport("kernel32.dll")]
    private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [DllImport("kernel32.dll")]
    private static extern bool CloseHandle(IntPtr hObject);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int OpenPackageInfoByFullName(string packageFullName, int reserved, out IntPtr packageInfoReference);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetPackageInfo(IntPtr packageInfoReference, PackageConstants flags, ref int bufferLength, IntPtr buffer, out int count);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int ClosePackageInfo(IntPtr packageInfoReference);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetPackageFullName(IntPtr hProcess, ref int packageFullNameLength, StringBuilder packageFullName);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetApplicationUserModelId(IntPtr hProcess, ref int applicationUserModelIdLength, StringBuilder applicationUserModelId);

    [Flags]
    private enum PackageConstants
    {
        PACKAGE_FILTER_ALL_LOADED = 0x00000000,
        PACKAGE_PROPERTY_FRAMEWORK = 0x00000001,
        PACKAGE_PROPERTY_RESOURCE = 0x00000002,
        PACKAGE_PROPERTY_BUNDLE = 0x00000004,
        PACKAGE_FILTER_HEAD = 0x00000010,
        PACKAGE_FILTER_DIRECT = 0x00000020,
        PACKAGE_FILTER_RESOURCE = 0x00000040,
        PACKAGE_FILTER_BUNDLE = 0x00000080,
        PACKAGE_INFORMATION_BASIC = 0x00000000,
        PACKAGE_INFORMATION_FULL = 0x00000100,
        PACKAGE_PROPERTY_DEVELOPMENT_MODE = 0x00010000,
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    private struct PACKAGE_INFO
    {
        public int reserved;
        public int flags;
        public IntPtr path;
        public IntPtr packageFullName;
        public IntPtr packageFamilyName;
        public PACKAGE_ID packageId;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    private struct PACKAGE_ID
    {
        public int reserved;
        public AppxPackageArchitecture processorArchitecture;
        public ushort VersionRevision;
        public ushort VersionBuild;
        public ushort VersionMinor;
        public ushort VersionMajor;
        public IntPtr name;
        public IntPtr publisher;
        public IntPtr resourceId;
        public IntPtr publisherId;
    }
}

public sealed class AppxApp
{
    private AppxPackage.IAppxManifestApplication _app;

    internal AppxApp(AppxPackage.IAppxManifestApplication app)
    {
        _app = app;
    }

    public string GetStringValue(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        return AppxPackage.GetStringValue(_app, name);
    }

    // we code well-known but there are others (like Square71x71Logo, Square44x44Logo, whatever ...)
    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh446703.aspx
    public string Description { get; internal set; }
    public string DisplayName { get; internal set; }
    public string EntryPoint { get; internal set; }
    public string Executable { get; internal set; }
    public string Id { get; internal set; }
    public string Logo { get; internal set; }
    public string SmallLogo { get; internal set; }
    public string StartPage { get; internal set; }
    public string Square150x150Logo { get; internal set; }
    public string Square30x30Logo { get; internal set; }
    public string BackgroundColor { get; internal set; }
    public string ForegroundText { get; internal set; }
    public string WideLogo { get; internal set; }
    public string Wide310x310Logo { get; internal set; }
    public string ShortName { get; internal set; }
    public string Square310x310Logo { get; internal set; }
    public string Square70x70Logo { get; internal set; }
    public string MinWidth { get; internal set; }
}

public enum AppxPackageArchitecture
{
    x86 = 0,
    Arm = 5,
    x64 = 9,
    Neutral = 11,
    Arm64 = 12
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM