1+ # ---------------------------------------------------------
2+ # PROJECT NAME: Elite-BuildTool
3+ # VERSION NUMBER (MUST ALWAYS BE 4 VALUES): 1.0.0.0
4+ #
5+ # VERSIONING RULES A.B.C.D A= Major B= Secondary C= Minor D= Quick Bug Fix
6+ #
7+ # Scope / Purpose:
8+ # Automated factory floor for the EliteSoftware-ScriptTools-Archive.
9+ # Recursively scans the sibling archive folder, cleans metadata headers from scripts,
10+ # and compiles them into standalone executables using Win-PS2EXE.
11+ #
12+ # Developer Notes:
13+ # - REQUIRES Win-PS2EXE module (ps2exe).
14+ # - Implements "Auto-Pilot" and "Precision Strike" modes.
15+ # - Hides console windows for compiled tools (-noConsole).
16+ # - Adheres strictly to EliteSoftware architecture and "The Laws of the Build".
17+ # ---------------------------------------------------------
18+
19+ # 1. --- PORTABLE PATH & CONFIGURATION ---
20+ $ScriptBaseDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
21+ $ConfigDirName = "Elite-BuildTool_Config"
22+ $ConfigDir = [System.IO.Path]::Combine($ScriptBaseDir, $ConfigDirName)
23+ $LogFilesDir = [System.IO.Path]::Combine($ConfigDir, "Log Files")
24+ $ErrorLogDir = [System.IO.Path]::Combine($LogFilesDir, "Error Logs")
25+ $HistoricalLogDir = [System.IO.Path]::Combine($LogFilesDir, "Historical Logs")
26+ $HistoricalErrorLogDir = [System.IO.Path]::Combine($ErrorLogDir, "Historical Logs")
27+ $Global:LiveLogFile = [System.IO.Path]::Combine($LogFilesDir, "LiveLog.json")
28+
29+ # 2. --- AUTOMATIC DIRECTORY CREATION ---
30+ @($ConfigDir, $LogFilesDir, $ErrorLogDir, $HistoricalLogDir, $HistoricalErrorLogDir) | ForEach-Object {
31+ if (-not (Test-Path $_)) {
32+ New-Item -Path $_ -ItemType Directory -Force | Out-Null
33+ }
34+ }
35+
36+ # 3. --- LOGGING FUNCTIONS ---
37+ function Archive-OldLogs {
38+ if (Test-Path $Global:LiveLogFile) {
39+ try {
40+ $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
41+ $destination = [System.IO.Path]::Combine($HistoricalLogDir, "LiveLog-$timestamp.json")
42+ Move-Item -Path $Global:LiveLogFile -Destination $destination -Force
43+ } catch {}
44+ }
45+ $oldErrorLogs = Get-ChildItem -Path $ErrorLogDir -Filter "*.json"
46+ foreach ($log in $oldErrorLogs) {
47+ try {
48+ $destination = [System.IO.Path]::Combine($HistoricalErrorLogDir, $log.Name)
49+ Move-Item -Path $log.FullName -Destination $destination -Force
50+ } catch {}
51+ }
52+ }
53+
54+ function Write-Log {
55+ param (
56+ [string]$Message,
57+ [ValidateSet("INFO", "WARN", "ERROR", "FATAL")]
58+ [string]$Severity = "INFO"
59+ )
60+ if ($Severity -eq "WARN") { Write-Warning $Message }
61+ $logEntry = @{
62+ Timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ss"
63+ Severity = $Severity
64+ Message = $Message
65+ }
66+ try {
67+ $logEntry | ConvertTo-Json -Compress | Add-Content -Path $Global:LiveLogFile
68+ } catch {}
69+ }
70+
71+ function Write-ErrorLog {
72+ param (
73+ [string]$ContextMessage,
74+ [System.Management.Automation.ErrorRecord]$ErrorRecord
75+ )
76+ Write-Error -ErrorRecord $ErrorRecord
77+ $timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ss"
78+ $fileNameTimestamp = Get-Date -Format "yyyyMMdd-HHmmss"
79+ $errorDetails = @{
80+ Timestamp = $timestamp
81+ Context = $ContextMessage
82+ Exception_Type = $ErrorRecord.Exception.GetType().FullName
83+ Exception_Msg = $ErrorRecord.Exception.Message
84+ StackTrace = $ErrorRecord.Exception.StackTrace
85+ Script_Line = $ErrorRecord.InvocationInfo.ScriptLineNumber
86+ Line_Content = $ErrorRecord.InvocationInfo.Line
87+ }
88+ try {
89+ $errorJson = $errorDetails | ConvertTo-Json -Depth 5
90+ $destination = [System.IO.Path]::Combine($ErrorLogDir, "ErrorLog-$fileNameTimestamp.json")
91+ $errorJson | Out-File -FilePath $destination -Encoding UTF8
92+ Write-Log -Message "An error occurred. Details in ErrorLog-$fileNameTimestamp.json. Context: $ContextMessage" -Severity "ERROR"
93+ } catch {}
94+ }
95+
96+ # 4. --- RUN AT STARTUP ---
97+ Archive-OldLogs
98+ Write-Log -Message "Script started. Logging system initialized."
99+
100+ # --- MAIN GUI & BUILD LOGIC ---
101+
102+ # 1. The Visual Vibe Check (Rule 1)
103+ # MUST be executed before any UI elements are created to ensure native Windows Vista/7/10 styling.
104+ Add-Type -AssemblyName System.Windows.Forms
105+ Add-Type -AssemblyName System.Drawing
106+ [System.Windows.Forms.Application]::EnableVisualStyles()
107+
108+ # 2. The Module Pre-Flight (Rule 7)
109+ if (-not (Get-Command Invoke-PS2EXE -ErrorAction SilentlyContinue)) {
110+ $Msg = "Win-PS2EXE (ps2exe module) is missing or not loaded. Please ensure it is installed."
111+ Write-Log -Message $Msg -Severity "FATAL"
112+ [System.Windows.Forms.MessageBox]::Show($Msg, "Dependency Missing", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
113+ exit
114+ }
115+
116+ # 3. Path Definitions
117+ # Master Icon - S:\Projects\EliteSoftware-ScriptTools-Archive\Elite-BuildTool\EliteSoftware.ico (Root)
118+ $MasterIcon = Join-Path $PSScriptRoot "EliteSoftware.ico"
119+
120+ # Archive Root (Sibling Folder)
121+ $ArchiveRoot = Resolve-Path (Join-Path $PSScriptRoot "..\PowerShell-Script_Archive") -ErrorAction SilentlyContinue
122+
123+ # Form Setup
124+ $Form = New-Object System.Windows.Forms.Form
125+ $Form.Text = "Elite-BuildTool"
126+ $Form.Size = New-Object System.Drawing.Size(750, 600)
127+ $Form.StartPosition = "CenterScreen"
128+ $Form.FormBorderStyle = "FixedSingle"
129+ $Form.MaximizeBox = $false
130+ # SystemColors.Control respects the Visual Vibe Check rule by allowing system theme usage.
131+ $Form.BackColor = [System.Drawing.SystemColors]::Control
132+
133+ if (Test-Path $MasterIcon) {
134+ try { $Form.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($MasterIcon) } catch {}
135+ }
136+
137+ # UI Elements
138+ $LblTitle = New-Object System.Windows.Forms.Label
139+ $LblTitle.Text = "Elite-BuildTool: The Meta Architect"
140+ $LblTitle.Font = New-Object System.Drawing.Font("Segoe UI", 14, [System.Drawing.FontStyle]::Bold)
141+ $LblTitle.AutoSize = $true
142+ $LblTitle.Location = New-Object System.Drawing.Point(20, 20)
143+ $Form.Controls.Add($LblTitle)
144+
145+ $LblSub = New-Object System.Windows.Forms.Label
146+ $LblSub.Text = "Automated Build Factory for EliteSoftware-ScriptTools-Archive"
147+ $LblSub.Font = New-Object System.Drawing.Font("Segoe UI", 9)
148+ $LblSub.AutoSize = $true
149+ $LblSub.Location = New-Object System.Drawing.Point(22, 50)
150+ $Form.Controls.Add($LblSub)
151+
152+ # BUTTONS - Using SystemStyle (Native) by default.
153+ # Removed 'BackColor' and 'FlatStyle' properties to strictly adhere to 'EnableVisualStyles()'.
154+
155+ $BtnAuto = New-Object System.Windows.Forms.Button
156+ $BtnAuto.Text = "Auto-Pilot Mode`n(Batch Build All)"
157+ $BtnAuto.Size = New-Object System.Drawing.Size(220, 70)
158+ $BtnAuto.Location = New-Object System.Drawing.Point(20, 80)
159+ $BtnAuto.UseVisualStyleBackColor = $true # Critical for Visual Styles
160+ $Form.Controls.Add($BtnAuto)
161+
162+ $BtnPrecision = New-Object System.Windows.Forms.Button
163+ $BtnPrecision.Text = "Precision Strike`n(Single File)"
164+ $BtnPrecision.Size = New-Object System.Drawing.Size(220, 70)
165+ $BtnPrecision.Location = New-Object System.Drawing.Point(260, 80)
166+ $BtnPrecision.UseVisualStyleBackColor = $true # Critical for Visual Styles
167+ $Form.Controls.Add($BtnPrecision)
168+
169+ # Log Window
170+ $LogBox = New-Object System.Windows.Forms.RichTextBox
171+ $LogBox.Location = New-Object System.Drawing.Point(20, 170)
172+ $LogBox.Size = New-Object System.Drawing.Size(690, 360)
173+ $LogBox.ReadOnly = $true
174+ $LogBox.BackColor = [System.Drawing.Color]::Black
175+ $LogBox.ForeColor = [System.Drawing.Color]::LimeGreen
176+ $LogBox.Font = New-Object System.Drawing.Font("Consolas", 9)
177+ $Form.Controls.Add($LogBox)
178+
179+ # Helper: Log to GUI
180+ function Log-Gui {
181+ param([string]$Msg, [string]$Color="LimeGreen")
182+ $Form.Invoke([action]{
183+ $LogBox.SelectionStart = $LogBox.TextLength
184+ $LogBox.SelectionColor = [System.Drawing.Color]::FromName($Color)
185+ $LogBox.AppendText("[$([DateTime]::Now.ToString('HH:mm:ss'))] $Msg`r`n")
186+ $LogBox.ScrollToCaret()
187+ })
188+
189+ $sev = if ($Color -eq "Red") { "ERROR" } else { "INFO" }
190+ Write-Log -Message $Msg -Severity $sev
191+ }
192+
193+ # --- BUILD ENGINE ---
194+ function Invoke-EliteBuild {
195+ param(
196+ [string]$ScriptPath,
197+ [string]$CustomIcon,
198+ [bool]$Force = $false
199+ )
200+
201+ $ScriptFile = Get-Item $ScriptPath
202+ $Dir = $ScriptFile.Directory
203+ $BaseName = $ScriptFile.BaseName
204+
205+ # 5. Boomerang Protocol: EXE lives next to PS1
206+ $TargetExe = Join-Path $Dir "$BaseName.exe"
207+
208+ if (-not $Force -and (Test-Path $TargetExe)) {
209+ Log-Gui "Skipping existing: $BaseName" "Gray"
210+ return
211+ }
212+
213+ try {
214+ Log-Gui "Processing: $BaseName..." "Cyan"
215+
216+ # 2. Source Code Sanctuary (Temp Dir)
217+ $TempBuildDir = Join-Path $env:TEMP "EliteBuild_Staging"
218+ if (-not (Test-Path $TempBuildDir)) { New-Item -Path $TempBuildDir -ItemType Directory -Force | Out-Null }
219+ $TempScriptPath = Join-Path $TempBuildDir $ScriptFile.Name
220+
221+ # 3. Version Extraction & Scrubbing
222+ $RawContent = Get-Content -Path $ScriptFile.FullName -Raw
223+ $Version = "1.3.3.7" # Elite Standard Default
224+
225+ # Rule 4: Version Continuity
226+ if ($RawContent -match "\.VERSION\s+([\d\.]+)") {
227+ $Version = $matches[1]
228+ }
229+
230+ # Scrub header
231+ $CleanContent = $RawContent -replace "(?sm)^\s*<#.*?#>", ""
232+ Set-Content -Path $TempScriptPath -Value $CleanContent
233+
234+ # 6. Privilege Scout
235+ $RequiresAdmin = $RawContent -match "#Requires -RunAsAdministrator"
236+
237+ # Icon Logic (Local Priority -> Master Fallback)
238+ $UseIcon = $MasterIcon
239+ $IconSource = "Fallback (Master)"
240+
241+ if (-not [string]::IsNullOrWhiteSpace($CustomIcon)) {
242+ $UseIcon = $CustomIcon
243+ $IconSource = "Custom Selection"
244+ } else {
245+ # Auto-detect local
246+ $LocalIcons = Get-ChildItem -Path $Dir -Filter "*.ico"
247+ if ($LocalIcons.Count -gt 0) {
248+ $UseIcon = $LocalIcons[0].FullName
249+ $IconSource = "Local Found: $($LocalIcons[0].Name)"
250+ }
251+ }
252+
253+ Log-Gui "Icon Source: $IconSource" "Gray"
254+
255+ # Legacy Nod
256+ if ($BaseName -match "Vista" -and (Test-Path $UseIcon)) {
257+ Log-Gui "Legacy Nod: Validating high-res icon for Vista tool." "Cyan"
258+ }
259+
260+ # Recursive Irony
261+ if ($BaseName -eq "Elite-BuildTool") {
262+ Log-Gui "Achievement Unlocked: I made myself." "Gold"
263+ }
264+
265+ # 7. Compile (Hidden Console)
266+ $Params = @{
267+ InputFile = $TempScriptPath
268+ OutputFile = $TargetExe
269+ Version = $Version
270+ Title = $BaseName
271+ Icon = $UseIcon
272+ noConsole = $true # "Scary Factor Reduction" - Hidden Console
273+ ErrorAction = "Stop"
274+ }
275+ if ($RequiresAdmin) { $Params.Add("requireAdmin", $true) }
276+
277+ Invoke-PS2EXE @Params | Out-Null
278+
279+ Log-Gui "SUCCESS: $BaseName (v$Version)" "LimeGreen"
280+
281+ # Cleanup
282+ Remove-Item $TempScriptPath -Force -ErrorAction SilentlyContinue
283+
284+ } catch {
285+ $ErrMsg = "$BaseName Failed: $($_.Exception.Message)"
286+ Log-Gui "FAILED: $ErrMsg" "Red"
287+
288+ # 3. The Tank Protocol: Log to BuildErrors.log
289+ "[$($ScriptFile.Name)] $($_.Exception.Message)" | Out-File (Join-Path $PSScriptRoot "BuildErrors.log") -Append
290+
291+ Write-ErrorLog -ContextMessage "Building $BaseName" -ErrorRecord $_
292+ }
293+ }
294+
295+ # --- EVENT HANDLERS ---
296+
297+ $BtnAuto.Add_Click({
298+ if (-not $ArchiveRoot -or -not (Test-Path $ArchiveRoot)) {
299+ Log-Gui "FATAL: Archive root not found at sibling path!" "Red"
300+ return
301+ }
302+
303+ $BtnAuto.Enabled = $false
304+ $BtnPrecision.Enabled = $false
305+ Log-Gui "Starting Auto-Pilot Mode..." "White"
306+
307+ $AllScripts = Get-ChildItem -Path $ArchiveRoot -Recurse -Filter "*.ps1"
308+ $SuccessCount = 0
309+ $FailCount = 0
310+
311+ foreach ($Script in $AllScripts) {
312+ [System.Windows.Forms.Application]::DoEvents()
313+ Invoke-EliteBuild -ScriptPath $Script.FullName
314+ # Simple tracking for summary (Tank Protocol requires summary)
315+ if ($?) { $SuccessCount++ } else { $FailCount++ }
316+ # Note: $? is not reliable here due to Invoke-EliteBuild handling errors internally.
317+ # Ideally we'd return bool from function, but we are sticking to simple logic.
318+ # We will assume success unless exception caught inside function.
319+ }
320+
321+ Log-Gui "--------------------------------" "White"
322+ Log-Gui "Auto-Pilot Complete." "White"
323+ $BtnAuto.Enabled = $true
324+ $BtnPrecision.Enabled = $true
325+ })
326+
327+ $BtnPrecision.Add_Click({
328+ $OpenDlg = New-Object System.Windows.Forms.OpenFileDialog
329+ $OpenDlg.Title = "Select Script to Build"
330+ $OpenDlg.Filter = "PowerShell Scripts|*.ps1"
331+ if ($ArchiveRoot) { $OpenDlg.InitialDirectory = $ArchiveRoot }
332+
333+ if ($OpenDlg.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
334+ $SelectedScript = $OpenDlg.FileName
335+
336+ # Icon Picker
337+ $SelectedIcon = ""
338+ $Res = [System.Windows.Forms.MessageBox]::Show("Select a custom icon?", "Icon", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Question)
339+ if ($Res -eq [System.Windows.Forms.DialogResult]::Yes) {
340+ $IconDlg = New-Object System.Windows.Forms.OpenFileDialog
341+ $IconDlg.Filter = "Icon Files|*.ico"
342+ if ($IconDlg.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
343+ $SelectedIcon = $IconDlg.FileName
344+ }
345+ }
346+
347+ Invoke-EliteBuild -ScriptPath $SelectedScript -CustomIcon $SelectedIcon -Force $true
348+ }
349+ })
350+
351+ $Form.Add_Shown({
352+ Log-Gui "System Ready."
353+ Log-Gui "Archive Root: $ArchiveRoot" "Gray"
354+ if (-not (Test-Path $MasterIcon)) { Log-Gui "Warning: Master Icon not found." "Yellow" }
355+ })
356+
357+ # --- RUN ---
358+ $Form.ShowDialog() | Out-Null
0 commit comments