From 0f3d985b82283535084b584dbd6c7ff37609681c Mon Sep 17 00:00:00 2001 From: chiDT Date: Tue, 12 Aug 2025 19:36:53 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20SearchModel=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EB=B9=84=EB=8F=99=EA=B8=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChromeDriverManager.cs 제거하여 코드 중복 제거 - ILibrarySearcher 인터페이스의 StartDriver 메서드를 async로 변경 - KwangjuCityLibrarySearcher 및 NamguLibrarySearcher에 ChromeDriverHelper 적용 - 드라이버 생성 로직을 통합하여 일관성 있는 구조로 개선 - Check_copyWD.cs 및 DLS_Copy.cs에서 비동기 검색 처리 개선 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- unimarc/.claude/settings.local.json | 5 +- .../SearchModel/ChromeDriverManager.cs | 740 ------------------ .../unimarc/SearchModel/ILibrarySearcher.cs | 2 +- .../SearchModel/KwangjuCityLibrarySearcher.cs | 56 +- .../SearchModel/NamguLibrarySearcher.cs | 60 +- unimarc/unimarc/UniMarc.csproj | 1 - unimarc/unimarc/마크/Check_copyWD.cs | 111 +-- unimarc/unimarc/마크/DLS_Copy.cs | 88 +-- 8 files changed, 126 insertions(+), 937 deletions(-) delete mode 100644 unimarc/unimarc/SearchModel/ChromeDriverManager.cs diff --git a/unimarc/.claude/settings.local.json b/unimarc/.claude/settings.local.json index a97f767..baba76c 100644 --- a/unimarc/.claude/settings.local.json +++ b/unimarc/.claude/settings.local.json @@ -18,8 +18,9 @@ }, "permissions": { "allow": [ - "WebFetch(domain:lib.namgu.gwangju.kr)" + "Bash(git add:*)" ], - "deny": [] + "deny": [], + "ask": [] } } \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/ChromeDriverManager.cs b/unimarc/unimarc/SearchModel/ChromeDriverManager.cs deleted file mode 100644 index caacefd..0000000 --- a/unimarc/unimarc/SearchModel/ChromeDriverManager.cs +++ /dev/null @@ -1,740 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; -using WebDriverManager; -using WebDriverManager.DriverConfigs.Impl; -using System.Reflection; -using System.Net.Http; -using System.Threading; -using System.IO.Compression; -using System.Linq; -using System.Security.Principal; -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace BokBonCheck -{ - public static class ChromeDriverManager - { - private static string _driverPath = null; - private static readonly object _lockObject = new object(); - private static readonly int MaxRetryCount = 3; - private static readonly int RetryDelayMs = 2000; - private static readonly string UserDataDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ChromeDriverUserData"); - - public static async Task SetupChromeDriverAsync(DownloadProgressForm progressForm = null) - { - lock (_lockObject) - { - if (!string.IsNullOrEmpty(_driverPath) && File.Exists(_driverPath)) - { - // 이미 설정된 드라이버가 있고 정상 동작하면 재사용 - if (IsDriverReady()) - { - if (progressForm != null) - { - progressForm.UpdateProgress(100, "기존 드라이버 사용"); - progressForm.SetCompleted("기존 드라이버를 사용합니다."); - } - return _driverPath; - } - } - } - - try - { - // Chrome 설치 여부 확인 - if (!IsChromeInstalled()) - { - var errorMsg = "Chrome이 설치되어 있지 않습니다. Chrome을 설치한 후 다시 시도해주세요."; - Console.WriteLine(errorMsg); - if (progressForm != null) - { - progressForm.SetError(errorMsg); - } - throw new InvalidOperationException(errorMsg); - } - - // 사용자 데이터 디렉토리 생성 - EnsureUserDataDirectory(); - - // 사용자 디렉토리 생성 후 기존 Chrome/ChromeDriver 프로세스 정리 - CleanupChromeProcesses(); - - // Chrome 버전 확인 - var chromeVersion = GetChromeVersion(); - Console.WriteLine($"설치된 Chrome 버전: {chromeVersion}"); - - if (progressForm != null) - { - progressForm.UpdateProgress(10, $"Chrome 버전 확인 중... ({chromeVersion})"); - } - - // 기존 드라이버 경로 확인 - var existingDriverPath = GetExistingDriverPath(); - if (!string.IsNullOrEmpty(existingDriverPath) && File.Exists(existingDriverPath)) - { - Console.WriteLine($"기존 드라이버 발견: {existingDriverPath}"); - - if (progressForm != null) - { - progressForm.UpdateProgress(20, "기존 드라이버 테스트 중..."); - } - - // 기존 드라이버 테스트 (한 번만) - if (await TestExistingDriver(existingDriverPath)) - { - if (progressForm != null) - { - progressForm.UpdateProgress(100, "기존 드라이버 사용"); - progressForm.SetCompleted("기존 드라이버를 사용합니다."); - } - - lock (_lockObject) - { - _driverPath = existingDriverPath; - Environment.SetEnvironmentVariable("webdriver.chrome.driver", existingDriverPath); - } - return existingDriverPath; - } - else - { - Console.WriteLine("기존 드라이버 테스트 실패 - 새로 다운로드"); - // 기존 드라이버 삭제 - try - { - File.Delete(existingDriverPath); - Console.WriteLine("기존 드라이버 삭제됨"); - } - catch (Exception ex) - { - Console.WriteLine($"기존 드라이버 삭제 실패: {ex.Message}"); - } - } - } - - // 드라이버 다운로드 - if (progressForm != null) - { - progressForm.UpdateProgress(30, "Chrome 드라이버 다운로드 중..."); - } - var driverPath = await DownloadChromeDriverWithRetryAsync(progressForm); - - // 다운로드된 드라이버 테스트 (한 번만) - if (progressForm != null) - { - progressForm.UpdateProgress(80, "다운로드된 드라이버 테스트 중..."); - } - - if (await TestExistingDriver(driverPath)) - { - lock (_lockObject) - { - _driverPath = driverPath; - Environment.SetEnvironmentVariable("webdriver.chrome.driver", driverPath); - } - - if (progressForm != null) - { - progressForm.UpdateProgress(100, "드라이버 설정 완료"); - progressForm.SetCompleted("드라이버 설정 완료!"); - } - - Console.WriteLine($"ChromeDriver 경로: {driverPath}"); - Console.WriteLine($"환경 변수 설정: webdriver.chrome.driver = {driverPath}"); - - return driverPath; - } - else - { - throw new InvalidOperationException("다운로드된 드라이버 테스트에 실패했습니다."); - } - } - catch (Exception ex) - { - var errorMsg = $"ChromeDriver 설정 오류: {ex.Message}"; - Console.WriteLine(errorMsg); - if (progressForm != null) - { - progressForm.SetError(errorMsg); - } - throw; - } - } - - private static void EnsureUserDataDirectory() - { - try - { - if (!Directory.Exists(UserDataDir)) - { - Directory.CreateDirectory(UserDataDir); - Console.WriteLine($"사용자 데이터 디렉토리 생성: {UserDataDir}"); - } - - // 임시 파일 디렉토리도 생성 - var tempDir = Path.Combine(UserDataDir, "temp"); - if (!Directory.Exists(tempDir)) - { - Directory.CreateDirectory(tempDir); - } - - // 로그 디렉토리 생성 - var logDir = Path.Combine(UserDataDir, "logs"); - if (!Directory.Exists(logDir)) - { - Directory.CreateDirectory(logDir); - } - } - catch (Exception ex) - { - Console.WriteLine($"사용자 데이터 디렉토리 생성 실패: {ex.Message}"); - } - } - - private static async Task DownloadChromeDriverWithRetryAsync(DownloadProgressForm progressForm) - { - Exception lastException = null; - - for (int attempt = 1; attempt <= MaxRetryCount; attempt++) - { - try - { - if (progressForm != null) - { - progressForm.UpdateProgress(30 + (attempt - 1) * 10, - $"Chrome 드라이버 다운로드 중... (시도 {attempt}/{MaxRetryCount})"); - } - - Console.WriteLine($"드라이버 다운로드 시도 {attempt}/{MaxRetryCount}"); - - // WebDriverManager를 사용하여 설치된 Chrome 버전에 맞는 드라이버 다운로드 - var driverManager = new DriverManager(); - var driverPath = driverManager.SetUpDriver(new ChromeConfig(), "MatchingBrowser"); - - if (!string.IsNullOrEmpty(driverPath) && File.Exists(driverPath)) - { - Console.WriteLine($"드라이버 다운로드 성공: {driverPath}"); - return driverPath; - } - else - { - throw new InvalidOperationException("드라이버 파일을 찾을 수 없습니다."); - } - } - catch (Exception ex) - { - lastException = ex; - Console.WriteLine($"드라이버 다운로드 시도 {attempt} 실패: {ex.Message}"); - - if (attempt < MaxRetryCount) - { - if (progressForm != null) - { - progressForm.UpdateProgress(30 + attempt * 10, - $"다운로드 실패. 재시도 중... ({attempt + 1}/{MaxRetryCount})"); - } - - // 재시도 전 잠시 대기 - await Task.Delay(RetryDelayMs); - } - } - } - - throw new InvalidOperationException($"드라이버 다운로드를 {MaxRetryCount}번 시도했지만 실패했습니다. 마지막 오류: {lastException?.Message}"); - } - - private static string GetExistingDriverPath() - { - try - { - // 환경 변수에서 확인 - var envPath = Environment.GetEnvironmentVariable("webdriver.chrome.driver"); - if (!string.IsNullOrEmpty(envPath) && File.Exists(envPath)) - { - return envPath; - } - - // 사용자 디렉토리에서 확인 (관리자 권한 없이도 접근 가능) - var userDriverPath = Path.Combine(UserDataDir, "chromedriver.exe"); - if (File.Exists(userDriverPath)) - { - return userDriverPath; - } - - // WebDriverManager 캐시 폴더에서 확인 - var cachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - ".cache", "selenium"); - if (Directory.Exists(cachePath)) - { - var chromeDriverFiles = Directory.GetFiles(cachePath, "chromedriver*", SearchOption.AllDirectories) - .Where(f => f.EndsWith(".exe") || !Path.HasExtension(f)) - .OrderByDescending(f => File.GetLastWriteTime(f)) - .ToArray(); - - if (chromeDriverFiles.Length > 0) - { - return chromeDriverFiles[0]; // 가장 최근 파일 반환 - } - } - - // 현재 실행 파일과 같은 디렉토리에서 확인 - var currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - if (!string.IsNullOrEmpty(currentDir)) - { - var localDriverPath = Path.Combine(currentDir, "chromedriver.exe"); - if (File.Exists(localDriverPath)) - { - return localDriverPath; - } - } - - return null; - } - catch (Exception ex) - { - Console.WriteLine($"기존 드라이버 경로 확인 실패: {ex.Message}"); - return null; - } - } - - public static string GetDriverPath() - { - return _driverPath; - } - - private static string GetChromeVersion() - { - try - { - // Windows에서 Chrome 설치 경로 확인 - var chromePaths = new[] - { - @"C:\Program Files\Google\Chrome\Application\chrome.exe", - @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - @"Google\Chrome\Application\chrome.exe"), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), - @"Google\Chrome\Application\chrome.exe"), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), - @"Google\Chrome\Application\chrome.exe") - }; - - foreach (var path in chromePaths) - { - if (File.Exists(path)) - { - var versionInfo = FileVersionInfo.GetVersionInfo(path); - var version = versionInfo.FileVersion; - Console.WriteLine($"Chrome 버전 감지: {version} (경로: {path})"); - return version; - } - } - - // 레지스트리에서 확인 (추가 방법) - try - { - using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Google\Chrome\BLBeacon")) - { - if (key != null) - { - var version = key.GetValue("version") as string; - if (!string.IsNullOrEmpty(version)) - { - Console.WriteLine($"레지스트리에서 Chrome 버전 감지: {version}"); - return version; - } - } - } - } - catch (Exception ex) - { - Console.WriteLine($"레지스트리 확인 실패: {ex.Message}"); - } - - return "알 수 없음"; - } - catch (Exception ex) - { - Console.WriteLine($"Chrome 버전 감지 실패: {ex.Message}"); - return "확인 실패"; - } - } - - public static bool IsChromeInstalled() - { - try - { - var chromePaths = new[] - { - @"C:\Program Files\Google\Chrome\Application\chrome.exe", - @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - @"Google\Chrome\Application\chrome.exe"), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), - @"Google\Chrome\Application\chrome.exe"), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), - @"Google\Chrome\Application\chrome.exe") - }; - - foreach (var path in chromePaths) - { - if (File.Exists(path)) - { - return true; - } - } - - // 레지스트리에서도 확인 - try - { - using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Google\Chrome\BLBeacon")) - { - if (key != null) - { - return true; - } - } - } - catch - { - // 레지스트리 접근 실패는 무시 - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine($"Chrome 설치 확인 실패: {ex.Message}"); - return false; - } - } - - public static async Task TestChromeDriverAsync(DownloadProgressForm progressForm = null) - { - try - { - var driverPath = await SetupChromeDriverAsync(progressForm); - - if (progressForm != null) - { - progressForm.UpdateProgress(50, "드라이버 테스트 중..."); - } - - return await TestExistingDriver(driverPath); - } - catch (Exception ex) - { - Console.WriteLine($"ChromeDriver 테스트 실패: {ex.Message}"); - if (progressForm != null) - { - progressForm.SetError($"테스트 실패: {ex.Message}"); - } - return false; - } - } - - public static void ClearDriverCache() - { - try - { - Console.WriteLine("Chrome 드라이버 캐시 정리 시작..."); - - // 사용자 데이터 디렉토리 정리 - if (Directory.Exists(UserDataDir)) - { - try - { - Directory.Delete(UserDataDir, true); - Console.WriteLine($"사용자 데이터 디렉토리 정리됨: {UserDataDir}"); - } - catch (Exception ex) - { - Console.WriteLine($"사용자 데이터 디렉토리 정리 실패: {ex.Message}"); - } - } - - // WebDriverManager 캐시 폴더 정리 - var cachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - ".cache", "selenium"); - if (Directory.Exists(cachePath)) - { - Directory.Delete(cachePath, true); - Console.WriteLine($"WebDriverManager 캐시 정리됨: {cachePath}"); - } - - // 환경 변수에서 설정된 드라이버 경로도 정리 - var envDriverPath = Environment.GetEnvironmentVariable("webdriver.chrome.driver"); - if (!string.IsNullOrEmpty(envDriverPath) && File.Exists(envDriverPath)) - { - try - { - File.Delete(envDriverPath); - Console.WriteLine($"환경 변수 드라이버 삭제됨: {envDriverPath}"); - } - catch (Exception ex) - { - Console.WriteLine($"환경 변수 드라이버 삭제 실패: {ex.Message}"); - } - } - - // 저장된 드라이버 경로도 정리 - lock (_lockObject) - { - if (!string.IsNullOrEmpty(_driverPath) && File.Exists(_driverPath)) - { - try - { - File.Delete(_driverPath); - Console.WriteLine($"저장된 드라이버 삭제됨: {_driverPath}"); - } - catch (Exception ex) - { - Console.WriteLine($"저장된 드라이버 삭제 실패: {ex.Message}"); - } - } - _driverPath = null; - } - - Environment.SetEnvironmentVariable("webdriver.chrome.driver", null); - - Console.WriteLine("Chrome 드라이버 캐시 정리 완료"); - } - catch (Exception ex) - { - Console.WriteLine($"캐시 정리 실패: {ex.Message}"); - } - } - - public static bool IsDriverReady() - { - try - { - var driverPath = GetExistingDriverPath(); - if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath)) - { - Console.WriteLine("기존 드라이버가 없습니다."); - return false; - } - - Console.WriteLine($"드라이버 준비 상태 확인: {driverPath}"); - - // 파일 크기와 수정 날짜로 기본 검증 - var fileInfo = new FileInfo(driverPath); - if (fileInfo.Length < 1000) // 1KB 미만이면 의심스러움 - { - Console.WriteLine("드라이버 파일이 너무 작습니다."); - return false; - } - - // 최근 30일 내 파일인지 확인 - if (fileInfo.LastWriteTime < DateTime.Now.AddDays(-30)) - { - Console.WriteLine("드라이버 파일이 너무 오래되었습니다."); - return false; - } - - Console.WriteLine("드라이버 준비 상태: 준비됨"); - return true; - } - catch (Exception ex) - { - Console.WriteLine($"드라이버 준비 상태 확인 실패: {ex.Message}"); - return false; - } - } - - /// - /// 기본 Chrome 옵션을 생성하는 헬퍼 메서드 - /// - public static ChromeOptions CreateBaseChromeOptions(bool hideBrowser = true,int width = 800,int height = 600) - { - var options = new ChromeOptions(); - - if (hideBrowser) - { - options.AddArgument("--headless"); - } - - if(width > 0 && height > 0) - { - options.AddArgument($"--window-size={width},{height}"); - } - - // 기본 안정성 옵션 - options.AddArgument("--no-sandbox"); - options.AddArgument("--disable-dev-shm-usage"); - options.AddArgument("--remote-debugging-port=0"); - - return options; - } - - - /// - /// 검색 최적화된 Chrome 옵션을 반환합니다 - /// - public static ChromeOptions GetSearchOptimizedOptions() - { - var options = CreateBaseChromeOptions(true); - - // 검색에 필요한 기능만 활성화 - options.AddArgument("--enable-javascript"); - options.AddArgument("--enable-images"); - - return options; - } - - private static async Task TestExistingDriver(string driverPath) - { - try - { - Console.WriteLine($"드라이버 테스트: {driverPath}"); - - // ChromeDriver 서비스 설정 - var service = OpenQA.Selenium.Chrome.ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath)); - service.HideCommandPromptWindow = true; - - // 기본 Chrome 옵션 사용하고 테스트용 추가 옵션 설정 - var options = CreateBaseChromeOptions(true); - - // 테스트용 추가 옵션들 - options.AddArgument("--log-level=3"); // 오류만 표시 - options.AddArgument("--silent"); - //options.AddArgument("--window-size=1920,1080"); - //options.AddArgument("--start-maximized"); - options.AddArgument("--disable-blink-features=AutomationControlled"); - options.AddArgument("--enable-aggressive-domstorage-flushing"); - - //var options2 = new ChromeOptions(); - //options2.BinaryLocation = (driverPath); - //options2.AddArgument("--disable-web-security"); - //options2.AddArgument("--allow-running-insecure-content"); - //options2.AddArgument("--no-sandbox"); - //options2.AddArgument("--disable-dev-shm-usage"); - //options2.AddArgument("--remote-debugging-port=9222"); - - using (var driver = new OpenQA.Selenium.Chrome.ChromeDriver(service, options)) - { - driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(15); - driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10); - - driver.Navigate().GoToUrl("https://www.google.com"); - var title = driver.Title; - Console.WriteLine($"드라이버 테스트 성공: {title}"); - return !string.IsNullOrEmpty(title); - } - } - catch (Exception ex) - { - Console.WriteLine($"드라이버 테스트 실패: {ex.Message}"); - - // DevToolsActivePort 및 Chrome 크래시 관련 특별 처리 - if (ex.Message.Contains("DevToolsActivePort file doesn't exist") || - ex.Message.Contains("was killed") || - ex.Message.Contains("Chrome has crashed")) - { - Console.WriteLine("DevToolsActivePort 또는 Chrome 크래시 감지됨. 사용자 데이터 디렉토리 정리 시도..."); - try - { - // 사용자 데이터 디렉토리 정리 - if (Directory.Exists(UserDataDir)) - { - Directory.Delete(UserDataDir, true); - Console.WriteLine("사용자 데이터 디렉토리 정리 완료"); - } - - // Chrome 프로세스 정리 시도 - CleanupChromeProcesses(); - - // 잠시 대기 - await Task.Delay(1000); - } - catch (Exception cleanupEx) - { - Console.WriteLine($"사용자 데이터 디렉토리 정리 실패: {cleanupEx.Message}"); - } - } - - return false; - } - } - - // Chrome 프로세스 정리 메서드 추가 - private static void CleanupChromeProcesses() - { - try - { - Console.WriteLine("Chrome 프로세스 정리 시작..."); - - // Chrome 관련 프로세스들 찾기 - var chromeProcesses = System.Diagnostics.Process.GetProcessesByName("chrome"); - var chromedriverProcesses = System.Diagnostics.Process.GetProcessesByName("chromedriver"); - - // Chrome 프로세스 정리 - bool KILLPROC = false; - foreach (var process in chromeProcesses) - { - try - { - if (!process.HasExited) - { - KILLPROC = true; - process.Kill(); - Console.WriteLine($"Chrome 프로세스 종료: PID {process.Id}"); - } - } - catch (Exception ex) - { - Console.WriteLine($"Chrome 프로세스 종료 실패 (PID {process.Id}): {ex.Message}"); - } - } - - // ChromeDriver 프로세스 정리 - foreach (var process in chromedriverProcesses) - { - try - { - if (!process.HasExited) - { - KILLPROC = true; - process.Kill(); - Console.WriteLine($"ChromeDriver 프로세스 종료: PID {process.Id}"); - } - } - catch (Exception ex) - { - Console.WriteLine($"ChromeDriver 프로세스 종료 실패 (PID {process.Id}): {ex.Message}"); - } - } - - // 잠시 대기하여 프로세스 완전 종료 확인 - if(KILLPROC) - System.Threading.Thread.Sleep(2000); - - Console.WriteLine("Chrome 프로세스 정리 완료"); - } - catch (Exception ex) - { - Console.WriteLine($"Chrome 프로세스 정리 실패: {ex.Message}"); - } - } - - public static void Dispose() - { - try - { - lock (_lockObject) - { - _driverPath = null; - } - Environment.SetEnvironmentVariable("webdriver.chrome.driver", null); - Console.WriteLine("ChromeDriverManager 리소스 해제 완료"); - } - catch (Exception ex) - { - Console.WriteLine($"ChromeDriverManager 리소스 해제 실패: {ex.Message}"); - } - } - } -} \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/ILibrarySearcher.cs b/unimarc/unimarc/SearchModel/ILibrarySearcher.cs index cecec1f..caf98a8 100644 --- a/unimarc/unimarc/SearchModel/ILibrarySearcher.cs +++ b/unimarc/unimarc/SearchModel/ILibrarySearcher.cs @@ -15,7 +15,7 @@ namespace BokBonCheck string SiteName { get; } string SiteUrl { get; } Task SearchAsync(string searchTerm); - void StartDriver(bool showBrowser); + Task StartDriver(bool showBrowser); void StopDriver(); Task WaitForPageChange(WebDriverWait wait); diff --git a/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs b/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs index a98a021..bcb97c2 100644 --- a/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs +++ b/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs @@ -8,6 +8,8 @@ using WebDriverManager; using WebDriverManager.DriverConfigs.Impl; using System.IO; using System.Runtime.InteropServices; +using UniMarc.SearchModel; +using OpenQA.Selenium.Chromium; namespace BokBonCheck { @@ -67,8 +69,7 @@ namespace BokBonCheck protected string SelectorValue = ""; - private ChromeDriver _driver; - private ChromeDriverService _service; + private ChromiumDriver _driver; [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); @@ -81,54 +82,20 @@ namespace BokBonCheck this.No = no; } - public void StartDriver(bool showBrowser) - { - try - { - // 동기적으로 실행 (권장하지 않음) - StartDriverAsync( showBrowser).GetAwaiter().GetResult(); - } - catch (Exception ex) - { - Console.WriteLine($"StartDriver 실패: {ex.Message}"); - throw; - } - } - - public async Task StartDriverAsync( bool showdriver = false) + public async Task StartDriver(bool showBrowser = false) { if (_driver == null) { try { - // ChromeDriverManager를 사용하여 안정적으로 드라이버 설정 - var driverPath = await ChromeDriverManager.SetupChromeDriverAsync(); - - // ChromeDriver 서비스 생성 - _service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath), Path.GetFileName(driverPath)); - _service.HideCommandPromptWindow = true; - - // 안정적인 Chrome 옵션 가져오기 (브라우저 창 숨김) - var options = ChromeDriverManager.CreateBaseChromeOptions(!showdriver); - - // 추가 보안 및 안정성 옵션 - options.AddArgument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"); - options.AddArgument("--disable-blink-features=AutomationControlled"); - options.AddExcludedArgument("enable-automation"); - options.AddAdditionalOption("useAutomationExtension", false); - - // ChromeDriver 생성 - _driver = new ChromeDriver(_service, options); - - // 웹드라이버 감지 방지 - ((IJavaScriptExecutor)_driver).ExecuteScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"); - - Console.WriteLine("NamguLibrarySearcher ChromeDriver 초기화 완료"); + if (SeleniumHelper.IsReady == false) await SeleniumHelper.Download(); + _driver = await SeleniumHelper.CreateDriver(); + Console.WriteLine("KwangjuCityLibrarySearcher Driver 초기화 완료"); } catch (Exception ex) { - Console.WriteLine($"ChromeDriver 초기화 실패: {ex.Message}"); - throw new InvalidOperationException($"ChromeDriver 초기화에 실패했습니다: {ex.Message}", ex); + Console.WriteLine($"KwangjuCityLibrarySearcher Driver 초기화 실패: {ex.Message}"); + throw new InvalidOperationException($"KwangjuCityLibrarySearcher Driver 초기화에 실패했습니다: {ex.Message}", ex); } } } @@ -141,11 +108,6 @@ namespace BokBonCheck _driver.Dispose(); _driver = null; } - if (_service != null) - { - _service.Dispose(); - _service = null; - } } virtual protected void SelectLibrary(WebDriverWait wait) diff --git a/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs b/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs index af4aaf6..f4ae4d6 100644 --- a/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs +++ b/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs @@ -10,6 +10,9 @@ using System.IO; using System.Runtime.InteropServices; using System.Threading; using UniMarc.마크; +using OpenQA.Selenium.Chromium; +using UniMarc.SearchModel; +using System.Runtime.CompilerServices; namespace BokBonCheck { @@ -206,8 +209,7 @@ namespace BokBonCheck public int No { get; set; } - private ChromeDriver _driver; - private ChromeDriverService _service; + private ChromiumDriver _driver; [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); @@ -220,20 +222,7 @@ namespace BokBonCheck this.No = no; } - // 기존 StartDriver 메서드를 유지하여 호환성 보장 - public void StartDriver(bool showBrowser) - { - try - { - // 동기적으로 실행 (권장하지 않음) - StartDriverAsync(showBrowser).GetAwaiter().GetResult(); - } - catch (Exception ex) - { - Console.WriteLine($"StartDriver 실패: {ex.Message}"); - throw; - } - } + public void StopDriver() { @@ -243,47 +232,22 @@ namespace BokBonCheck _driver.Dispose(); _driver = null; } - if (_service != null) - { - _service.Dispose(); - _service = null; - } } - public async Task StartDriverAsync(bool showdriver = false) + public async Task StartDriver(bool showdriver = false) { if (_driver == null) { try { - // ChromeDriverManager를 사용하여 안정적으로 드라이버 설정 - var driverPath = await ChromeDriverManager.SetupChromeDriverAsync(); - - // ChromeDriver 서비스 생성 - _service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath), Path.GetFileName(driverPath)); - _service.HideCommandPromptWindow = true; - - // 안정적인 Chrome 옵션 가져오기 (브라우저 창 숨김) - var options = ChromeDriverManager.CreateBaseChromeOptions(!showdriver); - - // 추가 보안 및 안정성 옵션 - options.AddArgument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"); - options.AddArgument("--disable-blink-features=AutomationControlled"); - options.AddExcludedArgument("enable-automation"); - options.AddAdditionalOption("useAutomationExtension", false); - - // ChromeDriver 생성 - _driver = new ChromeDriver(_service, options); - - // 웹드라이버 감지 방지 - ((IJavaScriptExecutor)_driver).ExecuteScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"); - - Console.WriteLine("NamguLibrarySearcher ChromeDriver 초기화 완료"); + if (SeleniumHelper.IsReady == false) await SeleniumHelper.Download(); + _driver = await SeleniumHelper.CreateDriver(); + Console.WriteLine("NamguLibrarySearcher Driver 초기화 완료"); } catch (Exception ex) { - Console.WriteLine($"ChromeDriver 초기화 실패: {ex.Message}"); - throw new InvalidOperationException($"ChromeDriver 초기화에 실패했습니다: {ex.Message}", ex); + Console.WriteLine($"NamguLibrarySearcher Driver 초기화 실패: {ex.Message}"); + throw new InvalidOperationException($"NamguLibrarySearcher Driver 초기화에 실패했습니다: {ex.Message}", ex); } } } @@ -363,7 +327,7 @@ namespace BokBonCheck // 드라이버가 없으면 자동으로 시작 if (_driver == null) { - await StartDriverAsync(); + await StartDriver(); } _driver.Navigate().GoToUrl(SiteUrl); diff --git a/unimarc/unimarc/UniMarc.csproj b/unimarc/unimarc/UniMarc.csproj index e12bf8c..9aae795 100644 --- a/unimarc/unimarc/UniMarc.csproj +++ b/unimarc/unimarc/UniMarc.csproj @@ -226,7 +226,6 @@ - Form diff --git a/unimarc/unimarc/마크/Check_copyWD.cs b/unimarc/unimarc/마크/Check_copyWD.cs index feefeaf..a93d154 100644 --- a/unimarc/unimarc/마크/Check_copyWD.cs +++ b/unimarc/unimarc/마크/Check_copyWD.cs @@ -8,6 +8,7 @@ using System.Windows.Forms; using UniMarc.마크; using BokBonCheck; using AR; +using UniMarc.SearchModel; namespace WindowsFormsApp1.Mac { @@ -64,7 +65,6 @@ namespace WindowsFormsApp1.Mac private readonly BookSearchService _searchService; private bool _isSearching = false; - private bool _isDriverReady = false; private async void InitializeChromeDriver() { @@ -75,72 +75,75 @@ namespace WindowsFormsApp1.Mac try { // Chrome 설치 확인 - if (!ChromeDriverManager.IsChromeInstalled()) + if (!SeleniumHelper.IsBrowserInstalled()) { - MessageBox.Show("Google Chrome이 설치되어 있지 않습니다. Chrome을 설치한 후 프로그램을 다시 실행해주세요.", + MessageBox.Show("Google Chrome / Microsoft Edge 이(가) 설치되어 있지 않습니다. 브라우저를 설치한 후 프로그램을 다시 실행해주세요.", "Chrome 필요", MessageBoxButtons.OK, MessageBoxIcon.Warning); - lblStatus.Text = "WebDriver:Chrome이 설치되지 않음"; + lblStatus.Text = "WebDriver: 브라우저가 설치되지 않음"; lblStatus.ForeColor = Color.Red; return; } - // 기존 드라이버가 준비되어 있는지 확인 - if (ChromeDriverManager.IsDriverReady()) + //기존프로세스 삭제 + SeleniumHelper.KillExistingDrivers(); + + //준비된 경우에는 다운로드 하지 않는다. + if (SeleniumHelper.IsReady) { - lblStatus.Text = "WebDriver:Ready"; + lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})"; lblStatus.ForeColor = Color.Green; - _isDriverReady = true; - return; } - - // 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시 - using (var progressForm = new DownloadProgressForm()) + else { - progressForm.Show(); - - try + // 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시 + using (var progressForm = new DownloadProgressForm()) { - // ChromeDriver 설정 - await ChromeDriverManager.SetupChromeDriverAsync(progressForm); + progressForm.Show(); - // 드라이버 테스트 - var isWorking = await ChromeDriverManager.TestChromeDriverAsync(progressForm); - - if (isWorking) + try { - _isDriverReady = true; - lblStatus.Text = "WebDriver:Ready"; - lblStatus.ForeColor = Color.Green; + // ChromeDriver 설정 + await SeleniumHelper.Download(progressForm: progressForm); + + // 드라이버 테스트 + var isWorking = await SeleniumHelper.TestDriver(progressForm); + if (isWorking) + { + lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})"; + lblStatus.ForeColor = Color.Green; + } + else + { + lblStatus.Text = "WebDriver:드라이버 테스트 실패"; + lblStatus.ForeColor = Color.Red; + MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.", + "드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + } } - else + catch (OperationCanceledException) + { + lblStatus.Text = "WebDriver:드라이버 테스트가 취소되었습니다."; + lblStatus.ForeColor = Color.Orange; + return; + } + catch (Exception ex) { lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패"; lblStatus.ForeColor = Color.Red; - MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.", - "드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show($"Chrome 드라이버 테스트 중 오류가 발생했습니다: {ex.Message}", + "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; } } - catch (OperationCanceledException) - { - lblStatus.Text = "WebDriver:드라이버 다운로드가 취소되었습니다."; - lblStatus.ForeColor = Color.Orange; - return; - } - catch (Exception ex) - { - lblStatus.Text = "WebDriver:Chrome 드라이버 설정 실패"; - lblStatus.ForeColor = Color.Red; - MessageBox.Show($"Chrome 드라이버 설정 중 오류가 발생했습니다: {ex.Message}", - "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } } + + } catch (Exception ex) { - lblStatus.Text = "WebDriver:Chrome 드라이버 설정 실패"; + lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패"; lblStatus.ForeColor = Color.Red; - MessageBox.Show($"Chrome 드라이버 설정 중 오류가 발생했습니다: {ex.Message}", + MessageBox.Show($"Chrome 드라이버 테스트 중 오류가 발생했습니다: {ex.Message}", "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -212,7 +215,7 @@ namespace WindowsFormsApp1.Mac { //legacy UTIL.MsgE("이 기능은 기존 복본검사를 사용하세요"); - + } else { @@ -222,7 +225,7 @@ namespace WindowsFormsApp1.Mac return; } - if (this._isDriverReady == false) + if (SeleniumHelper.IsReady == false) { UTIL.MsgE("웹드라이버가 초기화되지 않았습니다\n1.크롬브라우즈가 설치되어있는지 확인하세요\n\n2.개발자 문의하세요"); return; @@ -237,11 +240,11 @@ namespace WindowsFormsApp1.Mac return; } - + this._isSearching = true; btn_Start.Enabled = false; btn_Stop.Enabled = false; - searcher.StartDriver(this.chkShowBrowser.Checked); + await searcher.StartDriver(this.chkShowBrowser.Checked); byte searchopt = 0; //전체검색 if (radTargetEmpty.Checked) searchopt = 1; else if (radTargetErr.Checked) searchopt = 2; @@ -253,8 +256,8 @@ namespace WindowsFormsApp1.Mac int cnt_ok = 0; int cnt_ng = 0; int cnt_er = 0; - - + + RetrySearch: foreach (DataGridViewRow drow in this.dataGridView1.Rows) { @@ -281,7 +284,7 @@ namespace WindowsFormsApp1.Mac if (radTargetErr.Checked) //오류데이터만 처리 { - if ( cntValue.Equals("-1")==false) + if (cntValue.Equals("-1") == false) continue; } else if (radTargetEmpty.Checked) //빈데이터만 처리 @@ -296,7 +299,7 @@ namespace WindowsFormsApp1.Mac } cnt_totalcnt += 1; - var rlt = await searcher.SearchAsync(bookName); + var rlt = await searcher.SearchAsync(bookName); if (rlt.IsSuccess) { drow.Cells["dvc_remark"].Value = rlt.ErrorMessage; @@ -335,7 +338,7 @@ namespace WindowsFormsApp1.Mac UTIL.MsgI($"검색 완료\n전체:{cnt_totalcnt}건/오류:{cnt_er}/성공:{cnt_ok}/없음:{cnt_ng}"); //재시도한경우라면 원복해준다 - if(retry) + if (retry) { if (searchopt == 1) radTargetEmpty.Checked = true; else if (searchopt == 2) radTargetErr.Checked = true; @@ -362,7 +365,7 @@ namespace WindowsFormsApp1.Mac } int RowCount = 0; - + /// /// 입력된 카운트를 소장/미소장으로 바꿔서 반환 @@ -391,7 +394,7 @@ namespace WindowsFormsApp1.Mac return Count; } - + private void btn_Stop_Click(object sender, EventArgs e) { _isSearching = false; diff --git a/unimarc/unimarc/마크/DLS_Copy.cs b/unimarc/unimarc/마크/DLS_Copy.cs index 61f3a9d..22cce0e 100644 --- a/unimarc/unimarc/마크/DLS_Copy.cs +++ b/unimarc/unimarc/마크/DLS_Copy.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using UniMarc.SearchModel; namespace WindowsFormsApp1.Mac { @@ -43,7 +44,6 @@ namespace WindowsFormsApp1.Mac private readonly BookSearchService _searchService; private bool _isSearching = false; - private bool _isDriverReady = false; private async void InitializeChromeDriver() { @@ -54,76 +54,76 @@ namespace WindowsFormsApp1.Mac try { // Chrome 설치 확인 - if (!ChromeDriverManager.IsChromeInstalled()) + if (!SeleniumHelper.IsBrowserInstalled()) { - MessageBox.Show("Google Chrome이 설치되어 있지 않습니다. Chrome을 설치한 후 프로그램을 다시 실행해주세요.", + MessageBox.Show("Google Chrome / Microsoft Edge 이(가) 설치되어 있지 않습니다. 브라우저를 설치한 후 프로그램을 다시 실행해주세요.", "Chrome 필요", MessageBoxButtons.OK, MessageBoxIcon.Warning); - lblStatus.Text = "WebDriver:Chrome이 설치되지 않음"; + lblStatus.Text = "WebDriver: 브라우저가 설치되지 않음"; lblStatus.ForeColor = Color.Red; return; } - // 기존 드라이버가 준비되어 있는지 확인 - if (ChromeDriverManager.IsDriverReady()) + //준비된 경우에는 다운로드 하지 않는다. + if (SeleniumHelper.IsReady) { - lblStatus.Text = "WebDriver:Ready"; + lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})"; lblStatus.ForeColor = Color.Green; - _isDriverReady = true; - return; } - - // 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시 - using (var progressForm = new DownloadProgressForm()) + else { - progressForm.Show(); - - try + // 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시 + using (var progressForm = new DownloadProgressForm()) { - // ChromeDriver 설정 - await ChromeDriverManager.SetupChromeDriverAsync(progressForm); + progressForm.Show(); - // 드라이버 테스트 - var isWorking = await ChromeDriverManager.TestChromeDriverAsync(progressForm); - - if (isWorking) + try { - _isDriverReady = true; - lblStatus.Text = "WebDriver:Ready"; - lblStatus.ForeColor = Color.Green; + // ChromeDriver 설정 + await SeleniumHelper.Download(progressForm: progressForm); + + // 드라이버 테스트 + var isWorking = await SeleniumHelper.TestDriver(progressForm); + if (isWorking) + { + lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})"; + lblStatus.ForeColor = Color.Green; + } + else + { + lblStatus.Text = "WebDriver:드라이버 테스트 실패"; + lblStatus.ForeColor = Color.Red; + MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.", + "드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + } } - else + catch (OperationCanceledException) + { + lblStatus.Text = "WebDriver:드라이버 테스트가 취소되었습니다."; + lblStatus.ForeColor = Color.Orange; + return; + } + catch (Exception ex) { lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패"; lblStatus.ForeColor = Color.Red; - MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.", - "드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show($"Chrome 드라이버 테스트 중 오류가 발생했습니다: {ex.Message}", + "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; } } - catch (OperationCanceledException) - { - lblStatus.Text = "WebDriver:드라이버 다운로드가 취소되었습니다."; - lblStatus.ForeColor = Color.Orange; - return; - } - catch (Exception ex) - { - lblStatus.Text = "WebDriver:Chrome 드라이버 설정 실패"; - lblStatus.ForeColor = Color.Red; - MessageBox.Show($"Chrome 드라이버 설정 중 오류가 발생했습니다: {ex.Message}", - "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } } + + } catch (Exception ex) { - lblStatus.Text = "WebDriver:Chrome 드라이버 설정 실패"; + lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패"; lblStatus.ForeColor = Color.Red; - MessageBox.Show($"Chrome 드라이버 설정 중 오류가 발생했습니다: {ex.Message}", + MessageBox.Show($"Chrome 드라이버 테스트 중 오류가 발생했습니다: {ex.Message}", "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); } } -#endregion + #endregion private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) { Skill_Grid sg = new Skill_Grid();