遷移桌面程序到MS Store(14)——APPX嵌入WCF Service以Admin權限運行

Windows10 1809版本開始,微軟又對UWP開放了新的Capability:AllowElevation。 通過這個新的Capability,UWP APP能夠在運行時向用戶請求Admin權限,配合Windows 1607版本就引入的RunFullTrust Capability(參考《遷移桌面程序到MS Store(9)——APPX With Desktop Extension 》),我們可以讓MS Store中的APP擁有無限接近傳統桌面程序的能力。
本篇提到的Sample工程位於全球最大的同性交友平臺GitHub:
https://github.com/manupstairs/UWPAllowElevation

上圖解釋了整個程序運行的流程,UWP APP通過RunFullTrust Capability來運行一個exe程序,在這個exe程序中,又因爲新的AllowElevation而能夠請求Admin權限來啓動WCF Servcie。用戶在UAC彈窗中確認授予Admin權限後,我們就在UWP APP的身後擁有了一個具有Admin權限的WCF Service。
首先讓我們創建WCFBackgroundProcess工程,包含一個Hello World級別的WCF Service。在該服務的接口中,我們定義了三個方法,用來啓動,停止和查詢Windows Service狀態。這麼設計是因爲這些操作需要Admin權限。

    [ServiceContract]
    public interface ILocalService
    {

        [OperationContract]
        ServiceControllerStatus StartService(string name);

        [OperationContract]
        ServiceControllerStatus StopService(string name);

        [OperationContract]
        ServiceControllerStatus GetServiceStatus(string name);
    }

WCFBackgroundProcess工程本身是一個Console類型的程序,作爲exe啓動後,我們就可以在UWP Client工程中,添加對WCFBackgroundProcess中服務的引用。具體可以參考《遷移桌面程序到MS Store(7)——APPX + Service》。

    class Program
    {
        static void Main(string[] args)
        {
            var selfHost = new ServiceHost(typeof(LocalServiceWrapper));

            selfHost.Open();

            Console.WriteLine("The service is ready.");

            // Close the ServiceHost to stop the service.
            Console.WriteLine("Press <Enter> to terminate the service.");
            Console.WriteLine();
            Console.ReadLine();
            selfHost.Close();
        }
    }

Launcher工程是一個標準的Console程序,內容非常簡單,通過ProcessStartInfo類來啓動WCFBackgroundProcess.exe。該工程在UWP環境下所需的AllowElevation我們在創建Packaging工程時會添加。

    class Program
    {
        static void Main(string[] args)
        {
            string result = Assembly.GetExecutingAssembly().Location;
            int index = result.LastIndexOf("\\");
            string rootPath = $"{result.Substring(0, index)}\\..\\";

            rootPath += @"WCFBackgroundProcess\WCFBackgroundProcess.exe";

            ProcessStartInfo info = new ProcessStartInfo
            {
                Verb = "runas",
                UseShellExecute = true,
                FileName = rootPath
            };
            Process.Start(info);
        }
    }

接着創建UWPClient工程,這是一個標準的UWP項目。除了WCFBackgroundService的引用外,我們還需要通過NuGet添加Windows Desktop Extension for the UWP來實現對Launcher.exe的調用(參考《遷移桌面程序到MS Store(9)——APPX With Desktop Extension 》)。

 

UWPClient僅包含唯一的MainPage,四個按鈕事件分別負責啓動Launcher.exe,啓動、停止、查詢BluetoothService的狀態,代碼如下:

    public sealed partial class MainPage : Page
    {
        private string serviceName = "bthserv";
        private LocalServiceClient client = new LocalServiceClient();

        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void StopButton_Click(object sender, RoutedEventArgs e)
        {
            var status = await client.StopServiceAsync(serviceName);
            textBlockStatus.Text = status.ToString();
        }

        private async void StartButton_Click(object sender, RoutedEventArgs e)
        {
            var status = await client.StartServiceAsync(serviceName);
            textBlockStatus.Text = status.ToString();
        }

        private async void QueryButton_Click(object sender, RoutedEventArgs e)
        {
            var status = await client.GetServiceStatusAsync(serviceName);
            textBlockStatus.Text = status.ToString();
        }

        private async void RunWCFService_Click(object sender, RoutedEventArgs e)
        {
            if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
            {
                await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
            }
        }
    }

以上就是所有的準備工作。然後我們創建作爲啓動項目的AllowElevationPackaging工程(參考《遷移桌面程序到MS Store(1)——通過Visual Studio創建Packaging工程》)。在AllowElevationPackaging的Applications中包含之前創建的所有三個工程,同時將UWPClient設爲Entry Point。

右鍵選中Package.aapxmanifest後進行編輯,在<Application/>節點中添加:

      <Extensions>
        <desktop:Extension xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10" Category="windows.fullTrustProcess" Executable="Launcher\Launcher.exe" />
      </Extensions>

同時修改Capabilities節點:

  <Capabilities>
    <Capability Name="internetClient" />
    <rescap:Capability Name="runFullTrust" />
    <rescap:Capability Name="allowElevation" />
  </Capabilities>

完成後保存關閉文件,大功告成!編譯整個解決方案確保沒有任何錯誤,然後讓我們點擊F5開始運行(記得將AllowElevationPackaging設爲啓動項)。
首先我們先點擊Apply for Elevation capability and Run WCF Service按鈕。在UAC窗口中我們同意給予Admin權限,WCF Service順利啓動。感興趣的同學可以通過窗口的標題欄查看WCFBackgroundProcess.exe的物理路徑。

然後我們即可以開始查詢藍牙服務的運行狀態了。如果用的是藍牙鼠標,在點擊Stop Blue Support Service的同時不要驚慌失措哦。本篇作爲《遷移桌面程序到MS Store》系列的最終篇,沒人看的系列就準備太監了。猶豫就會敗北,果斷就會白給。後續博客將專注於.NET Core的學習,與諸君共勉!

GitHub:
https://github.com/manupstairs/UWPAllowElevation

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章