using System; using System.IO; using System.IO.Compression; using System.Reflection; using System.Windows.Forms; using System.Drawing; namespace MarkingInstaller { public class Program { [STAThread] public static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); string targetDir = @"C:\marking"; // 설치 의사 확인 var confirm = MessageBox.Show( "Marking 시스템을 컴퓨터에 설치하시겠습니까?\n\n" + "설치 경로: " + targetDir + "\n" + "바탕화면에 실행 바로가기 아이콘이 생성됩니다.", "Marking 설치 관리자", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (confirm != DialogResult.Yes) return; // 설치 상태 진행 폼 Form installForm = new Form { Text = "Marking 설치 진행 중...", Size = new Size(400, 150), StartPosition = FormStartPosition.CenterScreen, FormBorderStyle = FormBorderStyle.FixedDialog, MaximizeBox = false, MinimizeBox = false, BackColor = Color.FromArgb(240, 243, 244) }; Label lblStatus = new Label { Text = "설치 파일 압축을 푸는 중입니다...", Location = new Point(20, 20), Size = new Size(360, 25), Font = new Font("Malgun Gothic", 10, FontStyle.Bold) }; ProgressBar pb = new ProgressBar { Location = new Point(20, 55), Size = new Size(345, 23), Style = ProgressBarStyle.Marquee }; installForm.Controls.Add(lblStatus); installForm.Controls.Add(pb); installForm.Shown += async (s, ev) => { try { await System.Threading.Tasks.Task.Run(() => { // 1. 기존 디렉토리 안전 클린업 if (Directory.Exists(targetDir)) { try { Directory.Delete(targetDir, true); } catch { // 프로세스가 잠긴 경우 대비하여 모든 파일 삭제 시도 foreach (var file in Directory.GetFiles(targetDir, "*.*", SearchOption.AllDirectories)) { try { File.Delete(file); } catch { } } } } Directory.CreateDirectory(targetDir); // 2. 리소스에서 payload.zip 추출 및 압축 해제 var assembly = Assembly.GetExecutingAssembly(); using (Stream resourceStream = assembly.GetManifestResourceStream("payload.zip")) { if (resourceStream == null) { throw new Exception("설치 리소스를 찾을 수 없습니다. (payload.zip)"); } string tempZip = Path.Combine(Path.GetTempPath(), "marking_payload.zip"); using (FileStream fs = new FileStream(tempZip, FileMode.Create, FileAccess.Write)) { resourceStream.CopyTo(fs); } ZipFile.ExtractToDirectory(tempZip, targetDir); try { File.Delete(tempZip); } catch { } } // 3. 바탕화면에 프로그램 바로가기 단축 아이콘 생성 CreateShortcut(targetDir); }); installForm.Close(); MessageBox.Show( "설치가 성공적으로 완료되었습니다!\n" + "바탕화면의 [Marking System] 아이콘을 클릭하여 앱을 사용하십시오.", "설치 완료", MessageBoxButtons.OK, MessageBoxIcon.Information); // 설치 완료 후 즉시 프로그램 실행 try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = Path.Combine(targetDir, "marking_gui.exe"), WorkingDirectory = targetDir }); } catch { } } catch (Exception ex) { installForm.Close(); MessageBox.Show("설치 중 예기치 못한 오류가 발생했습니다:\n" + ex.Message, "설치 실패", MessageBoxButtons.OK, MessageBoxIcon.Error); } }; Application.Run(installForm); } private static void CreateShortcut(string targetDir) { try { string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); string shortcutPath = Path.Combine(desktopPath, "Marking System.lnk"); // Windows Script Host 리플렉션을 활용해 무참조 단축 바로가기 아이콘 생성 Type shellType = Type.GetTypeFromProgID("WScript.Shell"); object shell = Activator.CreateInstance(shellType); object shortcut = shellType.InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shell, new object[] { shortcutPath }); shellType.InvokeMember("TargetPath", BindingFlags.SetProperty, null, shortcut, new object[] { Path.Combine(targetDir, "marking_gui.exe") }); shellType.InvokeMember("WorkingDirectory", BindingFlags.SetProperty, null, shortcut, new object[] { targetDir }); shellType.InvokeMember("Description", BindingFlags.SetProperty, null, shortcut, new object[] { "Marking System Application" }); shellType.InvokeMember("Save", BindingFlags.InvokeMethod, null, shortcut, null); } catch (Exception ex) { Console.WriteLine("바탕화면 바로가기 등록 실패: " + ex.Message); } } } }