2018/4/11

UWP - 調整 WebView 的 UserAgent

想要在 UWP 調整 WebView 的 User-Agent 記得先把 App 的 mini SDK version 升級到在 Windows 10 (15063),來看一下是怎麽做的吧。

我參考 Set the UserAgent for a UWP WebView 的介紹,得知可以從 Win32 API 的 urlmon.dll 做到這個效果。如下程式碼:
const int URLMON_OPTION_USERAGENT = 0x10000001;

[DllImport("urlmon.dll", CharSet = CharSet.Ansi)]
private static extern int UrlMkSetSessionOption(int dwOption, string pBuffer, int dwBufferLength, int dwReserved);

[DllImport("urlmon.dll", CharSet = CharSet.Ansi)]
private static extern int UrlMkGetSessionOption(int dwOption, StringBuilder pBuffer, int dwBufferLength, ref int pdwBufferLength, int dwReserved);
因此,我就好奇 urlmon.dll 還可以做到那些用途,是否還有其他 Win32 API 可以使用。

根據 APIs from urlmon.dll 的説明提到:
APIRequirements
CreateUriIntroduced into urlmon.dll in 10.0.10240. Moved into ext-ms-win-core-iuri-l1-1-0.dll in 10.0.15063.
CreateUriWithFragmentIntroduced into urlmon.dll in 10.0.10240. Moved into ext-ms-win-core-iuri-l1-1-0.dll in 10.0.15063.
UrlMkGetSessionOptionIntroduced into urlmon.dll in 10.0.15063.
UrlMkSetSessionOptionIntroduced into urlmon.dll in 10.0.15063.

需要 15063 以上才有支援,而 UrlMkSetSessionOption 調整 UserAgent 的參數值為 0x10000001,參考如下:
FlagValueDescription
URLMON_OPTION_USERAGENT0x10000001Sets the user agent string for this process.
URLMON_OPTION_USERAGENT_REFRESH0x10000002Refreshes the user agent string from the registry for this process.

需注意,利用 UrlMkSetSessionOption 的 (0x10000001) 更新 UserAgent 之後,在 App 執行期間是用的 WebView 都是使用修改後的值。
利用下面的程式片段可設定與取得目前的 UserAgent:
public static class UserAgent
{
    const int URLMON_OPTION_USERAGENT = 0x10000001;

    [DllImport("urlmon.dll", CharSet = CharSet.Ansi)]
    private static extern int UrlMkSetSessionOption(int dwOption, string pBuffer, int dwBufferLength, int dwReserved);

    [DllImport("urlmon.dll", CharSet = CharSet.Ansi)]
    private static extern int UrlMkGetSessionOption(int dwOption, StringBuilder pBuffer, int dwBufferLength, ref int pdwBufferLength, int dwReserved);

    public static string GetUserAgent()
    {
        // 設定讀取的長度 255 bytes ,因爲是 0x (16 進位數)
        int bufferLength = 255;
        StringBuilder buffer = new StringBuilder(bufferLength);
        int length = 0;
        UrlMkGetSessionOption(URLMON_OPTION_USERAGENT, buffer, bufferLength, ref length, 0);
        return buffer.ToString();
    }

    public static void SetUserAgent(string agent)
    {
        // S_OK, E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL
        var hr = UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, agent, agent.Length, 0);
  
        // 轉換得到的值看是否為 Exception
        var ex = Marshal.GetExceptionForHR(hr);
  
        if(ex!= null)
        {
            throw ex;
        }
    }

    public static void AppendUserAgent(string appendContent)
    {
        SetUserAgent(GetUserAgent() + appendContent);
    }
}
另外有看過這篇 Setting a custom User-Agent in the UWP WebView control 的介紹,還可以使用 WebView.NavigateWithHttpRequestMessage 時,另外建立一個 HttpRequestMessage 調整送出的 UserAgent,但是非常複雜。
======
如果您是使用 HttpClient 要調整 UserAgent 是很容易的,但是 WebView 是 UWP 包裝好的要調整就比較麻煩。
因此整理上面的介紹與使用方式,希望有幫助到大家。

References:

沒有留言:

張貼留言