1.首先建立UWP專案

在參考新增Windows Desktop Extensions for the UWP 套件

修改Package.appmainifest讓UWP可以啟動Win32並透過AppService溝通,首先新增標籤
<Package
xmlns=”http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp=”http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap=”http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap=”http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop=”http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:uap3=”http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
IgnorableNamespaces=”uap mp uap3">
在Application標籤最後之前加入Extensions
<Extensions>
<desktop:Extension Category=”windows.fullTrustProcess” Executable=”exe檔案的位置(Assets/ConsoleFolder.exe)”>
<desktop:FullTrustProcess></desktop:FullTrustProcess>
</desktop:Extension>
<uap:Extension Category=”windows.appService”>
<uap:AppService Name=”自訂建立連線的Service名稱(GetFolderService)”/>
</uap:Extension>
</Extensions>
</Application>
在後面的Capabilities標籤加上runFullTrust
<Capabilities>
<Capability Name=”internetClient” />
<rescap:Capability Name=”runFullTrust” />
</Capabilities>
2.在App.xaml.cs中引入元件
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
在OnLaunched function中,啟動Win32 Process
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
LaunchWin32Process();
…
}
private async void LaunchWin32Process()
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
}
3.新增一個Console Project

右鍵對方案的屬性進行設定,讓FolderApp對ConsoleFolder進行依賴

在ConsoleFolder中的屬性進行編譯後的設定,將編譯後的exe放入FolderApp中

執行一次後會出錯,但在Assets中會出現ConsoleFolder編譯完成的執行檔,
將此執行檔加入專案中就不會再出錯了


4.建立AppServiceppService物件,當背景啟動App時用AppServiceTriggerDetails創建連線並實作連線方法,以及Cancel處理(在App.xaml.cs中實作)
static AppServiceConnection Connection = null;
BackgroundTaskDeferral AppServiceDeferral = null;
protected async override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
if(args.TaskInstance.TriggerDetails is AppServiceTriggerDetails)
{
AppServiceDeferral = args.TaskInstance.GetDeferral();
args.TaskInstance.Canceled += OnTaskCanceled;
AppServiceTriggerDetails details = args.TaskInstance.TriggerDetails as AppServiceTriggerDetails;
Connection = details.AppServiceConnection;
// Send request to win32
await SendToWin32();
}
}
private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
if(this.AppServiceDeferral!= null)
{
// Complete the service defferral
this.AppServiceDeferral.Complete();
}
}
private async Task SendToWin32()
{
ValueSet valuePairs = new ValueSet();
valuePairs.Add(“GetListFolder”, “”);
AppServiceResponse response = null;
response = await Connection.SendMessageAsync(valuePairs);
ApplicationDataContainer container = Windows.Storage.ApplicationData.Current.LocalSettings;
container.Values[“FolderList”] = response.Message[“FolderList”];
}
5.回到ConsoleFolder專案,先加入引用(到WinSDK路徑上去找)

選擇Windows.winmd和System.Runtime.WindowsRuntime.dll

6.在Program.cs中建立AppServiceConnection物件,並開一個Thread去監聽來自UWP的訊息
static AppServiceConnection connection;
static void Main(string[] args)
{
new Thread(ThreadProc).Start();
while (true) ;
}
static async void ThreadProc()
{
connection = new AppServiceConnection();
connection.AppServiceName = “GetFolderService”;
connection.PackageFamilyName = Package.Current.Id.FamilyName;
connection.RequestReceived += Connection_RequestReceived;
AppServiceConnectionStatus status = await connection.OpenAsync();
switch (status)
{
case AppServiceConnectionStatus.Success:
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(“Connection established — waiting for requests”);
Console.WriteLine();
break;
case AppServiceConnectionStatus.AppNotInstalled:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(“The app AppServicesProvider is not installed.”);
return;
case AppServiceConnectionStatus.AppUnavailable:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(“The app AppServicesProvider is not available.”);
return;
case AppServiceConnectionStatus.AppServiceUnavailable:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(string.Format(“The app AppServicesProvider is installed but it does not provide the app service {0}.”, connection.AppServiceName));
return;
case AppServiceConnectionStatus.Unknown:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(string.Format(“An unkown error occurred while we were trying to open an AppServiceConnection.”));
return;
}
}
在Connection收到資料時處理的Function,回傳資料時一樣用ValueSet放Key和Value,用SendResponseAsync回傳給UWP
private static async void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
string key = args.Request.Message.First().Key;
Console.WriteLine(key);
ValueSet valuePairs = new ValueSet();
valuePairs.Add(“FolderList”, folder2.ToArray());
valuePairs.Add(“FileList”, fileList.ToArray());
await args.Request.SendResponseAsync(valuePairs);
}
7.最後,因為要在MainPage.xaml.cs和Program.cs溝通,在App.xaml.cs需要將載入Frame的時間點在OnBackgroundActivated而不是在OnLaunched,到了MainPage就可以Call使用
AppServiceResponse response = null;
response = await App.Connection.SendMessageAsync(valuePairs);
response一樣用ValueSet的方式進行取值