Aufrufen von systemeigenem Code aus webseitigem Code
WebView2 ermöglicht Es Anwendungen, die Lücke zwischen dem Web und der nativen Seite einer Anwendung zu schließen, indem ein Objekt an das Web übergeben werden kann. Sie machen ausgewählte native APIs für JavaScript ihrer Webseite über ein im nativen Code definiertes zwischengeschaltetes natives Hostobjekt verfügbar. Die nativen APIs werden mithilfe der WebView2-API AddHostObjectToScript
in JavaScript projiziert.
In diesem Artikel wird hauptsächlich Win32/C++ behandelt, und es werden auch einige Aspekte von .NET/C# innerhalb von Frames behandelt. Informationen zu WinRT finden Sie unter Aufrufen von nativem WinRT-Code aus webseitigem Code.
Gründe für die Verwendung AddHostObjectToScript
von ?
Beim Entwickeln einer WebView2-App tritt möglicherweise ein natives Objekt auf, dessen Methoden oder Eigenschaften Sie nützlich finden. Möglicherweise möchten Sie diese nativen Objektmethoden aus webseitigem Code als Ergebnis einer Benutzerinteraktion auf der Webseite Ihrer App auslösen. Darüber hinaus möchten Sie die Methoden Ihrer nativen Objekte möglicherweise nicht erneut in Ihren webseitigen Code implementieren. Die
AddHostObjectToScript
API ermöglicht die Wiederverwendung von nativem Code durch webseitigen Code.Beispielsweise kann es eine native Webcam-API geben, für die eine große Menge an Code auf der Webseite neu geschrieben werden muss. Die Möglichkeit, die Methoden des nativen Objekts aufzurufen, ist schneller und effizienter, als die Methoden des Objekts auf der Webseite Ihrer App neu zu codieren. In diesem Fall kann Ihr nativer Code das Objekt an den webseitigen JavaScript-Code Ihrer App übergeben, sodass Ihr JavaScript-Code die Methoden der nativen API wiederverwenden kann.
Szenarien, die von der Verwendung von Hostobjekten im Skript profitieren können:
Es gibt eine Tastatur-API, und Sie möchten die
keyboardObject.showKeyboard
Funktion von der Webseite aufrufen.Zugriff auf das Dateisystem, nicht nur auf die Sandbox für Webseiten, über JavaScript. JavaScript ist eine Sandbox, die verhindert, dass es direkt auf das Dateisystem zugreifen kann. Wenn Sie verwenden
AddHostObjectToScript
, um ein natives Objekt zu erstellen, das für JavaScript verfügbar gemacht wird, können Sie das Hostobjekt verwenden, um Dateien im Dateisystem zu bearbeiten, nicht nur in der Sandbox für Webseiten.
In diesem Artikel wird die Win32-Beispiel-App verwendet, um einige praktische Anwendungen von zu veranschaulichen AddHostObjectToScript
.
Schritt 1: Installieren von Visual Studio, Installieren von Git, Klonen des WebView2Samples-Repositorys und Öffnen der Projektmappe
Laden Sie Microsoft Visual Studio 2019 (Version 16.11.10) oder höher herunter, und installieren Sie sie, und installieren Sie es, und installieren Sie andere Voraussetzungen, wie unter Win32-Beispiel-App beschrieben. Die Win32-Beispiel-App wurde mit Visual Studio 2019 erstellt. Um die Beispielschritte in diesem Artikel auszuführen, empfehlen wir daher, mit Visual Studio 2019 statt mit Visual Studio 2022 zu beginnen.
Klonen Sie das WebView2Samples-Repository . Das Repository enthält die Win32-spezifische WebView2-Beispiel-App. Anweisungen in einem neuen Fenster oder einer neuen Registerkarte finden Sie unter Win32-Beispiel-App.
Öffnen Sie Microsoft Visual Studio. Es wird empfohlen, das Win32-Beispiel zunächst mit Visual Studio 2019 zu öffnen.
Öffnen>
WebView2Samples
>SampleApps
Sie in Ihrer lokalen Kopie des geklontenWebView2Samples
Repositorys WebView2Samples.sln.WebView2Samples.sln
enthält dasWebView2APISample
Projekt, bei dem es sich um die Win32-Beispiel-App handelt. Lassen Sie die Beispiel-App-Lösung geöffnet, um den Rest dieses Artikels zu befolgen.
Schritt 2: Definieren der COM-Schnittstelle des Hostobjekts mithilfe von IDL
Definieren Sie die COM-Schnittstelle des Hostobjekts in einer .idl
Datei wie HostObjectSample.idl, um die Methoden und Eigenschaften für das Hostobjekt zu beschreiben.
Verwenden Sie zunächst die Schnittstellendefinitionssprache (Interface Definition Language, IDL), um die COM-Schnittstelle des Hostobjekts zu definieren. Diese Hostobjektdefinition in einer idl
Datei beschreibt die verfügbar gemachten (oder "umschlossenen") nativen Eigenschaften und Methoden. Die IDL-Datei (.idl
) definiert eine Schnittstelle, implementiert sie jedoch nicht.
Erweitern Sie im Projektmappen-Explorer von Visual Studio WebView2APIQuelldateien>, und doppelklicken Sie dann,
HostObjectSample.idl
um es zu öffnen.Der folgende Code definiert die
IHostObjectSample
-Schnittstelle, die gemäß dem Standard für COM erbtIUnknown
. Verwenden Sie dieseIHostObjectSample
Definition als Vorlage zum Definieren der Methoden, Eigenschaften, Rückruffunktionen usw. ihres Objekts.import "oaidl.idl"; import "ocidl.idl"; [uuid(0a7a4655-5660-47d0-8a37-98ae21399e57), version(0.1)] library HostObjectSampleLibrary { [uuid(3a14c9c0-bc3e-453f-a314-4ce4a0ec81d8), object, local] interface IHostObjectSample : IUnknown { // Demonstrates a basic method call with some parameters and a return value. HRESULT MethodWithParametersAndReturnValue([in] BSTR stringParameter, [in] INT integerParameter, [out, retval] BSTR* stringResult); // Demonstrate getting and setting a property. [propget] HRESULT Property([out, retval] BSTR* stringResult); [propput] HRESULT Property([in] BSTR stringValue); [propget] HRESULT IndexedProperty(INT index, [out, retval] BSTR * stringResult); [propput] HRESULT IndexedProperty(INT index, [in] BSTR stringValue); // Demonstrate native calling back into JavaScript. HRESULT CallCallbackAsynchronously([in] IDispatch* callbackParameter); // Demonstrates a property which uses Date types. [propget] HRESULT DateProperty([out, retval] DATE * dateResult); [propput] HRESULT DateProperty([in] DATE dateValue); // Creates a date object on the native side and sets the DateProperty to it. HRESULT CreateNativeDate(); };
Beachten Sie oben die
DateProperty
, die einenDATE
-Typ verwendet. Wir konzentrieren uns in diesem Artikel auf diese Datumsdemoeigenschaft.
Schritt 3: Definieren einer Hostobjekt-Co-Klasse
Als Nächstes definiert das Beispiel die HostObjectSample
Co-Klasse, um und IDispatch
einzuschließenIHostObjectSample
.
Untersuchen Sie in
HostObjectSample.idl
dieHostObjectSample
Co-Klasse (Komponentenobjektklasse), die dieIHostObjectSample
Schnittstellen undIDispatch
enthält:[uuid(637abc45-11f7-4dde-84b4-317d62a638d3)] coclass HostObjectSample { [default] interface IHostObjectSample; interface IDispatch; }; }
Die
HostObjectSample
Co-Klasse enthältinterface IDispatch
, was erforderlich ist, damit das Hostobjekt mitAddHostObjectToScript
funktioniert.
Schritt 4: Implementieren der Elemente des C++-Objekts
Im Win32-Beispiel-App-Code übernimmt HostObjectSampleImpl.cpp das Gerüst, das in der COM-IDL-Datei erstellt wurde, und implementiert jedes Element des C++-Objekts. Diese C++-Datei (.cpp
) implementiert die definierte Schnittstelle (und implementiert IDispatch
auch ).
Implementieren Sie alle Funktionen, die in der Schnittstelle Ihres Objekts definiert sind, wie in der IDL-Datei beschrieben. Stellen Sie sicher, dass Sie die Funktionen implementieren, die für IDispatch
erforderlich sind. Der Compiler löst einen Fehler aus, wenn diese Funktionen nicht definiert sind.
Als Nächstes untersuchen wir zwei spezifische Eigenschaften, die in der IDL definiert wurden, um zu zeigen, wie die IDL mit der .cpp
Datei verknüpft ist.
Erweitern Sie im Projektmappen-Explorer von Visual Studio WebView2APIQuelldateien>, und doppelklicken Sie dann auf HostObjectSampleImpl.cpp, um es zu öffnen.
Untersuchen Sie die Eigenschaftendeklarationen in HostObjectSample.idl:
// Demonstrate getting and setting a property. [propget] HRESULT Property([out, retval] BSTR* stringResult); [propput] HRESULT Property([in] BSTR stringValue); ... // Demonstrate a property which uses Date types [propget] HRESULT DateProperty([out, retval] DATE * dateResult); [propput] HRESULT DateProperty([in] DATE dateValue); // Creates a date object on the native side and sets the DateProperty to it. HRESULT CreateNativeDate();
Untersuchen Sie die Implementierung der Eigenschaften des Objekts in HostObjectSampleImpl.cpp:
STDMETHODIMP HostObjectSample::get_Property(BSTR* stringResult) { *stringResult = SysAllocString(m_propertyValue.c_str()); return S_OK; } STDMETHODIMP HostObjectSample::put_Property(BSTR stringValue) { m_propertyValue = stringValue; return S_OK; } ... STDMETHODIMP HostObjectSample::get_DateProperty(DATE* dateResult) { *dateResult = m_date; return S_OK; } STDMETHODIMP HostObjectSample::put_DateProperty(DATE dateValue) { m_date = dateValue; SYSTEMTIME systemTime; if (VariantTimeToSystemTime(dateValue, &systemTime)) ... } STDMETHODIMP HostObjectSample::CreateNativeDate() { SYSTEMTIME systemTime; GetSystemTime(&systemTime); DATE date; if (SystemTimeToVariantTime(&systemTime, &date)) { return put_DateProperty(date); } return E_UNEXPECTED; }
Untersuchen Sie
DateProperty
, die wir in diesem Artikel nachverfolgen.
Schritt 5: Implementieren von IDispatch
Das Hostobjekt muss implementieren IDispatch
, damit WebView2 das native Hostobjekt in den webseitigen Code der App projizieren kann.
IDispatch
ermöglicht das dynamische Aufrufen von Methoden und Eigenschaften. Normalerweise erfordert das Aufrufen von Objekten statische Aufrufe, aber Sie können JavaScript verwenden, um Objektaufrufe dynamisch zu erstellen. Im Win32-Beispiel-App-Code implementiert IDispatch
HostObjectSampleImpl.cpp , was bedeutet, dass diese Methoden implementiert werden:
GetIDsOfNames
GetTypeInfo
GetTypeInfoCount
Invoke
Implementieren Sie IDispatch
wie unter Typbibliotheken und objektbeschreibungssprache beschrieben. Weitere Informationen zu IDispatch
Vererbung und Methoden finden Sie unter IDispatch-Schnittstelle (oaidl.h).
Wenn das Objekt, das Sie JavaScript hinzufügen möchten, noch nicht implementiert IDispatch
, müssen Sie einen IDispatch
Klassenwrapper für das Objekt schreiben, das Sie verfügbar machen möchten.
Möglicherweise gibt es Bibliotheken, die dies automatisch tun. Weitere Informationen zu den Schritten, die zum Schreiben eines IDispatch
Klassenwrappers für das Objekt erforderlich sind, das Sie verfügbar machen möchten, finden Sie unter Automatisierung.
Speichern Sie als Nächstes alle Änderungen, die Sie im Projekt vorgenommen haben.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf WebView2APISample (die Win32-Beispiel-App), und wählen Sie dann Erstellen aus. Dadurch wird eine COM-Typbibliotheksdatei
.tlb
erstellt. Sie müssen aus dem.tlb
C++-Quellcode auf die Datei verweisen. Weitere Informationen finden Sie unter Typbibliothek in COM, DCOM und Typbibliotheken.
Schritt 6: Aufrufen von AddHostObjectToScript, um das Hostobjekt an webseitigen Code zu übergeben
Bisher haben wir unsere Schnittstelle erstellt und unser natives Hostobjekt implementiert. Jetzt können wir verwenden AddHostObjectToScript
, um das native Hostobjekt an den webseitigen JavaScript-Code unserer App zu übergeben. Die Win32-Beispiel-App ruft AddHostObjectToScript
in ScenarioAddHostObject.cpp auf, wie unten gezeigt.
Öffnen Sie im Projektmappen-Explorer von Visual Studio WebView2APISample>Source Files>ScenarioAddHostObject.cpp.
Wechseln Sie zur
ScenarioAddHostObject
Klassenimplementierung. Diese Klasse zeigt HTML an und behandelt die Navigation:ScenarioAddHostObject::ScenarioAddHostObject(AppWindow* appWindow) : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) { std::wstring sampleUri = m_appWindow->GetLocalUri(L"ScenarioAddHostObject.html"); m_hostObject = Microsoft::WRL::Make<HostObjectSample>( [appWindow = m_appWindow](std::function<void(void)> callback) { appWindow->RunAsync(callback); });
Die
Make
-Anweisung zeigt, wie dasHostObjectSample
COM-Objekt instanziiert wird, das in der IDL-Datei definiert wurde. Dies ist das Objekt, das wir später verwenden werden, wenn wir aufrufenAddHostObjectToScript
. DieMake
-Anweisung ruft uns einen Zeiger auf die Schnittstelle ab, die in HostObjectSampleImpl.cpp implementiert ist.Als Nächstes fügen wir einen Ereignishandler hinzu, um auf das
NavigationStarting
Ereignis zu lauschen:CHECK_FAILURE(m_webView->add_NavigationStarting( Microsoft::WRL::Callback<ICoreWebView2NavigationStartingEventHandler>( [this, sampleUri](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT { wil::unique_cotaskmem_string navigationTargetUri; CHECK_FAILURE(args->get_Uri(&navigationTargetUri)); std::wstring uriTarget(navigationTargetUri.get());
NavigationStarting
Im Ereignishandler wandelt diequery_to
Zeile (unten) das neu erstellte COM-Objekt in einenIDispatch
Typ um und konvertiert das Objekt dann in einVARIANT
.VARIANT
mit -Typen können Sie Datenstrukturen wie ganze Zahlen und Arrays sowie komplexere Typen wieIDispatch
verwenden.Eine vollständige Liste der unterstützten Datentypen finden Sie unter VARIANT-Struktur (oaidl.h). Nicht alle Typen in der
VARIANT
Union werden vonAddHostObjectToScript
unterstützt. Weitere Informationen finden Sie unter ICoreWebView2::AddHostObjectToScript-Methode.if (AreFileUrisEqual(sampleUri, uriTarget)) { VARIANT remoteObjectAsVariant = {}; m_hostObject.query_to<IDispatch>(&remoteObjectAsVariant.pdispVal); remoteObjectAsVariant.vt = VT_DISPATCH;
Da wir nun über eine Variante des Objekts verfügen, die C++-codefreundlich ist, ist der native Code der Beispiel-App bereit, um das Hostobjekt an den webseitigen Code der App zu übergeben.
In der unteren Zeile oben legt der
NavigationStarting
Ereignishandler dann den Variant-Typ des Remoteobjekts aufIDispatch
fest.// We can call AddHostObjectToScript multiple times in a row without // calling RemoveHostObject first. This will replace the previous object // with the new object. In our case this is the same object and everything // is fine. CHECK_FAILURE( m_webView->AddHostObjectToScript(L"sample", &remoteObjectAsVariant)); remoteObjectAsVariant.pdispVal->Release(); }
Oben wird im
NavigationStarting
-Ereignishandler anVARIANT
übergebenAddHostObjectToScript
, wobei der Namesample
verwendet wird.
Schritt 7: Zugreifen auf Hostobjektmember über Webseiten-JavaScript
In den obigen IDispatch
Schritten hat der native Code der Beispiel-App ein Hostobjekt erstellt, das implementiert. Dieser native Code ruft auch die WebView2-API ICoreWebView2::AddHostObjectToScript
oder ICoreWebView2Frame::AddHostObjectToScriptWithOrigins
auf und übergibt das Hostobjekt an den webseitigen Code der App.
Jetzt kann der webseitige Code der App auf die nativen APIs zugreifen, die vom Hostobjekt verfügbar gemacht werden. JavaScript-Anweisungen in Ihrem .html
Webseitenelement script
oder in einer JavaScript-Datei, auf die verwiesen wird .js
, können auf die exportierten nativen APIs zugreifen.
Der webseitige Code der Win32-Beispiel-App kann jetzt auf die Eigenschaften und Methoden des nativen Hostobjekts zugreifen, um auf die nativen APIs zuzugreifen. Wir verwenden die Webseitensteuerelemente der Beispiel-App auf der WebseiteSzenariohostobjekte> der App, um dies zu veranschaulichen.
Wählen Sie in Microsoft Visual Studio Datei>Alle speichern (STRG+UMSCHALT+S) aus, um das Projekt zu speichern.
Öffnen Sie im Projektmappen-Explorer WebView2APISample>ScenarioAddHostObject.html. Wir vergleichen diese Datei mit der entsprechenden Webseite in der ausgeführten Win32-Beispiel-App.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf WebView2APISample (die Win32-Beispiel-App), und wählen Sie dann Erstellen aus.
Drücken Sie F5 , um das Projekt im Debugmodus auszuführen.
Klicken Sie in der Win32-Beispiel-App (die über die Titelleiste von WebView2APISample verfügt) auf das Menü Szenario , und wählen Sie dann das Menüelement Hostobjekte aus. Die Webseite AddHostObjectToScript-Beispiel wird angezeigt, die durch definiert wird
ScenarioAddHostObject.html
:Die Webseite schlägt vor, das Konsolentool von DevTools zum Ausführen von JavaScript-Anweisungen für das
chrome.webview.hostObjects.sample
Objekt zu verwenden. Wenn Sie DevTools über die Beispiel-App öffnen möchten, klicken Sie mit der rechten Maustaste auf die Seite, und wählen Sie dann Untersuchen aus. Wählen Sie dann die Registerkarte Konsole aus. Weitere Informationen finden Sie unter Übersicht über die Konsole.Um DevTools zu öffnen, funktioniert das Drücken von F12 in diesem Kontext möglicherweise nicht und löst möglicherweise eine Ausnahme aus. Wenn ja, wählen Sie in Visual Studio Debuggen beenden aus, und drücken Sie dann F5 , um das Debuggen neu zu starten. Wählen Sie in der Beispiel-App erneutSzenariohostobjekte> aus. Weitere Informationen finden Sie unter Öffnen von DevTools mit einem anderen Ansatz als F12 unter Debuggen von WebView2-Apps mit Visual Studio.
Am unteren Rand der Demoseite host objects werden die Demoobjektmember in einem
<iframe>
dupliziert:Lesen Sie auf der gerenderten Demoseite in der Beispiel-App den Beschriftungstext, der die Schaltflächen "Datum " erläutert.
Klicken Sie auf die Schaltflächen Datum . Unter den Schaltflächen wird eine Datumszeichenfolge angezeigt, z. B.:
sample.dateProperty: Tue Nov 01 2022 12:45:25 GMT-0700 (Pacific Daylight Time)
Erkunden Sie Eigenschaften und Methoden, indem Sie auf die Schaltflächen auf der Demowebseite klicken und Werte eingeben, um zu sehen, wie sich der Beispielcode verhält. Die Schaltflächen veranschaulichen den Zugriff auf Eigenschaften und Methoden des Hostobjekts aus dem webseitigen Code der App.
Um Einen Einblick in die Vorgänge in JavaScript zu erhalten, untersuchen Sie den folgenden Code in ScenarioAddHostObject.html.
Der folgende Code ist eine Demoeigenschaft
Date
direkt imbody
-Element:<h2>Date Objects</h2> <button id="setDateButton">Set Date to Now</button> <label for="setDateButton">Sets <code>chrome.webview.hostObjects.options.shouldSerializeDates = true</code> and then runs <code>chrome.webview.hostObjects.sample.dateProperty = new Date()</code></label> <br /> <button id="createRemoteDateButton">Set Remote Date</button> <label for="createRemoteDateButton">Calls <code>chrome.webview.hostObjects.sample.createNativeDate()</code> to have the native object create and set the current time to the DateProperty</label> <code><pre><span id="dateOutput"></span></pre></code> <div id="div_iframe" style="display: none;"> <h2>IFrame</h2> </div>
Sie können auch den obigen Beschriftungstext auf der gerenderten Demoseite in der Beispiel-App lesen und den Code der Datumsschaltfläche erläutern.
Der folgende Code ist eine Demoeigenschaft
Date
, die in einemiframe
Element umschlossen ist, das in einemscript
-Element erstellt wird:// Date property document.getElementById("setDateButton").addEventListener("click", () => { chrome.webview.hostObjects.options.shouldSerializeDates = true; chrome.webview.hostObjects.sync.sample.dateProperty = new Date(); document.getElementById("dateOutput").textContent = "sample.dateProperty: " + chrome.webview.hostObjects.sync.sample.dateProperty; }); document.getElementById("createRemoteDateButton").addEventListener("click", () => { chrome.webview.hostObjects.sync.sample.createNativeDate(); document.getElementById("dateOutput").textContent = "sample.dateProperty: " + chrome.webview.hostObjects.sync.sample.dateProperty; });
Der Ausdruck
chrome.webview.hostObjects.sync.sample.dateProperty
ist derdateProperty
des nativen Hostobjekts.In der
.idl
zuvor beschriebenen Datei HostObjectSample.idl wird die date-Eigenschaft als Teil des Hostobjekts definiert.
Verwenden der Beispiel-App
Sie können mit der Verwendung und Änderung der Win32-Beispiel-App experimentieren. Folgen Sie dann demselben Muster in Ihrer eigenen App:
- Erstellen Sie ein Hostobjekt im nativen Code Ihrer App.
- Übergeben Sie das Hostobjekt an den webseitigen Code Ihrer App.
- Verwenden Sie das Hostobjekt aus dem webseitigen Code der App.
Informationen zu anderen APIs im Hostobjektökosystem finden Sie unter WebView2 Win32 C++ ICoreWebView2.
Übersicht über die API-Referenz
Weitere Informationen finden Sie unter Host-/Webobjektfreigabe in Übersicht über WebView2-Features und -APIs.
Siehe auch
- Web-/native Interop in Übersicht über WebView2-Features und -APIs.
- Verwenden von Frames in WebView2-Apps
- Aufrufen von systemeigenem WinRT-Code aus webseitigem Code
GitHub: