WinRT:システムにインストールされた Windows ストア アプリを列挙する(3)

執筆日時:

blog.daruyanagi.jp

3年前のブログ記事のソースコードを(ググったらでてきた……)そのままコピーしても動かなかったので。

復習しておくと、システムにインストールされた Windows ストア アプリを列挙するフローはこんな感じ。

まず、AppxManifest.xml を解析。前回との違いは、ネームスペースが変わっていても大丈夫なよう LocalName で要素を探すようにしたところぐらい。

private string GetDisplayNameFromManifest(string installedPath)
{
var xml = File.ReadAllText(Path.Combine(installedPath, "AppxManifest.xml"));
var doc = XDocument.Parse(xml);
var value = doc.Descendants().First(_ => _.Name.LocalName == "DisplayName").Value;

return value; }

次に ms-resource:// で記述されている場合の処理。ms-resource:// の書き方は数パターンあるようで、それに応じて処理を変えないといけない。

最初のパターンに寄せてから、SHLoadIndirectString() を使うことにした。

[DllImport("shlwapi.dll", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false, ThrowOnUnmappableChar = true)]
public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved);

private string GetTextFromResource(string installedPath, string name, string key) { var pri = Path.Combine(installedPath, "resources.pri"); var resourceKey = string.Empty;

if (key.Contains(name)) { // キーにアプリ名が含まれているパターン → そのままリソースキーとして扱う // ms-resource://Microsoft.SkypeApp/Resources/SkypeVideo_ProductName resourceKey = key; } else { // リソースキーの解析が必要なパターン // → とりあえずプロトコルを省く // ms-resource:///Resources/AppStoreName // ms-resource:/manifest/DisplayName // ms-resource:PackageDisplayName resourceKey = key.Split(':').Last();

if (resourceKey.StartsWith("/")) { // パスになっているパターン → アプリ名入りのパスに // :///Resources/AppStoreName // :/manifest/DisplayName resourceKey = resourceKey.TrimStart('/'); resourceKey = $"ms-resource://{name}/{resourceKey}"; } else { // リソース名になっているパターン → リソースへのパスに // :PackageDisplayName resourceKey = $"ms-resource://{name}/resources/{resourceKey}"; } }

var buffer = new StringBuilder(1024); // ← 適当

var result = SHLoadIndirectString( $"@{{{pri}? {resourceKey}}}", buffer, buffer.Capacity, IntPtr.Zero );

// 失敗したときはパスをそのまま返しておく return result == 0 ? buffer.ToString() : key; }

f:id:daruyanagi:20170702051825p:plain

うまくいっているみたい。「ストア」アプリと表記の違うパッケージもあるけど、今のところは気にしないことにする。