선택
[C#] 5. WebView2 양방향 통신 (AddHostObjectToScript, ExecuteScriptAsync) 본문
[C#] 5. WebView2 양방향 통신 (AddHostObjectToScript, ExecuteScriptAsync)
선 택 2022. 8. 2. 13:52
WebView2를 통해 다양한 기능을 수행할 수 있는데 그 중 AddHostObjectToScript, ExecuteScriptAsync 두가지는 유용하게 사용했고 앞으로도 잘 사용될 것이라고 생각한다.
하나씩 설명하자면 다음과 같다.
1. AddHostObjectToScript
AddHostObjectToScript는 WebView2를 사용해 호출한 사이트의 javascript를 이용해 C# 프로그램 상에 등록된 클래스의 API를 호출할 수 있는 기능이다.

쉽게 설명하자면 코드상에서 AddHostObjectToScript를 사용해 클래스를 등록한다면, WebView2에서 호출한 사이트는 등록한 클래스의 API를 호출할 수 있다. 이는 응용하면 HTML5에서 지원하지 않는 ActiveX 기능을 간접적으로 구현할 수 있게 된다. (이를 활용하려면 WebView2를 사용한 exe에서 url을 호출해야 하고, exe에 필요한 기능을 클래스 형태로 모두 구현한 다음 webview2와 매핑해야 한다)
어떻게 등록하고 사용할 수 있을까?
이는 간단하게 AddHostObjectToScript 함수를 통해 구현이 가능하다.
첫번째 인자값으로는 이름을, 두번째 인자값으로는 사용할 클래스를 적으면 된다.
testCls test = new testCls();
webView21.CoreWebView2.AddHostObjectToScript("testCls", test);
AddHostObjectToScript 기능을 사용하려면 먼저 EnsureCoreWebView2Async 함수를 통해 먼저 초기화를 진행해야 한다.
EnsureCoreWebView2Async를 먼저 호출해 CoreWebView2를 초기화시킨 다음에 AddHostObjectToScript를 실행해 등록하면 문제 없이 잘 된다.
그렇다면 어느 시점에 HostObject를 등록하면 될까?
그건 WebView2 컨트롤에서 지원하는 'CoreWebView2InitializationCompleted' 이벤트를 이용하면 되는데, 이벤트를 이용한 구현 코드는 아래와 같이 작성하면 되겠다.
namespace WebView2Sample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CoreWebView2CreationProperties webViewProperties = new CoreWebView2CreationProperties();
webViewProperties.BrowserExecutableFolder =
@"C:\Users\Home\Desktop\Example\WebView2Sample\Runtime\Microsoft.WebView2.FixedVersionRuntime.102.0.1245.41.x86";
webView21.CreationProperties = webViewProperties;
webView21.CoreWebView2InitializationCompleted += WebView21_CoreWebView2InitializationCompleted;
webView21.NavigationCompleted += WebView21_NavigationCompleted;
WebView21_Initialize();
}
private async void WebView21_Initialize()
{
//async로 corewebview2를 초기화할 수 있다. (1)
await webView21.EnsureCoreWebView2Async(null);
}
private void WebView21_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)
{
//(3) 사이트 접속 완료되면 이벤트 수행 (Source 주소창이 바뀔때 마다 호출)
Console.WriteLine("WebView21_NavigationCompleted");
}
private void WebView21_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
//(2) 초기화가 완료되면 이벤트가 수행 (한번만 수행됨)
Console.WriteLine("WebView21_CoreWebView2InitializationCompleted");
//이렇게 추가를 해두면 호출되는 웹페이지에서 C# 클래스에 등록된 API를 호출할 수 있다.
testCls test = new testCls();
webView21.CoreWebView2.AddHostObjectToScript("testCls", test);
}
private void button1_Click(object sender, EventArgs e)
{
webView21.Source = new Uri(textBox1.Text);
}
private void button2_Click(object sender, EventArgs e)
{
//버튼을 눌러 웹페이지의 스크립트를 실행시킬 수 있다.
string script = "";
Task.Run(() =>
{
webView21.ExecuteScriptAsync(script);
});
}
}
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class testCls
{
public void Alert(string message)
{
MessageBox.Show(message);
}
}
}
C#에서 testCls라는 클래스를 만들었고, 이를 HostObject에 붙이기까지 했다.
이제 호출할 웹 HTML의 코드를 수정해 작업을 할 차례다.
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction()">Click me</button>
<script>
function myFunction() {
chrome.webview.hostObjects.testCls.Alert('메시지 박스 출력');
}
</script>
</body>
</html>
HTML 페이지 하나를 만들어 버튼을 하나 만들고 이벤트를 만든다.
이벤트에서 API를 호출하면 되는데, 'chrome.webview.hostObjects'의 접두사까지는 항상 붙여야 한다.
그리고 뒤에 AddHostObjectToScript에 등록한 이름을 붙여 호출을 하면 된다.
상단 소스를 보면 testCls 클래스 안에는 Alert이라는 API가 있고, 파라메터가 string 형태이다.
Alert함수를 호출하고자 한다면 'chrome.webview.hostObjects.testCls.Alert('인자값 내용'); '을 javascript상에 적어주면 된다. 그리고 해당 HTML에서 호출을 하면 잘 실행이 됨을 볼 수 있다.

테스트를 위한 HTML 소스를 첨부한다.
위 소스를 복사 붙여넣기 하여, 지금 보고 있는 URL을 호출한 다음, 아래 Click me 버튼을 누르면 똑같이 메시지박스가 출력됨을 볼 수 있을 것이다.
API의 반환형이 void가 아니라, int/string의 경우에는 javascript에서 실행까지 한 다음 값도 가져올 수 있고
API를 비동기가 아닌 동기로 맞춰 순차적인 양방향 통신을 이루어 값을 셋팅하고 싶다고 한다면 hostObjects 뒤에 sync를 붙이면 된다. 이렇게 하면 Alert이 끝나기 전까지 javascript는 대기한다.
chrome.webview.hostObjects.sync.testCls.Alert('메시지 박스 출력');
속성 값과 변수들도 가지고 올 수 있는데, 이를 응용하면 데이터를 서로 주고 받고 할 수 있을 것이다.
2. ExecuteScriptAsync
AddHostObject 추가 후 Javascript에서 C#의 클래스 API를 호출할 수 있었는데, 반대로 C#에서 해당 URL에 자바스크립트를 역으로 호출할 수 있다.
AddHostObject와 다르게 간단하게 수행이 가능하다.
//버튼을 눌러 웹페이지의 스크립트를 실행시킬 수 있다.
string script = "javascript 코드 넣기..";
Task.Run(() =>
{
webView21.ExecuteScriptAsync(script);
});
이렇게 ExecuteScriptAsync 메서드를 이용해 스크립트 내용을 안에 적기만 하면 된다.
예를 들어 아래와 같은 HTML 코드가 있다고 한다면, Webview2 컨트롤에서 ExecuteScriptAsync("ClickMe();");를 호출하게 된다면 javascript가 실행이 된다.
<!DOCTYPE html>
<html>
<body>
<button onclick="ClickMe()">Click me!</button>
<script>
function ClickMe() {
alert('Clicked!');
}
</script>
</body>
</html>
C# 이벤트 코드
private void button2_Click(object sender, EventArgs e)
{
//버튼을 눌러 웹페이지의 스크립트를 실행시킬 수 있다.
string script = "ClickMe()";
Task.Run(() =>
{
webView21.ExecuteScriptAsync(script);
});
}
백문이 불여일견
샘플 코드를 복사해 똑같이 실행해 보자.

역시 잘 되는 것을 확인할 수 있다.
웹에서 호출을 할 때, 적절한 try - catch 구문과 HostObject, ExecuteScriptAsync를 사용한다면 웹 자원 뿐만이 아니라 프로그램 안에 내장되어 있는 C# 기능까지 모두 활용할 수 있어 더 많은 기능을 구현할 수 있을 것이다.
'프로그래밍 > C#, .NET' 카테고리의 다른 글
MFC SysTreeView32 컨트롤 내 node 텍스트 값 추출하기 (0) | 2023.11.06 |
---|---|
[C#] 4. WebView2 속성 설정으로 WebView 런타임 Fixed Version 사용 (0) | 2022.08.02 |
[C#] 3. WebView2를 이용해 사이트 호출 (0) | 2022.08.02 |
[C#] 2. WebView2 패키지 설치 (Nuget) (0) | 2022.08.02 |
[C#] 1. WebView2 구성 및 설치 (0) | 2022.08.02 |