■ 메인 크롬 브라우저 활성 탭에서 URL을 구하는 방법을 보여준다.
※ 비주얼 스튜디오에서 TestProject(Unpackaged) 모드로 빌드한다.
※ TestProject.csproj 프로젝트 파일에서 WindowsPackageType 태그를 None으로 추가했다.
▶ ChromeHelper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
using System; using System.Diagnostics; using System.Management; using System.Net.Http; using System.Threading.Tasks; using FlaUI.Core.AutomationElements; using FlaUI.UIA3; namespace TestProject; /// <summary> /// 크롬 헬퍼 /// </summary> public class ChromeHelper { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 메인 크롬 브라우저 활성 탭에서 URL 구하기 - GetURLFromMainChromeBrowserActiveTab() /// <summary> /// 메인 크롬 브라우저 활성 탭에서 URL 구하기 /// </summary> /// <returns></returns> public static async Task<string> GetURLFromMainChromeBrowserActiveTab() { string addressBarText = GetChromeAddressBarText(); if(addressBarText == null) { return null; } string protocol = await GetProtocol(addressBarText); return $"{protocol}://{addressBarText}"; } #endregion #region 크롬 주소바 텍스트 구하기 - GetChromeAddressBarText() /// <summary> /// 크롬 주소바 텍스트 구하기 /// </summary> /// <returns></returns> public static string GetChromeAddressBarText() { Process[] chromeProcessArray = Process.GetProcessesByName("chrome"); if(chromeProcessArray.Length == 0) { return null; } nint mainChromeWindowHandle = FindMainChromeWindowHandle(); if(mainChromeWindowHandle == IntPtr.Zero) { return null; } using(UIA3Automation uia3Automation = new UIA3Automation()) { AutomationElement windowAutomationElement = uia3Automation.FromHandle(mainChromeWindowHandle); AutomationElement addressEditAutomationElement = windowAutomationElement.FindFirstDescendant(conditionFactory => conditionFactory.ByClassName("OmniboxViewViews")); if(addressEditAutomationElement != null) { return addressEditAutomationElement.Patterns.Value.Pattern.Value; } else { return null; } } } #endregion //////////////////////////////////////////////////////////////////////////////// Private #region 메인 크롬 윈도우 핸들 찾기 - FindMainChromeWindowHandle() /// <summary> /// 메인 크롬 윈도우 핸들 찾기 /// </summary> /// <returns></returns> private static IntPtr FindMainChromeWindowHandle() { SelectQuery selectQuery = new SelectQuery("SELECT ProcessId, CommandLine FROM Win32_Process WHERE Name = 'chrome.exe'"); using(ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(selectQuery)) { foreach(ManagementObject process in managementObjectSearcher.Get()) { string commandLine = process["CommandLine"].ToString(); if(!commandLine.Contains("--type=")) { int processID = Convert.ToInt32(process["ProcessId"]); Process chromeProcess = Process.GetProcessById(processID); return chromeProcess.MainWindowHandle; } } } return IntPtr.Zero; } #endregion #region 보안 아이콘 구하기 - GetSecureIcon() /// <summary> /// 보안 아이콘 구하기 /// </summary> /// <returns>보안 아이콘</returns> private static string GetSecureIcon() { using(UIA3Automation uia3Automation = new UIA3Automation()) { nint mainWindowHandle = FindMainChromeWindowHandle(); AutomationElement windowAutomationElement = uia3Automation.FromHandle(mainWindowHandle); AutomationElement securityIconAutomationElement = windowAutomationElement.FindFirstDescendant(cf => cf.ByAutomationId("security-button")); if(securityIconAutomationElement != null) { string iconName = securityIconAutomationElement.Properties.Name.ToString(); if(iconName.Contains("보안") || iconName.Contains("Secure")) { return "secure"; } else if(iconName.Contains("비보안") || iconName.Contains("Not secure")) { return "insecure"; } } } return "unknown"; } #endregion #region HttpClient를 사용해 실제 프로토콜 구하기 - GetActualProtocalUsingHttpClient(url) /// <summary> /// HttpClient를 사용해 실제 프로토콜 구하기 /// </summary> /// <param name="url">URL</param> /// <returns>실제 프로토콜</returns> private static async Task<string> GetActualProtocalUsingHttpClient(string url) { try { using(HttpClient client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync($"https://{url}"); if(response.IsSuccessStatusCode) { return "https"; } } } catch { } try { using(HttpClient client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync($"http://{url}"); if(response.IsSuccessStatusCode) { return "http"; } } } catch { } return "unknown"; } #endregion #region 프로토콜 구하기 - GetProtocol(url) /// <summary> /// 프로토콜 구하기 /// </summary> /// <param name="url">URL</param> /// <returns>프로토콜</returns> private static async Task<string> GetProtocol(string url) { string secureIcon = GetSecureIcon(); if(secureIcon == "secure") { return "https"; } else if (secureIcon == "insecure") { return "http"; } return await GetActualProtocalUsingHttpClient(url); } #endregion } |
▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <Page x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" FontFamily="나눔고딕코딩" FontSize="16"> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="10"> <Button Name="fetchButton" HorizontalAlignment="Center" Padding="10" Content="가져오기" /> <TextBlock Name="textBlock" HorizontalAlignment="Center" /> </StackPanel> </Page> |
▶ MainPage.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; namespace TestProject; /// <summary> /// 메인 페이지 /// </summary> public sealed partial class MainPage : Page { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainPage() /// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent(); this.fetchButton.Click += fetchButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 가져오기 버튼 클릭시 처리하기 - fetchButton_Click(sender, e) /// <summary> /// 가져오기 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void fetchButton_Click(object sender, RoutedEventArgs e) { string url = await ChromeHelper.GetURLFromMainChromeBrowserActiveTab(); if(url != null) { this.textBlock.Text = url; } } #endregion } |