# Hard-coded deploy settings. Fill these in before running. $FtpHost = "xTr1m.com" $FtpUser = "xTr1m" $FtpPassword = $null # prompted at runtime $RemoteDir = "/httpdocs/picknplay" $ProjectPath = "..\\GameList.csproj" $Configuration = "Release" $Runtime = "win-x64" $PublishDir = "$env:TEMP\\GameList-publish" $SelfContained = $false $WinScpPath = "C:\\Users\\frank\\AppData\\Local\\Programs\\WinSCP\\WinSCP.com" $RecycleAppPool = $true $AppPoolName = "xTr1m.com(domain)(4.0)(pool)" $WinRmComputer = "xTr1m.com" $WinRmCredentialUser = "win-eisvr3h3qra\\Administrator" $WinRmCredentialPass = $null # prompted at runtime $UseWinRmHttps = $true # set false if using HTTP + TrustedHosts <#! .SYNOPSIS Publish the app and mirror the output to an FTP-deployed IIS site. .DESCRIPTION - Builds with dotnet publish. - Uses WinSCP (ftp) to mirror publish output into $RemoteDir (deletes extraneous remote files). - Optionally recycles the IIS app pool remotely via WinRM (no RDP needed). .PREREQS - WinSCP.com available in PATH or set $WinScpPath. - FTP user must have write/delete rights to $RemoteDir. - WinRM must be enabled for remote app pool recycle (set $RecycleAppPool = $false otherwise). .EXAMPLE pwsh ./scripts/deploy-ftp.ps1 #> Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" function Assert-Tool { param([string]$Name) if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) { throw "Required tool '$Name' not found. Install it or update paths." } } Assert-Tool "dotnet" Assert-Tool $WinScpPath function Read-PlainOrPrompt([string]$Value, [string]$Prompt, [bool]$Secure = $false) { if ($Value) { return $Value } if ($Secure) { $pwd = Read-Host -Prompt $Prompt -AsSecureString $ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd) try { return [Runtime.InteropServices.Marshal]::PtrToStringUni($ptr) } finally { if ($ptr -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr) } } } return Read-Host -Prompt $Prompt } $FtpPassword = Read-PlainOrPrompt $FtpPassword "FTP password" $true $WinRmCredentialPass = Read-PlainOrPrompt $WinRmCredentialPass "WinRM password" $true Write-Host "1) Publishing..." -ForegroundColor Cyan if (Test-Path $PublishDir) { Remove-Item $PublishDir -Recurse -Force -ErrorAction SilentlyContinue } New-Item -ItemType Directory -Force -Path $PublishDir | Out-Null $publishArgs = @("publish", $ProjectPath, "-c", $Configuration, "-r", $Runtime, "-o", $PublishDir) if (-not $SelfContained) { $publishArgs += "--self-contained=false" } dotnet @publishArgs if ($RecycleAppPool) { Write-Host "2) Stopping IIS app pool via WinRM..." -ForegroundColor Cyan $sec = ConvertTo-SecureString $WinRmCredentialPass -AsPlainText -Force $cred = New-Object pscredential($WinRmCredentialUser, $sec) $invokeParams = @{ ComputerName = $WinRmComputer Credential = $cred ScriptBlock = { Import-Module WebAdministration Stop-WebAppPool -Name $using:AppPoolName -ErrorAction SilentlyContinue } } if ($UseWinRmHttps) { $invokeParams["UseSSL"] = $true } try { Invoke-Command @invokeParams } catch { Write-Warning "WinRM stop failed: $($_.Exception.Message)." } } Write-Host "3) Syncing via WinSCP (FTP mirror with delete)..." -ForegroundColor Cyan $tempScript = New-TemporaryFile @" option batch continue option confirm off open ftp://$($FtpUser):$($FtpPassword.Replace('`n','').Replace('`r',''))@$FtpHost lcd $PublishDir cd $RemoteDir synchronize remote . -delete exit "@ | Set-Content -Path $tempScript -Encoding UTF8 & $WinScpPath "/ini=nul" "/script=$tempScript" Remove-Item $tempScript -ErrorAction SilentlyContinue if ($RecycleAppPool) { Write-Host "4) Starting IIS app pool via WinRM..." -ForegroundColor Cyan $sec = ConvertTo-SecureString $WinRmCredentialPass -AsPlainText -Force $cred = New-Object pscredential($WinRmCredentialUser, $sec) $invokeParams = @{ ComputerName = $WinRmComputer Credential = $cred ScriptBlock = { Import-Module WebAdministration Start-WebAppPool -Name $using:AppPoolName } } if ($UseWinRmHttps) { $invokeParams["UseSSL"] = $true } try { Invoke-Command @invokeParams } catch { Write-Warning "WinRM start failed: $($_.Exception.Message)." } } Write-Host "Done." -ForegroundColor Green