<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      利用 Win32 啟動和檢測 UWP App 的方法

      一種啟動和檢測 UWP 應用的方法

      背景

      我們發布過多款 UWP 平臺的同類型 App ,最近有一個需求:用傳統 Win32 程序啟動我們的 UWP 程序。因為我們的每一個UWP App在客戶機器上都是互斥的,也就是同時只能存在一個,并且我們的win32程序也只有一個版本,所以啟動 UWP App 時,需要先檢測,再啟動。

      我們大概有4個辦法,前3個比較扯,第4個目前可行,也是我們采用的。這4個方法的主要關注點是:如何檢測客戶機器上是否有我們的 UWP App。至于調用,方法比較簡單。

      Solution 1

      Win32 和 UWP 交互,首先想到的就是微軟的 Desktop Bridge 相關的內容,找了一圈,倒是發現了 Win32 調用 UWP Api 的方法,不過可以調用的 Api 有限,而且文檔比較殘缺,最麻煩的就是要對 Win32 Project 配置修改,引入一堆 WinRT 的東西。嘗試了半天,終于不報錯了,但是運行時會奔潰,原因未知,有待繼續探索。而且比較存疑的是官方文檔有矛盾,我們用到的 Windows.System.Launcher Api 是否被這種調用方式支持不明確,因為報錯我們也無法驗證。

      有興趣的小伙伴可以參考以下鏈接:

      Desktop Bridge

      Detect UWP App

      Solution 2

      簡單粗暴,直接檢測 UWP 的安裝目錄。一般 UWP 的默認安裝路徑就是 "C:\Program Files\WindowsApps"。這種方法真的很簡單粗暴,但是有幾個缺點:

      1. 可能有強迫癥用戶修改了 UWP 的安裝路徑。這種情況下,需要自行去查注冊表,當然注冊表鍵值是什么就需要baidu了;
      2. 如果直接枚舉 "C:\Program Files\WindowsApps"的子目錄,會有權限問題(System),普通用戶權限只能訪問類似 "C:\Program Files\WindowsApps\microsoft.windowscommunicationsapps_17.9126.21695.0_x64__8wekyb3d8bbwe"的特定 UWP App 目錄,這就需要我們提前確定要查找的 UWP App的 pfn (package family name,UWP App 的特定標識,全球唯一)和版本,但是版本因為經常變化,比較不好確定。

      Solution 3 (Solution 1和這個差不多)

      微軟為我們提供了許多啟動 UWP 的方式,比如什么協議啟動,命令行啟動等,但是這些方法的使用前提是:我們的UWP app需要修改現有的 App Manifest,這對于已經發布出去的UWP App,顯然是不可能的。(在我們的場景下,因為我們的 UWP App 和驅動綁定,一般隨驅動升級,比較穩定,所以此方法不可用)

      Solution 4 (Best solution)

      隱約記得以前使用 Fiddler 的時候,有一個 WinConfig 功能,可以列出當前電腦上所有的 UWP 程序(實際上是 沙箱類程序,從 Windows 8 開始, UWP 也包含其中),然后可以進行 web 調試。所以就想能不能借鑒 Fiddler 的做法。然后理所應當的發現 Fiddler 安裝目錄下面有一個名為 EnableLoopback.exe 的程序,沒有為什么,我就把它丟到了ILSpy里面,完美的反編譯出了C#代碼,然后經過一番探索,發現了AppContainer類,無論看類名還是類的定義,都很明確,這就是我們要找的東西,然后順著這個類看下去,找到了它獲取所有 UWP 程序的方法:通過 FirewallAPI.dll 里面的接口 NetworkIsolationEnumAppContainers 來枚舉。

      AppContainer

      有了了解,開始Coding!

      BTW,如果想省事兒的話,直接把這個類相關的內容導出,是可以直接用的。不過我們的 Win32 是用C++寫的,所以要稍稍轉換一下。

      C++代碼如下:

      #include <Netfw.h>
      #include <string>
      #include <vector>
      #include <algorithm>
      using namespace std;
      namespace Launcher
      {
          typedef DWORD(*pNetworkIsolationEnumAppContainers)(
              _In_  DWORD                        Flags,
              _Out_ DWORD                        *pdwNumPublicAppCs,
              _Out_ PINET_FIREWALL_APP_CONTAINER *ppPublicAppCs
              );
          typedef DWORD(*pNetworkIsolationFreeAppContainers)(
              _In_ PINET_FIREWALL_APP_CONTAINER pPublicAppCs
              );
          void LaunchSpecifcApp(wstring *pfn)
          {
              TCHAR szCommandLine[1024];
              wsprintf(szCommandLine, L"explorer.exe shell:AppsFolder\\%ws!App", (*pfn).c_str());
              STARTUPINFO si;
              PROCESS_INFORMATION pi;
              ZeroMemory(&si, sizeof(si));
              si.cb = sizeof(si);
              ZeroMemory(&pi, sizeof(pi));
      
              si.dwFlags = STARTF_USESHOWWINDOW;
              si.wShowWindow = TRUE;
      
              BOOL bRet = ::CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
      
          }
      
          void LaunchUWPApp()
          {
              vector<wstring> uwpApps;
              uwpApps.push_back(L"microsoft.windowscommunicationsapps_8wekyb3d8bbwe");
      
              HMODULE FirewallAPIModule;
              FirewallAPIModule = (LoadLibrary(L"FirewallAPI.dll"));
      
              auto EnumAppContainersProc = pNetworkIsolationEnumAppContainers(GetProcAddress(FirewallAPIModule, "NetworkIsolationEnumAppContainers"));
              auto FreeAppContainersProc = pNetworkIsolationFreeAppContainers(GetProcAddress(FirewallAPIModule, "NetworkIsolationFreeAppContainers"));
      
              DWORD pdwNumPublicAppCs = 0;
              PINET_FIREWALL_APP_CONTAINER ppPublicAppCs = NULL;
              HRESULT re = EnumAppContainersProc(0, &pdwNumPublicAppCs, &ppPublicAppCs);
      
              for (int i = 0; i < pdwNumPublicAppCs; i++)
              {
                  auto appContainer = ppPublicAppCs[i];
                  for (int j = 0; j < uwpApps.size(); j++)
                  {
                      auto app = uwpApps.at(j);
                      transform(app.begin(), app.end(), app.begin(), tolower);
                      if (app == appContainer.appContainerName)
                      {
                          //launch it;
                          auto temp = uwpApps.at(j);
                          LaunchSpecifcApp(&temp);
                      }
                  }
              }
              FreeAppContainersProc(ppPublicAppCs);
              FreeLibrary(FirewallAPIModule);
              vector<wstring>().swap(uwpApps);
          }
      }
      

      代碼很直白,里里面就兩個函數,一個用來查找,一個用來啟動,額外用到的就是 Win32 Dll 調用相關的內容了。

      最后

      可以看到,我們查找 UWP 比較麻煩,但是調用卻很簡單,核心就是:

      "explorer.exe shell:AppsFolder\{pfn}!App"
      
      {pfn} 整體用App的pfn代替
      

      很直白,赤裸裸的一個快捷方式呀!但是有坑,如果傳遞的參數有任何問題(要么拼錯了,要么不存在),explorer 會直接忽略參數,把自己啟動。這種行為,對于不明真相的用戶,會很莫名其妙,垃圾軟件。所以我們在啟動我們的 UWP App 時,要確保這個我們的 App 一定存在于用戶的電腦上面,所以才有了上面檢測 UWP App 的邏輯。如果參數錯誤,explorer 啥也不敢的話,我們就不這么麻煩了,可以直接把我們所有的 UWP app 挨個啟動一遍,簡單粗暴!

      最后的最后

      我們用到了 Fillder 里面所使用的方法,但對于 Fiddler 版權的各種問題,個人不了解。好在我們直接用 C++ 實現,沒有任何影響。 權當學習學習!

      之前網上有 Fiddler 2.x版本的源碼,但不清楚這軟件是不是開源。

      致敬 Fiddler !

      posted @ 2018-04-26 16:41  DemoApp  閱讀(3820)  評論(8)    收藏  舉報
      主站蜘蛛池模板: 天天躁日日躁狠狠躁中文字幕| 国产精成人品日日拍夜夜| 人人澡人摸人人添| 久久久久免费看成人影片| 99国产精品永久免费视频| 国产精品激情av在线播放| 久久国产免费观看精品3| 国产99久久久国产精品~~牛| 亚洲人精品午夜射精日韩| 亚洲成在人线在线播放无码| 无码人妻熟妇av又粗又大| 精品一日韩美女性夜视频| 天堂亚洲免费视频| 欧美巨大极度另类| 久久精品国产2020| 亚洲 日韩 国产 制服 在线| 国产国产久热这里只有精品| 孕交videos小孕妇xx| 欧美成人精品三级网站视频| 午夜福利激情一区二区三区| 成av免费大片黄在线观看| 好男人日本社区www| 少妇精品亚洲一区二区成人| 国产AV巨作丝袜秘书| 婷婷综合亚洲| 国产精品成人综合色在线| 国产盗摄xxxx视频xxxx| 狠狠躁夜夜躁人人爽天天古典| 国产性一交一乱一伦一色一情| 激情综合网一区二区三区| 日韩亚洲欧美中文高清| 人人入人人爱| 韩国三级网一区二区三区| 亚洲国产成人无码AV在线影院L| 高清| 欧美人与动zozo在线播放| 老太脱裤子让老头玩xxxxx| 国产成人精品无码播放| 色悠久久网国产精品99| 亚洲香蕉伊综合在人在线| 亚洲制服无码一区二区三区|