diff --git a/App.config b/App.config index 3ea2120..b92d608 100644 --- a/App.config +++ b/App.config @@ -9,4 +9,5 @@ + \ No newline at end of file diff --git a/Models/VNCPathRequest.cs b/Models/VNCPathRequest.cs new file mode 100644 index 0000000..e57d3ee --- /dev/null +++ b/Models/VNCPathRequest.cs @@ -0,0 +1,7 @@ +namespace VNCServerList.Models +{ + public class VNCPathRequest + { + public string Path { get; set; } + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 717e51e..c6cacac 100644 --- a/Program.cs +++ b/Program.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; +using Microsoft.Web.WebView2.Core; +using System.IO; +using System.Net; +using System.Diagnostics; namespace VNCServerList { @@ -16,7 +20,75 @@ namespace VNCServerList { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Form1()); + + // WebView2 런타임 확인 및 자동 다운로드 + if (!WebView2Installer.IsWebView2Installed()) + { + var result = MessageBox.Show( + "WebView2 런타임이 설치되지 않았습니다.\n\n" + + "자동으로 다운로드하여 설치하시겠습니까?\n\n" + + "예: 자동 다운로드 및 설치\n" + + "아니오: 수동으로 다운로드 페이지 열기", + "WebView2 런타임 설치", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + // 비동기로 설치 실행 + var installTask = WebView2Installer.InstallWebView2Async(); + + // 설치 완료 대기 + bool success = installTask.Result; + + if (success) + { + MessageBox.Show( + "WebView2 런타임 설치가 완료되었습니다.\n" + + "프로그램을 다시 실행해주세요.", + "설치 완료", + MessageBoxButtons.OK, + MessageBoxIcon.Information); + } + else + { + MessageBox.Show( + "WebView2 런타임 설치에 실패했습니다.\n" + + "수동으로 설치해주세요.", + "설치 실패", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + // 수동 다운로드 페이지 열기 + Process.Start("https://developer.microsoft.com/en-us/microsoft-edge/webview2/"); + } + } + else + { + // WebView2 런타임 다운로드 페이지 열기 + Process.Start("https://developer.microsoft.com/en-us/microsoft-edge/webview2/"); + } + return; + } + + try + { + var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\VNCServerList\\WebView2Data"; + var env = CoreWebView2Environment.CreateAsync(null, userDataFolder).Result; + + Application.Run(new Form1()); + } + catch (Exception ex) + { + MessageBox.Show( + "WebView2 초기화 중 오류가 발생했습니다.\n" + + "오류: " + ex.Message, + "오류", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + } } + + } } diff --git a/README_deploy.txt b/README_deploy.txt new file mode 100644 index 0000000..9d6886f --- /dev/null +++ b/README_deploy.txt @@ -0,0 +1,19 @@ +VNCServerList 배포 파일 (VS2017 Express 버전) + +필요한 파일: +- VNCServerList.exe (메인 실행 파일) +- VNCServerList.exe.config (설정 파일) +- *.dll 파일들 (필요한 라이브러리) +- Web\ 폴더 (웹 인터페이스 파일들) + +시스템 요구사항: +- Windows 7 SP1 이상 +- .NET Framework 4.8 +- Microsoft Edge WebView2 Runtime (자동 다운로드됨) + +설치 방법: +1. 모든 파일을 원하는 폴더에 복사 +2. VNCServerList.exe 실행 +3. 웹 브라우저에서 http://localhost:8080 접속 + +참고: WebView2 Runtime이 설치되지 않은 경우 자동으로 다운로드됩니다. \ No newline at end of file diff --git a/VNCServerList.csproj b/VNCServerList.csproj index 27fdcb7..905e8cf 100644 --- a/VNCServerList.csproj +++ b/VNCServerList.csproj @@ -12,6 +12,7 @@ 512 true true + false AnyCPU @@ -32,18 +33,13 @@ prompt 4 - + - - - - - @@ -56,7 +52,14 @@ + + + + + true + true + Form @@ -65,9 +68,11 @@ Form1.cs + + @@ -103,5 +108,6 @@ + \ No newline at end of file diff --git a/Web/Controllers/VNCServerController.cs b/Web/Controllers/VNCServerController.cs index 28c1fbf..ca1f7e0 100644 --- a/Web/Controllers/VNCServerController.cs +++ b/Web/Controllers/VNCServerController.cs @@ -186,11 +186,11 @@ namespace VNCServerList.Web.Controllers [HttpPost] [Route("set-vnc-path")] - public IHttpActionResult SetVNCPath([FromBody] dynamic data) + public IHttpActionResult SetVNCPath([FromBody] VNCPathRequest data) { try { - string path = data.path; + string path = data.Path; if (string.IsNullOrEmpty(path)) { return BadRequest("VNC Viewer 경로가 제공되지 않았습니다."); diff --git a/WebView2Installer.cs b/WebView2Installer.cs new file mode 100644 index 0000000..62832d2 --- /dev/null +++ b/WebView2Installer.cs @@ -0,0 +1,190 @@ +using System; +using System.IO; +using System.Net; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading.Tasks; + +namespace VNCServerList +{ + public static class WebView2Installer + { + private const string DOWNLOAD_URL = "https://go.microsoft.com/fwlink/p/?LinkId=2124703"; + private const string INSTALLER_NAME = "MicrosoftEdgeWebview2Setup.exe"; + + public static async Task InstallWebView2Async() + { + try + { + // 다운로드 진행 상황 표시 + using (var progressForm = new WebView2DownloadForm()) + { + progressForm.Show(); + + // 임시 폴더에 설치 파일 다운로드 + string tempFolder = Path.GetTempPath(); + string installerPath = Path.Combine(tempFolder, INSTALLER_NAME); + + // 기존 파일이 있으면 삭제 + if (File.Exists(installerPath)) + { + File.Delete(installerPath); + } + + // 다운로드 + using (var client = new WebClient()) + { + client.DownloadProgressChanged += (sender, e) => + { + progressForm.UpdateProgress(e.ProgressPercentage, e.BytesReceived, e.TotalBytesToReceive); + }; + + await client.DownloadFileTaskAsync(new Uri(DOWNLOAD_URL), installerPath); + } + + progressForm.Close(); + + // 설치 실행 + var startInfo = new ProcessStartInfo + { + FileName = installerPath, + Arguments = "/silent /install", // 자동 설치 + UseShellExecute = true + }; + + var process = Process.Start(startInfo); + + // 설치 완료 대기 (최대 5분) + if (process != null) + { + await Task.Run(() => process.WaitForExit(300000)); // 5분 + + // 설치 파일 정리 + try + { + if (File.Exists(installerPath)) + { + File.Delete(installerPath); + } + } + catch { /* 무시 */ } + + return process.ExitCode == 0; + } + + return false; + } + } + catch (Exception ex) + { + MessageBox.Show( + $"WebView2 런타임 설치 중 오류가 발생했습니다:\n{ex.Message}", + "설치 오류", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + return false; + } + } + + public static bool IsWebView2Installed() + { + try + { + // 레지스트리에서 WebView2 설치 확인 + using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}")) + { + if (key != null) + { + return true; + } + } + + // 64비트 시스템에서 32비트 레지스트리 확인 + using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}")) + { + if (key != null) + { + return true; + } + } + + return false; + } + catch + { + return false; + } + } + } + + public partial class WebView2DownloadForm : Form + { + private ProgressBar progressBar; + private Label statusLabel; + + public WebView2DownloadForm() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + this.progressBar = new ProgressBar(); + this.statusLabel = new Label(); + this.SuspendLayout(); + + // Form 설정 + this.Text = "WebView2 런타임 다운로드"; + this.Size = new System.Drawing.Size(400, 150); + this.StartPosition = FormStartPosition.CenterScreen; + this.FormBorderStyle = FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + + // Status Label + this.statusLabel.AutoSize = true; + this.statusLabel.Location = new System.Drawing.Point(20, 20); + this.statusLabel.Size = new System.Drawing.Size(360, 20); + this.statusLabel.Text = "WebView2 런타임을 다운로드하고 있습니다..."; + + // Progress Bar + this.progressBar.Location = new System.Drawing.Point(20, 50); + this.progressBar.Size = new System.Drawing.Size(360, 30); + this.progressBar.Style = ProgressBarStyle.Continuous; + + // Controls 추가 + this.Controls.Add(this.statusLabel); + this.Controls.Add(this.progressBar); + + this.ResumeLayout(false); + this.PerformLayout(); + } + + public void UpdateProgress(int percentage, long bytesReceived, long totalBytes) + { + if (this.InvokeRequired) + { + this.Invoke(new Action(() => UpdateProgress(percentage, bytesReceived, totalBytes))); + return; + } + + this.progressBar.Value = percentage; + this.statusLabel.Text = $"다운로드 중... {percentage}% ({FormatBytes(bytesReceived)} / {FormatBytes(totalBytes)})"; + } + + private string FormatBytes(long bytes) + { + string[] suffixes = { "B", "KB", "MB", "GB" }; + int counter = 0; + decimal number = bytes; + + while (Math.Round(number / 1024) >= 1) + { + number /= 1024; + counter++; + } + + return $"{number:n1} {suffixes[counter]}"; + } + } +} \ No newline at end of file diff --git a/build_simple.bat b/build_simple.bat new file mode 100644 index 0000000..ce8e556 --- /dev/null +++ b/build_simple.bat @@ -0,0 +1,46 @@ +@echo off +echo Creating VNCServerList deployment package from Debug folder... +echo. + +REM Check if Debug folder exists +if not exist "bin\Debug" ( + echo Error: bin\Debug folder not found! + echo Please build the project first in Visual Studio 2017 Express: + echo 1. Open VNCServerList.sln in Visual Studio 2017 Express + echo 2. Build -> Build Solution + echo. + pause + exit /b 1 +) + +echo Found Debug folder. Creating deployment package... +echo. + +REM Create deployment folder +if not exist "deploy" mkdir deploy + +REM Copy all files from Debug folder (except .pdb files) +echo Copying files from Debug folder... +xcopy "bin\Debug\*.*" "deploy\" /E /I /Y + +REM Remove .pdb files (debug symbols) +if exist "deploy\*.pdb" del "deploy\*.pdb" + +REM Copy README file +if exist "README_deploy.txt" ( + copy "README_deploy.txt" "deploy\README.txt" + echo Copied README.txt to deploy\ +) else ( + echo Warning: README_deploy.txt not found +) + +echo. +echo Deployment package created in 'deploy' folder! +echo. +echo Files included: +dir deploy /b +echo. +echo Note: This package includes all necessary files from Debug folder. +echo You can now zip the 'deploy' folder and distribute it. +echo. +pause \ No newline at end of file diff --git a/deploy_debug.bat b/deploy_debug.bat new file mode 100644 index 0000000..9da0726 --- /dev/null +++ b/deploy_debug.bat @@ -0,0 +1,34 @@ +@echo off +echo VNCServerList Debug 배포 패키지 생성 +echo. + +REM Debug 폴더 확인 +if not exist "bin\Debug" ( + echo 오류: bin\Debug 폴더를 찾을 수 없습니다! + echo Visual Studio에서 먼저 빌드해주세요. + pause + exit /b 1 +) + +REM 배포 폴더 생성 +if exist "deploy" rmdir /s /q "deploy" +mkdir deploy + +REM Debug 폴더의 모든 파일 복사 +echo Debug 폴더에서 파일 복사 중... +xcopy "bin\Debug\*.*" "deploy\" /E /I /Y + +REM .pdb 파일 제거 (디버그 심볼) +if exist "deploy\*.pdb" del "deploy\*.pdb" + +REM README 추가 +if exist "README_deploy.txt" copy "README_deploy.txt" "deploy\README.txt" + +echo. +echo 배포 패키지가 생성되었습니다! +echo. +echo 포함된 파일: +dir deploy /b +echo. +echo 이제 deploy 폴더를 압축해서 배포하세요. +pause \ No newline at end of file