refactor: SearchModel 구조 개선 및 비동기 처리 최적화

- 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 <noreply@anthropic.com>
This commit is contained in:
2025-08-12 19:36:53 +09:00
parent 4d1450d2c5
commit 0f3d985b82
8 changed files with 126 additions and 937 deletions

View File

@@ -18,8 +18,9 @@
},
"permissions": {
"allow": [
"WebFetch(domain:lib.namgu.gwangju.kr)"
"Bash(git add:*)"
],
"deny": []
"deny": [],
"ask": []
}
}

View File

@@ -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<string> 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<string> 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<bool> 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;
}
}
/// <summary>
/// 기본 Chrome 옵션을 생성하는 헬퍼 메서드
/// </summary>
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;
}
/// <summary>
/// 검색 최적화된 Chrome 옵션을 반환합니다
/// </summary>
public static ChromeOptions GetSearchOptimizedOptions()
{
var options = CreateBaseChromeOptions(true);
// 검색에 필요한 기능만 활성화
options.AddArgument("--enable-javascript");
options.AddArgument("--enable-images");
return options;
}
private static async Task<bool> 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}");
}
}
}
}

View File

@@ -15,7 +15,7 @@ namespace BokBonCheck
string SiteName { get; }
string SiteUrl { get; }
Task<BookSearchResult> SearchAsync(string searchTerm);
void StartDriver(bool showBrowser);
Task StartDriver(bool showBrowser);
void StopDriver();
Task WaitForPageChange(WebDriverWait wait);

View File

@@ -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)

View File

@@ -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);

View File

@@ -226,7 +226,6 @@
</Compile>
<Compile Include="PUB.cs" />
<Compile Include="SearchModel\BookSearchService.cs" />
<Compile Include="SearchModel\ChromeDriverManager.cs" />
<Compile Include="SearchModel\DownloadProgressForm.cs">
<SubType>Form</SubType>
</Compile>

View File

@@ -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,24 +75,26 @@ 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())
{
lblStatus.Text = "WebDriver:Ready";
lblStatus.ForeColor = Color.Green;
_isDriverReady = true;
return;
}
//기존프로세스 삭제
SeleniumHelper.KillExistingDrivers();
//준비된 경우에는 다운로드 하지 않는다.
if (SeleniumHelper.IsReady)
{
lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})";
lblStatus.ForeColor = Color.Green;
}
else
{
// 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시
using (var progressForm = new DownloadProgressForm())
{
@@ -101,20 +103,18 @@ namespace WindowsFormsApp1.Mac
try
{
// ChromeDriver 설정
await ChromeDriverManager.SetupChromeDriverAsync(progressForm);
await SeleniumHelper.Download(progressForm: progressForm);
// 드라이버 테스트
var isWorking = await ChromeDriverManager.TestChromeDriverAsync(progressForm);
var isWorking = await SeleniumHelper.TestDriver(progressForm);
if (isWorking)
{
_isDriverReady = true;
lblStatus.Text = "WebDriver:Ready";
lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})";
lblStatus.ForeColor = Color.Green;
}
else
{
lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패";
lblStatus.Text = "WebDriver:드라이버 테스트 실패";
lblStatus.ForeColor = Color.Red;
MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.",
"드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
@@ -122,25 +122,28 @@ namespace WindowsFormsApp1.Mac
}
catch (OperationCanceledException)
{
lblStatus.Text = "WebDriver:드라이버 다운로드가 취소되었습니다.";
lblStatus.Text = "WebDriver:드라이버 테스트가 취소되었습니다.";
lblStatus.ForeColor = Color.Orange;
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);
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);
}
}
@@ -222,7 +225,7 @@ namespace WindowsFormsApp1.Mac
return;
}
if (this._isDriverReady == false)
if (SeleniumHelper.IsReady == false)
{
UTIL.MsgE("웹드라이버가 초기화되지 않았습니다\n1.크롬브라우즈가 설치되어있는지 확인하세요\n\n2.개발자 문의하세요");
return;
@@ -241,7 +244,7 @@ namespace WindowsFormsApp1.Mac
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;

View File

@@ -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,24 +54,23 @@ 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;
}
else
{
// 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시
using (var progressForm = new DownloadProgressForm())
{
@@ -80,20 +79,18 @@ namespace WindowsFormsApp1.Mac
try
{
// ChromeDriver 설정
await ChromeDriverManager.SetupChromeDriverAsync(progressForm);
await SeleniumHelper.Download(progressForm: progressForm);
// 드라이버 테스트
var isWorking = await ChromeDriverManager.TestChromeDriverAsync(progressForm);
var isWorking = await SeleniumHelper.TestDriver(progressForm);
if (isWorking)
{
_isDriverReady = true;
lblStatus.Text = "WebDriver:Ready";
lblStatus.Text = $"WebDriver:Ready({SeleniumHelper.Browser})";
lblStatus.ForeColor = Color.Green;
}
else
{
lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패";
lblStatus.Text = "WebDriver:드라이버 테스트 실패";
lblStatus.ForeColor = Color.Red;
MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.",
"드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
@@ -101,25 +98,28 @@ namespace WindowsFormsApp1.Mac
}
catch (OperationCanceledException)
{
lblStatus.Text = "WebDriver:드라이버 다운로드가 취소되었습니다.";
lblStatus.Text = "WebDriver:드라이버 테스트가 취소되었습니다.";
lblStatus.ForeColor = Color.Orange;
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);
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);
}
}