Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Lär dig hur du skriver en UWP-app som använder Windows-enhetsportalen (WDP) som värd för en webbsida och tillhandahåller diagnostikinformation.
Från och med Windows 10 Creators Update (version 1703, version 15063) kan du använda enhetsportalen som värd för appens diagnostikgränssnitt. Den här artikeln beskriver de tre delar som behövs för att skapa en DevicePortalProvider för din app – programpaketmanifestet ändringar, konfigurera appens anslutning till Device Portal-tjänstenoch hantera en inkommande begäran.
Skapa ett nytt UWP-appprojekt
Skapa ett nytt UWP-appprojekt i Microsoft Visual Studio. Gå till File > New > Project och välj Tom app (Windows Universal) för C#och klicka sedan på Nästa. I dialogrutan Konfigurera ditt nya projekt. Ge projektet namnet "DevicePortalProvider" och klicka sedan på Skapa. Det här är appen som innehåller apptjänsten. Du kan behöva uppdatera Visual Studio eller installera den senaste Windows SDK.
Lägg till devicePortalProvider-tillägget i programpaketmanifestet
Du måste lägga till kod i package.appxmanifest-filen för att appen ska fungera som ett plugin-program för enhetsportalen. Lägg först till följande namnområdesdefinitioner överst i filen. Lägg också till dem i attributet IgnorableNamespaces
.
<Package
...
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
IgnorableNamespaces="uap mp rescap uap4">
...
För att kunna deklarera att din app är en provider för enhetsportalen måste du skapa en apptjänst och ett nytt providertillägg för enhetsportalen som använder den. Lägg till både windows.appService-tillägget och tillägget windows.devicePortalProvider i Extensions
-elementet under Application
. Kontrollera att AppServiceName
-attributen matchar i varje tillägg. Detta anger för enhetsportaltjänsten att den här apptjänsten kan startas för att hantera begäranden på hanterarens namnområde.
...
<Application
Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="DevicePortalProvider.App">
...
<Extensions>
<uap:Extension Category="windows.appService" EntryPoint="MySampleProvider.SampleProvider">
<uap:AppService Name="com.sampleProvider.wdp" />
</uap:Extension>
<uap4:Extension Category="windows.devicePortalProvider">
<uap4:DevicePortalProvider
DisplayName="My Device Portal Provider Sample App"
AppServiceName="com.sampleProvider.wdp"
HandlerRoute="/MyNamespace/api/" />
</uap4:Extension>
</Extensions>
</Application>
...
Attributet HandlerRoute
refererar till REST-namnområdet som din app hävdar. Alla HTTP-begäranden på det namnområdet (implicit följt av ett jokertecken) som tas emot av enhetsportaltjänsten skickas till din app för att hanteras. I det här fallet skickas alla autentiserade HTTP-begäranden till <ip_address>/MyNamespace/api/*
till din app. Konflikter mellan hanteringsvägar löses genom en kontroll där den längsta matchningen vinner: den väg som matchar flest av begärandena väljs, vilket innebär att en begäran till "/MyNamespace/api/foo" matchar en leverantör med "/MyNamespace/api" i stället för en med "/MyNamespace".
Två nya funktioner krävs för den här funktionen. De måste också läggas till i filen package.appxmanifest.
...
<Capabilities>
...
<Capability Name="privateNetworkClientServer" />
<rescap:Capability Name="devicePortalProvider" />
</Capabilities>
...
Anmärkning
Funktionen "devicePortalProvider" är begränsad ("sammanfattning"), vilket innebär att du måste få förhandsgodkännande från Store innan appen kan publiceras där. Detta hindrar dock inte dig från att testa din app lokalt genom sideloading. Mer information om begränsade funktioner finns i App-funktionsdeklarationer.
Konfigurera bakgrundsuppgiften och WinRT-komponenten
För att kunna konfigurera anslutningen till enhetsportalen måste din app ansluta en apptjänstanslutning från enhetsportaltjänsten med instansen av enhetsportalen som körs i din app. Det gör du genom att lägga till en ny WinRT-komponent i ditt program med en klass som implementerar IBackgroundTask.
using Windows.System.Diagnostics.DevicePortal;
using Windows.ApplicationModel.Background;
namespace MySampleProvider {
// Implementing a DevicePortalConnection in a background task
public sealed class SampleProvider : IBackgroundTask {
BackgroundTaskDeferral taskDeferral;
DevicePortalConnection devicePortalConnection;
//...
}
Kontrollera att namnet matchar namnområdet och klassnamnet som konfigurerats av AppService EntryPoint ("MySampleProvider.SampleProvider"). När du gör din första begäran till enhetsportalprovidern kommer enhetsportalen att gömma begäran, starta appens bakgrundsaktivitet, anropa metoden Kör och skicka in en IBackgroundTaskInstance-. Appen använder den sedan för att konfigurera en DevicePortalConnection-instans.
// Implement background task handler with a DevicePortalConnection
public void Run(IBackgroundTaskInstance taskInstance) {
// Take a deferral to allow the background task to continue executing
this.taskDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += TaskInstance_Canceled;
// Create a DevicePortal client from an AppServiceConnection
var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
var appServiceConnection = details.AppServiceConnection;
this.devicePortalConnection = DevicePortalConnection.GetForAppServiceConnection(appServiceConnection);
// Add Closed, RequestReceived handlers
devicePortalConnection.Closed += DevicePortalConnection_Closed;
devicePortalConnection.RequestReceived += DevicePortalConnection_RequestReceived;
}
Det finns två händelser som måste hanteras av appen för att slutföra begärandehanteringsloopen: Stängd, för när enhetsportaltjänsten stängs av och RequestReceived, som visar inkommande HTTP-begäranden och tillhandahåller huvudfunktionerna för enhetsportalprovidern.
Hantera RequestReceived-händelsen
Händelsen RequestReceived genereras en gång för varje HTTP-begäran som görs på plugin-programmets angivna hanteringsväg. Loopen för hantering av begäranden för enhetsportalprovidrar liknar den i NodeJS Express: begärande- och svarsobjekten tillhandahålls tillsammans med händelsen och hanteraren svarar genom att fylla i svarsobjektet. I enhetsportalleverantörer använder RequestReceived-händelsen och dess hanterare Windows.Web.Http.HttpRequestMessage och HttpResponseMessage-objekt.
// Sample RequestReceived echo handler: respond with an HTML page including the query and some additional process information.
private void DevicePortalConnection_RequestReceived(DevicePortalConnection sender, DevicePortalConnectionRequestReceivedEventArgs args)
{
var req = args.RequestMessage;
var res = args.ResponseMessage;
if (req.RequestUri.AbsolutePath.EndsWith("/echo"))
{
// construct an html response message
string con = "<h1>" + req.RequestUri.AbsoluteUri + "</h1><br/>";
var proc = Windows.System.Diagnostics.ProcessDiagnosticInfo.GetForCurrentProcess();
con += String.Format("This process is consuming {0} bytes (Working Set)<br/>", proc.MemoryUsage.GetReport().WorkingSetSizeInBytes);
con += String.Format("The process PID is {0}<br/>", proc.ProcessId);
con += String.Format("The executable filename is {0}", proc.ExecutableFileName);
res.Content = new Windows.Web.HttpStringContent(con);
res.Content.Headers.ContentType = new Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("text/html");
res.StatusCode = Windows.Web.Http.HttpStatusCode.Ok;
}
//...
}
I den här exempelbegärandehanteraren hämtar vi först begärande- och svarsobjekten från parametern args och skapar sedan en sträng med begärande-URL:en och ytterligare HTML-formatering. Detta läggs till i objektet Svar som en HttpStringContent-instans. Andra IHttpContent- klasser, till exempel de för "String" och "Buffer" är också tillåtna.
Svaret anges sedan som ett HTTP-svar och får statuskoden 200 (OK). Det bör visas som förväntat i webbläsaren som gjorde det ursprungliga anropet. Observera att när RequestReceived händelsehanterare returnerar returneras svarsmeddelandet automatiskt till användaragenten: ingen ytterligare "skicka"-metod behövs.
Tillhandahålla statiskt innehåll
Statiskt innehåll kan hanteras direkt från en mapp i paketet, vilket gör det mycket enkelt att lägga till ett användargränssnitt till din leverantör. Det enklaste sättet att hantera statiskt innehåll är att skapa en innehållsmapp i projektet som kan mappas till en URL.
Lägg sedan till en routningshanterare i din RequestReceived händelsehanterare som identifierar statiska innehållsvägar och mappar en begäran på rätt sätt.
if (req.RequestUri.LocalPath.ToLower().Contains("/www/")) {
var filePath = req.RequestUri.AbsolutePath.Replace('/', '\\').ToLower();
filePath = filePath.Replace("\\backgroundprovider", "")
try {
var fileStream = Windows.ApplicationModel.Package.Current.InstalledLocation.OpenStreamForReadAsync(filePath).GetAwaiter().GetResult();
res.StatusCode = HttpStatusCode.Ok;
res.Content = new HttpStreamContent(fileStream.AsInputStream());
res.Content.Headers.ContentType = new HttpMediaTypeHeaderValue("text/html");
} catch(FileNotFoundException e) {
string con = String.Format("<h1>{0} - not found</h1>\r\n", filePath);
con += "Exception: " + e.ToString();
res.Content = new Windows.Web.Http.HttpStringContent(con);
res.StatusCode = Windows.Web.Http.HttpStatusCode.NotFound;
res.Content.Headers.ContentType = new Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("text/html");
}
}
Kontrollera att alla filer i innehållsmappen är markerade som "Innehåll" och ange till "Kopiera om nyare" eller "Kopiera alltid" på Menyn Egenskaper i Visual Studio. Detta säkerställer att filerna kommer att finnas i ditt AppX-paket när du distribuerar det.
Använda befintliga resurser och API:er för enhetsportalen
Statiskt innehåll som hanteras av en enhetsportalprovider hanteras på samma port som den centrala enhetsportaltjänsten. Det innebär att du kan referera till befintliga JS och CSS som ingår i enhetsportalen med enkla <link>
- och <script>
-taggar i HTML-koden. I allmänhet föreslår vi användning av rest.js, som omsluter alla REST-API:er för enhetsportalen i ett praktiskt webbRest-objekt och filen common.css, vilket gör att du kan formatera innehållet så att det passar resten av enhetsportalens användargränssnitt. Du kan se ett exempel på detta på sidan index.html som ingår i exemplet. Den använder rest.js för att hämta enhetsnamnet och köra processer från enhetsportalen.
Viktigt är att användningen av Metoderna HttpPost/DeleteExpect200 på webbRest automatiskt gör CSRF-hantering åt dig, vilket gör att webbsidan kan anropa tillståndsförändrande REST-API:er.
Anmärkning
Det statiska innehåll som ingår i enhetsportalen har ingen garanti för icke-bakåtkompatibla ändringar. Även om API:erna inte förväntas ändras ofta kan de, särskilt i common.js och controls.js filerna, som din leverantör inte bör använda.
Felsöka anslutningen till enhetsportalen
För att kunna felsöka bakgrundsaktiviteten måste du ändra hur Visual Studio kör koden. Följ stegen nedan för att felsöka en apptjänstanslutning för att kontrollera hur leverantören hanterar HTTP-begäranden:
- På menyn Felsök väljer du Egenskaper för DevicePortalProvider.
- Under fliken Felsökning går du till avsnittet Starta åtgärd och väljer "Starta inte, men felsök min kod när den startar".
- Ange en brytpunkt i din RequestReceived-hanteringsfunktion.
Anmärkning
Kontrollera att byggarkitekturen matchar målarkitekturen exakt. Om du använder en 64-bitars dator måste du distribuera med en AMD64-version. 4. Tryck på F5 för att distribuera din app 5. Inaktivera Enhetsportalen och aktivera den igen så att den hittar din app (behövs bara när du ändrar appmanifestet – resten av tiden kan du helt enkelt distribuera om och hoppa över det här steget). 6. Gå till leverantörens namnområde i webbläsaren och brytpunkten ska nås.