Code: Select all
SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", ~"--inprivate --disk-cache-dir=\"" + GetTemporaryDirectory() + "WebView2_Cache" + ~"\"")
OpenWindow(0, 0, 0, 1000, 600, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(1, 210, 4, 500, 24, "https://www.purebasic.com")
ButtonGadget(2, 710, 4, 50, 24, "Go")
WebGadget(3, 0, 30, 1000, 560, "https://whatismyipaddress.com", #PB_Web_Edge)
Repeat
e = WaitWindowEvent()
If e = #PB_Event_Gadget
Select EventGadget()
Case 2
SetGadgetText(3, Trim(GetGadgetText(1)))
EndSelect
EndIf
Until e = #PB_Event_CloseWindow
Below is an example using MS's Detours library.
The link below is static library files that have been compiled for your convenience.
https://www.dropbox.com/scl/fi/q8nppbah ... mhvex&dl=0
The WebView2Loader.dll file can be found in the path "\build\native\x64\" and "\build\native\x86\" when you download and unzip the nuget package below.
It's an optional file. The code will be run without it.
https://www.nuget.org/packages/Microsoft.Web.WebView2
Code: Select all
; https://github.com/webview/webview
;// The minimum WebView2 API version we need regardless of the SDK release
;// actually used. The number comes from the SDK release version,
;// e.g. 1.0.1150.38. To be safe the SDK should have a number that is greater
;// than or equal to this number. The Edge browser webview client must
;// have a number greater than or equal to this number.
EnableExplicit
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
#Lib_x86x64 = "86"
CompilerElse
#Lib_x86x64 = "64"
CompilerEndIf
Import "Detours.lib"
DetourTransactionBegin.l()
DetourTransactionCommit.l()
DetourUpdateThread.l(hThread)
DetourAttach.l(*ppPointer, pDetour)
DetourDetach.l(*ppPointer, pDetour)
EndImport
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2365.46
; STDAPI CreateCoreWebView2EnvironmentWithOptions(PCWSTR browserExecutableFolder, PCWSTR userDataFolder, ICoreWebView2EnvironmentOptions* environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* environmentCreatedHandler);
; STDAPI GetAvailableCoreWebView2BrowserVersionString(PCWSTR browserExecutableFolder, LPWSTR* versionInfo);
; STDAPI CompareBrowserVersions(PCWSTR version1, PCWSTR version2, int* result);
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2365.46#createcorewebview2environmentwithoptions
; CreateCoreWebView2EnvironmentWithOptions(PCWSTR browserExecutableFolder, PCWSTR userDataFolder, ICoreWebView2EnvironmentOptions * environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * environmentCreatedHandler)
Prototype.l CreateCoreWebView2EnvironmentWithOptions(*browserExecutableFolder, *userDataFolder, *environmentOptions, *createdEnvironmentCallback)
Global CreateCoreWebView2EnvironmentWithOptions__.CreateCoreWebView2EnvironmentWithOptions
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2365.46#createwebviewenvironmentwithoptionsinternal
; CreateWebViewEnvironmentWithOptionsInternal(bool checkRunningInstance, int runtimeType, PCWSTR userDataFolder, IUnknown * environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * webViewEnvironmentCreatedHandler)
Prototype.l CreateWebViewEnvironmentWithOptionsInternal(checkRunningInstance.l, runtimeType.l, *userDataFolder, *environmentOptions, *webViewEnvironmentCreatedHandler)
Global CreateWebViewEnvironmentWithOptionsInternal__.CreateWebViewEnvironmentWithOptionsInternal
Procedure.l My_CreateWebViewEnvironmentWithOptionsInternal(checkRunningInstance.l, runtimeType.l, *userDataFolder, *environmentOptions.ICoreWebView2EnvironmentOptions, *webViewEnvironmentCreatedHandler)
Protected lResult.l
; Read the value you set in the environment variable below.
Protected sUserDataFolder.s = GetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER")
Debug "----------------------------------------"
Debug #PB_Compiler_Procedure
If sUserDataFolder
; In this example, it is only used to show the "UserDataFolder", which is already specified.
If *userDataFolder
Debug "Previous UserDataFolder: " + PeekS(*userDataFolder)
EndIf
; Specify the new "UserDataFolder" that you obtained above.
*userDataFolder = @sUserDataFolder
Debug "Set new UserDataFolder: " + sUserDataFolder
EndIf
Debug "----------------------------------------"
; Call the original unhooked function.
lResult = CreateWebViewEnvironmentWithOptionsInternal__(checkRunningInstance, runtimeType, *userDataFolder, *environmentOptions, *webViewEnvironmentCreatedHandler)
ProcedureReturn lResult
EndProcedure
Procedure.l My_CreateCoreWebView2EnvironmentWithOptions(*browserExecutableFolder, *userDataFolder, *environmentOptions.ICoreWebView2EnvironmentOptions, *createdEnvironmentCallback)
Protected lResult.l
Protected sUserDataFolder.s = GetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER")
Debug "----------------------------------------"
Debug #PB_Compiler_Procedure
If sUserDataFolder
If *userDataFolder
Debug "Previous UserDataFolder: " + PeekS(*userDataFolder)
EndIf
*userDataFolder = @sUserDataFolder
Debug "Set new UserDataFolder: " + sUserDataFolder
EndIf
Debug "----------------------------------------"
lResult = CreateCoreWebView2EnvironmentWithOptions__(*browserExecutableFolder, *userDataFolder, *environmentOptions, *createdEnvironmentCallback)
ProcedureReturn lResult
EndProcedure
Procedure.s GetWebView2Path()
Protected sResult.s
Protected sSubkey.s = "SOFTWARE\Microsoft\EdgeUpdate\ClientState\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
Protected hkey, *m, lDataBytes.l
If RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, sSubkey, 0, #KEY_READ | #KEY_WOW64_32KEY, @hkey) = #ERROR_SUCCESS
If RegQueryValueEx_(hkey, "EBWebView", 0, 0, *m, @lDataBytes) = #ERROR_SUCCESS
If lDataBytes > 0
*m = AllocateMemory(lDataBytes)
If *m
If RegQueryValueEx_(hkey, "EBWebView", 0, 0, *m, @lDataBytes) = #ERROR_SUCCESS
sResult = PeekS(*m)
EndIf
FreeMemory(*m)
EndIf
EndIf
EndIf
RegCloseKey_(hkey)
EndIf
ProcedureReturn sResult
EndProcedure
Define Lib_WV2, sPath.s
; First, we look in the registry to see if WebView2 is installed on the system.
sPath = GetWebView2Path()
If sPath
; If the "WebView2Loader.dll" file exists in the application folder,
; the WebGadget is created using the CreateCoreWebView2EnvironmentWithOptions function inside the "WebView2Loader.dll" file,
; otherwise, the WebGadget is created using the CreateWebViewEnvironmentWithOptionsInternal function inside the "EmbeddedBrowserWebView.dll" file at the path obtained above.
; We'll intercept the call to one of the two functions used to create the WebGadget.
Lib_WV2 = OpenLibrary(#PB_Any, "WebView2Loader.dll")
If Lib_WV2
Debug "WebView2Loader.dll open."
CreateCoreWebView2EnvironmentWithOptions__ = GetFunction(Lib_WV2, "CreateCoreWebView2EnvironmentWithOptions")
Else
Lib_WV2 = OpenLibrary(#PB_Any, sPath + "\EBWebView\x" + #Lib_x86x64 + "\EmbeddedBrowserWebView.dll")
If Lib_WV2
Debug "EmbeddedBrowserWebView.dll open."
CreateWebViewEnvironmentWithOptionsInternal__ = GetFunction(Lib_WV2, "CreateWebViewEnvironmentWithOptionsInternal")
EndIf
EndIf
; Once you have the address of one of the two functions, try the hook.
If CreateCoreWebView2EnvironmentWithOptions__ Or CreateWebViewEnvironmentWithOptionsInternal__
; https://github.com/microsoft/Detours/wiki/DetourTransactionBegin
If DetourTransactionBegin() = #NO_ERROR
; https://github.com/microsoft/Detours/wiki/DetourUpdateThread
If DetourUpdateThread(GetCurrentThread_()) = #NO_ERROR
If CreateCoreWebView2EnvironmentWithOptions__
; https://github.com/microsoft/Detours/wiki/DetourAttach
; As a result of the function execution, the former variable stores the original function address before it was hooked.
If DetourAttach(@CreateCoreWebView2EnvironmentWithOptions__, @My_CreateCoreWebView2EnvironmentWithOptions()) <> #NO_ERROR
Debug "Error 0"
EndIf
EndIf
If CreateWebViewEnvironmentWithOptionsInternal__
If DetourAttach(@CreateWebViewEnvironmentWithOptionsInternal__, @My_CreateWebViewEnvironmentWithOptionsInternal()) <> #NO_ERROR
Debug "Error 1"
EndIf
EndIf
; https://github.com/microsoft/Detours/wiki/DetourTransactionCommit
DetourTransactionCommit()
EndIf
EndIf
Else
Debug "WebView2 function not found."
EndIf
Else
Debug "No WebView2 installed."
EndIf
; Unlike setting browser arguments, this one line alone won't work, so we need an API hook.
; Reflecting the path of the environment variable may be possible in a future PB update, but for now, it's not possible in 6.10 b9.
SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", GetTemporaryDirectory() + "WebView2_User")
SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", ~"--inprivate --disk-cache-dir=\"" + GetTemporaryDirectory() + "WebView2_Cache" + ~"\"")
OpenWindow(0, 0, 0, 1000, 600, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(1, 210, 4, 500, 24, "https://www.purebasic.com")
ButtonGadget(2, 710, 4, 50, 24, "Go")
WebGadget(3, 0, 30, 1000, 560, "https://whatismyipaddress.com", #PB_Web_Edge)
Define e
Repeat
e = WaitWindowEvent()
If e = #PB_Event_Gadget
Select EventGadget()
Case 2
SetGadgetText(3, Trim(GetGadgetText(1)))
EndSelect
EndIf
Until e = #PB_Event_CloseWindow
CloseLibrary(#PB_All)