2015-08-20 8 views
9

Ich habe eine Funktion entwickelt, die das Symbol des Fensters für ein bestimmtes Fensterhandle zurückgibt. Es sieht aus wie das.Icon einer "modernen" Windows-App von einer Desktop-Anwendung erhalten?

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."); 
    } 
} 

Ich benutze diese Funktion in Kombination mit GetForegroundWindow das Symbol des aktiven Fensters zu erhalten.

Es scheint jedoch die gleiche langweilig aussehende Ikone für universelle Anwendungen zu produzieren.

Ist es irgendwie möglich, das Kachelbild oder das Symbol von einer universellen App abzurufen, die gerade ausgeführt wird?

+0

'LoadIcon kann nur ein Symbol laden, dessen Größe den Systemmetrikwerten SM_CXICON und SM_CYICON entspricht. Verwenden Sie die LoadImage-Funktion, um Symbole anderer Größen zu laden. - [MSDN] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms648072%28v=vs.85%29.aspx) – theB

+1

Normalerweise würden Sie so etwas mit LoadLibraryEx machen ... aber Windows 10 Apps sind wirklich seltsam, sie haben ihr Icon nicht als Ressource in ihrer Hauptdatei gespeichert ... es befindet sich im Labyrinth der Ressourcendateien und Verzeichnisse, aus denen das Paket für die App besteht. Ich weiß nicht, dass es ein "großmaßstäbliches" Icon gibt, das von besagten Apps überhaupt abgerufen werden kann ... zumindest nicht vom Desktop. Aber ich schaue hinein, seit du meine Neugier geweckt hast. –

+1

Was ich finde, bin so weit, dass es tief im Inneren COM, wahrscheinlich gehen zu müssen, tun mit C++/CLI, und Sie müssen die Klassen-ID der Anwendung der primären Objekts wissen, vor der Zeit. Dies ist nur ein kurzer Blick auf die API-Dokumentationen. Ich steche nur im Dunkeln, aber ich scheine immer näher zu kommen. –

Antwort

11

Hier ist ein Beispielcode, der zeigt, wie das gemacht werden könnte. Beachten Sie, dass:

  1. Sie sollten laufen diese evelated, sonst werden Sie nicht in der Lage sein, Ordner zuzugreifen mit Anwendungsressourcen (glaube ich, habe mich wirklich nicht zu überprüfen, weil die Dinge zu untersuchen gewährte mir Zugang zu diesem Ordner).
  2. Moderne Anwendungen werden im ApplicationFrameHost-Hostprozess ausgeführt. Sie benötigen einige Tricks, um zur eigentlichen ausführbaren Datei (wie Calculator.exe) zu gelangen, diese Tricks werden im Code kommentiert.
  3. Das moderne App-Manifest enthält einen Pfad zum Logo, aber möglicherweise gibt es mehrere Logos (schwarz, weiß, weiß als Beispiel). Sie werden eine Logik brauchen, um eine zu wählen. Habe das nicht selbst im Detail untersucht.
  4. Ich testete dies auf Calculator App in Windows 10 und es hat gut funktioniert. Natürlich sind mehr Tests mit mehr Apps erforderlich, um sicherzustellen, dass alles in Ordnung ist. Hier

ist der Code:

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 

} 

Die Verwendung ist einfach:

var icon = IconHelper.GetForegroundWindowIcon(); 
+0

Vielen Dank für Ihre Antwort. Dies scheint in einer App zu funktionieren, ohne Administratorrechte zu benötigen. – Jason

+0

Seltsamerweise funktioniert das für einige Apps, aber nicht für andere. Es scheint nicht für Skype oder die App Einstellungen zu funktionieren. Es gibt kein Kind mit einem anderen Pid – Kir

4

Die meisten "modernen app" (oder Windows Store Apps oder Apps im appx Anwendungsmodell) Informationen kann von offiziellen APIs abgefragt werden.

Sie können mit der GetPackageFullName function beginnen (es erhält den vollen Namen des Pakets für den angegebenen Prozess). Sobald Sie den vollständigen Namen des Pakets erhalten, können Sie die Package Query API verwenden, um weitere Informationen zu erhalten.

Diese API sind native, daher haben sie nach meinem Wissen keine Entsprechung in .NET Framework. Sie sind jedoch irgendwie von der WinRT-Anwendung aus zugänglich (und Sie können tatsächlich auf einige der WinRT-APIs von Standard-.NET-Framework-Apps zugreifen, aber das ist ein bisschen hack).

Also, ich habe eine Dienstprogramm-Klasse gebaut, mit der Sie Informationen aus diesen Anwendungen erhalten können. Hier ist eine Beispielanwendung, die alle aktuellen geladenen Windows Store-Pakete & Apps ablegt.

Die Bilder in diesen Anwendungen sind speziell, weil sie als Ressourcen (Assets) Schlüssel definiert sind, die mithilfe von Qualifiern optimiert werden können, um einen endgültigen Pfad zu bilden. Dies ist zum Beispiel hier dokumentiert: How to name resources using qualifiers (HTML) und hier: Quickstart: Using file or image resources (HTML).

Das Problem ist, was Sie finden können, hängt stark von der Anwendung selbst, so ist es nicht sehr einfach zu bestimmen, welches Bild Sie verwenden können, und ich habe keine API dafür gefunden, also habe ich ein Muster, das die höchste erhält skalieren Sie das Bild für einen gegebenen Ressourcennamen als Beispiel (FindHighestScaleQualifiedImagePath). Sie können eine WPF-BitmapSource (oder eine andere Imaging-Plattform-Ressource) von diesem Pfad laden.

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 
} 
Verwandte Themen