LoginSignup
1
0

More than 1 year has passed since last update.

PowerShellにてNuGetで取得したWebView2を直接利用し、ExecuteScriptAsyncの実行結果を取得する

Last updated at Posted at 2022-08-20

Microsoft.Web.WebView2 パッケージの管理を自分でやりたくないため、NuGet によって取得したパッケージを参照してみました。
参照方法は非公式な方法ですが、動いてしまったのでサンプルとして公開してみます。

大半は使用しないファイルがあるため、プログラムと一緒に配布するのが正しそうです。
https://docs.microsoft.com/ja-jp/microsoft-edge/webview2/get-started/wpf

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.610
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.610
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

32 ビット版や ARM64 ビット版でも動きそうな雰囲気はありますが、こちらでは 64 ビット版でのみ確認済みです。

事前準備

下記のプログラムをインストールしてください。

また、NuGet パッケージ取得に ExecutionPolicy の変更が必要です。PowerShell にコピペする場合はこのプロセスだけでも許可してください。

If ((Get-ExecutionPolicy) -eq "Restricted"){
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
}

サンプル

PowerShell ウィンドウに 770 と値が書き込まれている画像
下記スクリプトを実行すると、上記のような画面が表示されます。
左上の"横幅取得"ボタンを押すと、PowerShell ウィンドウに 770 と値が書き込まれたことを確認できます。

重要な行は行頭に + を付けて強調表示しています。(本来の用途とは違いますが…)
このままでは実行できませんので、PowerShell で実行する前にテキストエディタで、+ を空の文字列に置換してください。

# 環境を確認し、
# -> Microsoft.Web.WebView2 が無ければ NuGet からパッケージを取得する
# -> Microsoft Edge WebView2 エバーグリーン ブートストラップ がインストールされていなければ例外をスローする
# -> Microsoft Edge がインストールされていなければ例外をスローする
Function Test-WebView2Runtime{
    Function Get-WebView2Assembly([Switch]$Retry){
        Try{
+            $SetDllDirectory = Add-Type -PassThru -Name "WindowsNtBaseApiClientDll" -MemberDefinition "[DllImport(""kernel32.dll"", SetLastError = true)]
+            public static extern bool SetDllDirectory(string lpPathName);"

            # DLL のパスを取得する
            $WebView2RuntimesPath = "$env:ProgramFiles\PackageManagement\NuGet\Packages\Microsoft.Web.WebView*\runtimes"
            If (Test-Path $WebView2RuntimesPath -PathType Container){
                Switch ((Get-WmiObject -Class Win32_ComputerSystem).SystemType.ToLower()){
                    ("x64-based pc"){
+                        $WebView2LoaderPath = (Get-Item "$WebView2RuntimesPath\win-x64\native\WebView2Loader.dll")[0]
                    }
                    ("x86-based pc"){
                        $WebView2LoaderPath = (Get-Item "$WebView2RuntimesPath\win-x86\native\WebView2Loader.dll")[0]
                    }
                    ("arm64-based pc"){
                        $WebView2LoaderPath = (Get-Item "$WebView2RuntimesPath\win-arm64\native\WebView2Loader.dll")[0]
                    }
                }
+                $MicrosoftWebWebView2WpfForDotnet45Path = (Get-Item "$env:ProgramFiles\PackageManagement\NuGet\Packages\Microsoft.Web.WebView*\lib\net45\Microsoft.Web.WebView2.Wpf.dll")[0]
+                $MicrosoftWebWebView2CoreForDotnet45Path = (Get-Item "$env:ProgramFiles\PackageManagement\NuGet\Packages\Microsoft.Web.WebView*\lib\net45\Microsoft.Web.WebView2.Core.dll")[0]
            }


            # DLL のパスが空であれば警告を表示する
            If (($WebView2LoaderPath -eq $Null) -or ($WebView2LoaderPath -eq $Null) -or ($WebView2LoaderPath -eq $Null)){
                Write-Warning "Get the Microsoft.Web.WebView2: Install-Package Microsoft.Web.WebView2"
            }

            # DLL を読み込む
+            $Path = (Split-Path $WebView2LoaderPath -Parent)
+            $SetDllDirectory::SetDllDirectory($Path) | Out-Null
+            [Reflection.Assembly]::LoadFile($MicrosoftWebWebView2WpfForDotnet45Path) | Out-Null
+            [Reflection.Assembly]::LoadFile($MicrosoftWebWebView2CoreForDotnet45Path) | Out-Null

            # XAML を読み込むために使用する
+            Add-Type -AssemblyName System.Windows.Forms,PresentationFramework,PresentationCore,WindowsBase,WindowsFormsIntegration,System.Xml.Linq | Out-Null
            # PowerShell では Await が実装できないので、代わりに VB.NET で定義しておく
+            Add-Type -Language VisualBasic -ReferencedAssemblies PresentationFramework,PresentationCore,WindowsBase,System.Xaml,$MicrosoftWebWebView2WpfForDotnet45Path,$MicrosoftWebWebView2CoreForDotnet45Path -TypeDefinition '
+            Public Class WebView2ExtendFunctions
+
+                Public Shared Async Sub ExecuteScript(WebView2 As Microsoft.Web.WebView2.Wpf.WebView2, JavaScript As String, Action As System.Action(Of String))
+                    Dim Value As String = Await WebView2.ExecuteScriptAsync(JavaScript)
+                    Action(Value)
+                End Sub
+
+            End Class
+            '
        }
        Catch{
            # 再試行のフラグがあれば例外としてスローする
            If ($Retry){
                Write-Error -Exception ([System.PlatformNotSupportedException]"Get the Microsoft.Web.WebView2: Install-Package Microsoft.Web.WebView2") -ErrorAction Stop
                Break
            }
            # NuGet から Microsoft.Web.WebView2 をインストールする
            [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
            Import-Module PackageManagement
            Install-PackageProvider -Name NuGet -Force | Out-Null
            Install-Module PowerShellGet -AllowClobber -Force | Out-Null
            If ((Get-PackageSource | Where Name -eq nuget.org) -eq $Null){
                Register-PackageSource -Name nuget.org -Location https://www.nuget.org/api/v2 -ProviderName NuGet -Trusted | Out-Null
            }
            Get-PackageSource -Name nuget.org | Set-PackageSource -Trusted | Out-Null
            Install-Package Microsoft.Web.WebView2 | Out-Null
            # 再試行する
            Return Get-WebView2Assembly -Retry
        }
    }
    $Value = $False
    Get-WebView2Assembly

    Try{
        $WebView2Version = [Microsoft.Web.WebView2.Core.CoreWebView2Environment]::GetAvailableBrowserVersionString()
    }
    Catch{
        # GetAvailableBrowserVersionString が実行できなければ、Microsoft Edge WebView2 エバーグリーン ブートストラップ がインストールされていないと判定する
        Write-Error -Exception ([System.PlatformNotSupportedException]"Get the WebView2 Runtime Evergreen Bootstrapper: https://developer.microsoft.com/microsoft-edge/webview2/") -ErrorAction Stop
    }
    Try{
        $WebView2Version = [Version]$WebView2Version
        # 関数の判定として、バージョンが 0.0.0.0 以上か判定する
        $Value = $WebView2Version -gt [Version]"0.0.0.0"
    }
    Catch{
        # GetAvailableBrowserVersionString から取得した値が Version 型でない場合は、Microsoft Edge がインストールされていないと判定する
        Write-Error -Exception ([System.PlatformNotSupportedException]"Get the Microsoft Edge: https://www.microsoft.com/edge#evergreen") -ErrorAction Stop
    }

    Return $Value
}


If (-not (Test-WebView2Runtime)){
    # Microsoft Edge が 0.0.0.0 以下の場合
    Break
}

# ウィンドウの定義
+$XamlDocument = [System.Xml.Linq.XDocument]::Parse('<Window
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:Wpf="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
+        Title="WebView2 テスト" Height="450" Width="800">
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="*"/>
+        </Grid.RowDefinitions>
+        <StackPanel Grid.Row="0" Orientation="Horizontal">
+            <Button x:Name="GetClientWidthButton" Content="横幅取得" />
+        </StackPanel>
+        <Wpf:WebView2 x:Name="WebView2" Source="https://www.google.co.jp" Grid.Row="1"/>
+    </Grid>
+</Window>')
+$MainWindow = [Windows.Markup.XamlReader]::Load($XamlDocument.CreateReader())

# WebView2 の初期化
+$MainWindow.FindName("WebView2").CreationProperties = New-Object Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties
+$MainWindow.FindName("WebView2").CreationProperties.UserDataFolder = "$env:LocalAppData\YOUR APP NAME"

# 横幅取得ボタンを押したときに、コンソールに値を書きこむ
+$MainWindow.FindName("GetClientWidthButton").Add_Click({
+[WebView2ExtendFunctions]::ExecuteScript($MainWindow.FindName("WebView2"), "document.body.clientWidth", +[Action[String]]{param ($Value) Write-Host $Value})
+})

# ウィンドウの表示
+$MainWindow.ShowDialog()

クリーンアップ

WebView2 の UserData フォルダーを指定しています。

%LocalAppData%\YOUR APP NAME

実行後は不要となりますので削除してください。

簡単な解説

余分な行が多いため、強調表示された行・コメント等を見ながら照らし合わせてください。

  1. SetDllDirectory で WebView2Loader.dll があるディレクトリーを設定する
  2. .NET Framework 4.5 向けの Microsoft.Web.WebView2.Core.dll と Microsoft.Web.WebView2.Wpf.dll を参照
  3. XAML の読み込みに使用している System.Windows.Forms,PresentationFramework,PresentationCore,WindowsBase,WindowsFormsIntegration,System.Xml.Linq を参照
  4. ExecuteScriptAsync を Await している関数を定義
  5. XAML の定義
  6. WebView2 の実行に必要な CreationProperties を定義
  7. ボタンを押したときのイベントハンドラーを登録
  8. ウィンドウを表示
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0