日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用 Win32 启动和检测 UWP App 的方法

發(fā)布時間:2025/3/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用 Win32 启动和检测 UWP App 的方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
原文:利用 Win32 啟動和檢測 UWP App 的方法

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

背景

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

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

Solution 1

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

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

Desktop Bridge

  • Enhance your desktop application for Windows 10

  • UWP APIs available to a packaged desktop app (Desktop Bridge)

Detect UWP App

  • UWP Quick Tip - Detect any installed app on Windows 10 這也是 Solution 1 的核心,一個小 trick

Solution 2

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

  • 可能有強迫癥用戶修改了 UWP 的安裝路徑。這種情況下,需要自行去查注冊表,當然注冊表鍵值是什么就需要baidu了;
  • 如果直接枚舉 "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 的特定標識,全球唯一)和版本,但是版本因為經(jīng)常變化,比較不好確定。
  • Solution 3 (Solution 1和這個差不多)

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

    Solution 4 (Best solution)

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

    有了了解,開始Coding!

    BTW,如果想省事兒的話,直接把這個類相關的內(nèi)容導出,是可以直接用的。不過我們的 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);} }

    代碼很直白,里里面就兩個函數(shù),一個用來查找,一個用來啟動,額外用到的就是 Win32 Dll 調(diào)用相關的內(nèi)容了。

    最后

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

    "explorer.exe shell:AppsFolder\\{pfn}!App"

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

    最后的最后

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

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

    致敬 Fiddler !

    總結

    以上是生活随笔為你收集整理的利用 Win32 启动和检测 UWP App 的方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。