#Requires -Version 5.1 <# .SYNOPSIS "DMF 설정.lnk" / "지금 실행.lnk" 를 프로젝트 루트와 바탕화면에 만든다. .DESCRIPTION 대상은 반드시 pythonw.exe 다. python.exe 나 .cmd 를 대상으로 하면 더블클릭할 때마다 검은 콘솔 창이 번쩍인다(PE 서브시스템 = WINDOWS_CUI). 관리자 권한은 필요하지 않다. 멱등하다 — 몇 번을 다시 실행해도 기존 바로가기를 덮어쓸 뿐 중복 파일을 만들지 않는다. .PARAMETER ProjectRoot 프로젝트 루트 경로. bootstrap.cmd 가 자신의 위치를 넘겨준다. .EXAMPLE powershell -ExecutionPolicy Bypass -File .\scripts\make_shortcuts.ps1 -ProjectRoot "D:\workspace\DMF_Crawler" #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$ProjectRoot ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' function Write-Step { param([string]$Message) Write-Host "[make_shortcuts] $Message" } function Write-Warn { param([string]$Message) Write-Host "[make_shortcuts] ! $Message" -ForegroundColor Yellow } try { $ProjectRoot = (Resolve-Path -LiteralPath $ProjectRoot).Path } catch { throw "프로젝트 루트를 찾을 수 없습니다: $ProjectRoot" } $pythonw = Join-Path $ProjectRoot '.venv\Scripts\pythonw.exe' if (-not (Test-Path -LiteralPath $pythonw)) { throw "실행 환경을 찾을 수 없습니다: $pythonw`n → bootstrap.cmd 를 먼저 실행하세요." } # 아이콘: 있으면 전용 아이콘, 없으면 시스템 폴백(진단 문서 아이콘)을 쓴다. $iconFile = Join-Path $ProjectRoot 'assets\dmf.ico' if (-not (Test-Path -LiteralPath $iconFile)) { $iconFile = "$env:SystemRoot\System32\imageres.dll,109" } $desktop = [System.Environment]::GetFolderPath('Desktop') $targets = @($ProjectRoot, $desktop) | Where-Object { $_ -and (Test-Path -LiteralPath $_) } | Select-Object -Unique if ($targets.Count -eq 0) { throw '바로가기를 놓을 수 있는 폴더가 없습니다(프로젝트 루트도, 바탕화면도 접근 불가).' } # 지금 실행.lnk 는 "검사 → CRITICAL 통과면 즉시 실행" 모드로 들어간다(onboard --mode inspect --run-now). $specs = @( @{ Name = 'DMF 설정.lnk' Args = '-m dmf_crawler onboard --mode setup' Desc = 'DMF 크롤러 설정 및 상태 확인' }, @{ Name = '지금 실행.lnk' Args = '-m dmf_crawler onboard --mode inspect --run-now' Desc = 'DMF 자료를 지금 받아 리포트를 만듭니다' } ) $shell = New-Object -ComObject WScript.Shell $created = 0 $failed = 0 try { foreach ($dir in $targets) { foreach ($s in $specs) { $path = Join-Path $dir $s.Name try { $lnk = $shell.CreateShortcut($path) $lnk.TargetPath = $pythonw $lnk.Arguments = $s.Args $lnk.WorkingDirectory = $ProjectRoot $lnk.IconLocation = $iconFile $lnk.Description = $s.Desc $lnk.WindowStyle = 1 # SW_SHOWNORMAL — 호스트가 GUI 라 콘솔은 뜨지 않는다 $lnk.Save() Write-Step "바로가기 생성: $path" $created++ } catch { Write-Warn "바로가기 생성 실패: $path ($($_.Exception.Message))" $failed++ } finally { if ($lnk) { [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($lnk) } } } } } finally { [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($shell) } Write-Step "완료: $created 개 생성, $failed 개 실패" # 바탕화면 접근 실패 등으로 전부 실패했을 때만 비정상 종료로 알린다. # 부분 성공(예: 프로젝트 루트만 성공)은 실사용에 지장이 없으므로 0으로 끝낸다. if ($created -eq 0) { exit 1 } exit 0