2026-08-26 20:03:00 -05:00
# Interactive setup - asks plain questions and writes entity.json so nobody has
# to hand-edit JSON. Called by setup-entity.bat. Safe to re-run any time.
$scriptRoot = Split-Path -Parent $PSCommandPath
$entitiesDir = Join-Path $scriptRoot "Entities"
$winscpDll = Join-Path $scriptRoot "WinSCP\WinSCPnet.dll"
if ( -not ( Test-Path $entitiesDir )) { New-Item -ItemType Directory -Path $entitiesDir | Out-Null }
# -- Asking questions ---------------------------------------------------------
function Read-Answer($question , $default , [ switch ] $AllowBlank ) {
while ( $true ) {
if ( $default ) {
Write-Host " $question " -NoNewline -ForegroundColor White
Write-Host "[ $default ]" -NoNewline -ForegroundColor DarkGray
Write-Host ": " -NoNewline -ForegroundColor White
} else {
Write-Host " ${question} : " -NoNewline -ForegroundColor White
}
$answer = Read-Host
if ([ string ]:: IsNullOrWhiteSpace ( $answer )) {
if ( $default ) { return $default }
if ( $AllowBlank ) { return $null }
Write-Host " (this one is required)" -ForegroundColor Yellow
continue
}
return $answer . Trim ()
}
}
function Read-YesNo($question , $default ) {
$hint = if ( $default -eq "y" ) { "Y/n" } else { "y/N" }
while ( $true ) {
Write-Host " $question " -NoNewline -ForegroundColor White
Write-Host "( $hint )" -NoNewline -ForegroundColor DarkGray
Write-Host ": " -NoNewline -ForegroundColor White
$answer = Read-Host
if ([ string ]:: IsNullOrWhiteSpace ( $answer )) { $answer = $default }
switch ( $answer . Trim (). ToLower ()) {
"y" { return $true }
"yes" { return $true }
"n" { return $false }
"no" { return $false }
}
Write-Host " (please answer y or n)" -ForegroundColor Yellow
}
}
function Read-Choice($question , $options , $default ) {
Write-Host ""
Write-Host $question -ForegroundColor White
for ( $i = 0 ; $i -lt $options . Count ; $i ++) {
Write-Host ( " {0}. {1}" -f ( $i + 1 ), $options [ $i ])
}
while ( $true ) {
Write-Host "Choose 1- $( $options . Count ) " -NoNewline -ForegroundColor White
Write-Host "[ $default ]" -NoNewline -ForegroundColor DarkGray
Write-Host ": " -NoNewline -ForegroundColor White
$answer = Read-Host
if ([ string ]:: IsNullOrWhiteSpace ( $answer )) { $answer = [ string ] $default }
$n = 0
if ([ int ]:: TryParse (([ string ] $answer ). Trim (), [ ref ] $n ) -and $n -ge 1 -and $n -le $options . Count ) {
return $n
}
Write-Host " (type a number between 1 and $( $options . Count ) )" -ForegroundColor Yellow
}
}
function Write-Header($text ) {
Write-Host ""
Write-Host ( "=" * 64 ) -ForegroundColor Cyan
Write-Host " $text " -ForegroundColor Cyan
Write-Host ( "=" * 64 ) -ForegroundColor Cyan
}
function Write-Section($text ) {
Write-Host ""
Write-Host "--- $text " -NoNewline -ForegroundColor Cyan
Write-Host ( "-" * [ Math ]:: Max ( 1 , ( 58 - $text . Length ))) -ForegroundColor Cyan
}
# -- Config file read/write ---------------------------------------------------
function Get-EntityNames {
if ( -not ( Test-Path $entitiesDir )) { return @ () }
return @ ( Get-ChildItem -Path $entitiesDir -Directory |
Where-Object { $_ . Name -ne "EXAMPLE" } |
ForEach-Object { $_ . Name })
}
function Save-EntityConfig($entityName , $config ) {
$dir = Join-Path $entitiesDir $entityName
if ( -not ( Test-Path $dir )) { New-Item -ItemType Directory -Path $dir | Out-Null }
$file = Join-Path $dir "entity.json"
$config | ConvertTo-Json -Depth 10 | Set-Content -Path $file -Encoding UTF8
return $file
}
function Get-EntityConfig($entityName ) {
$file = Join-Path ( Join-Path $entitiesDir $entityName ) "entity.json"
if ( -not ( Test-Path $file )) { return $null }
return Get-Content $file -Raw | ConvertFrom-Json
}
function Copy-RunBat($entityName ) {
$source = Join-Path $scriptRoot "run.bat"
$target = Join-Path ( Join-Path $entitiesDir $entityName ) "run.bat"
if (( Test-Path $source ) -and -not ( Test-Path $target )) {
Copy-Item -Path $source -Destination $target
}
}
# -- Asking about one server --------------------------------------------------
# Returns a hashtable of connection settings, or $null if the user backs out.
function Read-ServerDetails($label , $existing ) {
$defaultHost = $null
$defaultUser = $null
$defaultProto = 1
if ( $existing -and $existing . host ) {
$defaultHost = (([ string ] $existing . host ) -replace '^\w+://' , '' ). Split ( '/' )[ 0 ]. Trim ()
$defaultUser = $existing . username
switch ( Get-ConnProtocol $existing "sftp" ) {
"ftps" { $defaultProto = 2 }
"ftp" { $defaultProto = 3 }
}
}
Write-Host ""
Write-Host "Server address for $label " -ForegroundColor White
Write-Host " Just the name - no sftp:// or ftp:// in front." -ForegroundColor DarkGray
Write-Host " Example: sft.polluxsystems.com" -ForegroundColor DarkGray
$serverHost = Read-Answer "Server address" $defaultHost
# Strip a pasted scheme/path so it can't break the connection later.
$serverHost = ( $serverHost -replace '^\w+://' , '' ). Split ( '/' )[ 0 ]. Trim ()
$protoChoice = Read-Choice "How does $serverHost receive files?" @ (
"SFTP - secure, port 22 (most common)" ,
"FTPS - secure FTP, port 21" ,
"FTP - plain, no encryption, port 21"
) $defaultProto
$protocol = @ ( "sftp" , "ftps" , "ftp" )[ $protoChoice - 1 ]
Write-Host ""
$username = Read-Answer "Username" $defaultUser
$password = $null
if ( $existing -and $existing . password ) {
Write-Host ""
Write-Host "A password is already saved for this server." -ForegroundColor DarkGray
if ( Read-YesNo "Keep the saved password?" "y" ) {
$password = $existing . password
}
}
if ( -not $password ) {
$password = Read-Answer "Password" $null
}
return @ {
host = $serverHost
protocol = $protocol
username = $username
password = $password
}
}
function Read-RemotePath($what , $default ) {
Write-Host ""
Write-Host "Where do $what go on the server?" -ForegroundColor White
Write-Host " Type {practice} where the practice name belongs and it gets" -ForegroundColor DarkGray
Write-Host " filled in automatically for each one - so one line covers all." -ForegroundColor DarkGray
Write-Host " Example: /home/clients/CAMBS/{practice}" -ForegroundColor DarkGray
return Read-Answer "Folder path" $default
}
# -- New / edit entity --------------------------------------------------------
function New-Entity {
Write-Header "Set up a new entity"
Write-Host ""
Write-Host "The entity name is the folder name you use for this group of" -ForegroundColor DarkGray
Write-Host "practices - for example CAMBS, RMI, INLAND." -ForegroundColor DarkGray
$entityName = $null
while ( -not $entityName ) {
$candidate = Read-Answer "Entity name" $null
if ( $candidate . IndexOfAny ([ System.IO.Path ]:: GetInvalidFileNameChars ()) -ge 0 ) {
Write-Host " A folder name cannot contain \ / : * ? "" < > | - try again." -ForegroundColor Yellow
continue
}
$entityName = $candidate
}
$entityDir = Join-Path $entitiesDir $entityName
if ( Test-Path ( Join-Path $entityDir "entity.json" )) {
Write-Host ""
Write-Host " $entityName is already set up." -ForegroundColor Yellow
if ( -not ( Read-YesNo "Start over and replace its settings?" "n" )) { return }
}
Write-Section "The daily upload"
Write-Host "These are the dated folders (like 20260826) full of scanned images." -ForegroundColor DarkGray
$daily = Read-ServerDetails "the daily files" $null
$tiffPath = Read-RemotePath "the daily image files" $null
Write-Host ""
$pdfPath = $null
Write-Host "Some entities get PT STMT files mixed into the same dated folder," -ForegroundColor DarkGray
Write-Host "and those go to a different folder on the server." -ForegroundColor DarkGray
2026-08-26 20:27:03 -05:00
if ( Read-YesNo "Do PT STMT files show up in the dated folders for ${entityName} ?" "n" ) {
2026-08-26 20:03:00 -05:00
$pdfPath = Read-RemotePath "the PT STMT files" $null
}
Write-Section "Patient files"
Write-Host "These come from Patient\Export\PT STMT_<date>\ - the folders the" -ForegroundColor DarkGray
Write-Host "rename script creates. Many entities do not use this at all." -ForegroundColor DarkGray
$patient = $null
$patientPath = $null
if ( Read-YesNo "Does $entityName send patient files too?" "n" ) {
$samePlace = Read-Choice "Which server do the patient files go to?" @ (
"The same server as the daily files ( $( $daily . host ) )" ,
"A different server"
) 1
if ( $samePlace -eq 1 ) {
$patient = @ {
host = $daily . host
protocol = $daily . protocol
username = $daily . username
password = $daily . password
}
} else {
$patient = Read-ServerDetails "the patient files" $null
}
$patientPath = Read-RemotePath "the patient .txt/.tif files" $null
}
$config = New-ConfigObject $daily $tiffPath $pdfPath $patient $patientPath
$file = Save-EntityConfig $entityName $config
Copy-RunBat $entityName
Write-Host ""
Write-Host "Saved $file " -ForegroundColor Green
Add-Practices $entityName
Write-Host ""
if ( Read-YesNo "Test the connection now?" "y" ) { Test-Entity $entityName }
}
function New-ConfigObject($daily , $tiffPath , $pdfPath , $patient , $patientPath ) {
$workflow = if ( $patient ) { "insurance+patient" } else { "insurance" }
$ftps = [ ordered ] @ {
host = $daily . host
protocol = $daily . protocol
port = $null
username = $daily . username
password = $daily . password
tiff_path = $tiffPath
pdf_path = $pdfPath
}
$sftp = [ ordered ] @ {
host = $null
protocol = $null
port = $null
username = $null
password = $null
patient_path = $null
}
if ( $patient ) {
$sftp . host = $patient . host
$sftp . protocol = $patient . protocol
$sftp . username = $patient . username
$sftp . password = $patient . password
$sftp . patient_path = $patientPath
}
return [ PSCustomObject][ordered ] @ {
"_note" = "Written by setup-entity.bat - run it again to change anything. The 'ftps' section is the daily upload (it can be SFTP too - see protocol); the 'sftp' section is the patient files."
workflow = $workflow
ftps = [ PSCustomObject ] $ftps
sftp = [ PSCustomObject ] $sftp
}
}
function Add-Practices($entityName ) {
$export1 = Join-Path ( Join-Path $entitiesDir $entityName ) "Export1"
if ( -not ( Test-Path $export1 )) { New-Item -ItemType Directory -Path $export1 | Out-Null }
$existing = @ ( Get-ChildItem -Path $export1 -Directory | ForEach-Object { $_ . Name })
Write-Section "Practices under $entityName "
if ( $existing . Count -gt 0 ) {
Write-Host "Already there: $( $existing -join ', ' ) " -ForegroundColor Gray
Write-Host ""
if ( -not ( Read-YesNo "Add more practice folders?" "n" )) { return }
} else {
Write-Host "Type each practice name and press Enter." -ForegroundColor DarkGray
Write-Host "Press Enter on an empty line when you are done." -ForegroundColor DarkGray
}
while ( $true ) {
$name = Read-Answer "Practice name (blank to finish)" $null -AllowBlank
if ( -not $name ) { break }
if ( $name . IndexOfAny ([ System.IO.Path ]:: GetInvalidFileNameChars ()) -ge 0 ) {
Write-Host " A folder name cannot contain \ / : * ? "" < > | - try again." -ForegroundColor Yellow
continue
}
$dir = Join-Path $export1 $name
if ( Test-Path $dir ) {
Write-Host " $name already exists - skipped." -ForegroundColor Gray
continue
}
New-Item -ItemType Directory -Path $dir | Out-Null
New-Item -ItemType Directory -Path ( Join-Path $dir "Archive sent to FTP" ) | Out-Null
New-Item -ItemType Directory -Path ( Join-Path $dir "Patient\Export\Archive Sent to FTP" ) -Force | Out-Null
Write-Host " Created $name " -ForegroundColor Green
}
}
function Edit-Entity($entityName ) {
$config = Get-EntityConfig $entityName
if ( -not $config ) {
Write-Host "No entity.json found for $entityName ." -ForegroundColor Red
return
}
# A hand-written entity.json may be missing whole sections.
foreach ( $section in @ ( "ftps" , "sftp" )) {
if ( -not $config . $section ) {
Set-Field $config $section ([ PSCustomObject ] @ {})
}
}
while ( $true ) {
Write-Header " $entityName - current settings"
Show-Settings $config
$choice = Read-Choice "What do you want to change?" @ (
"The daily-upload server (address, protocol, login)" ,
"Where the daily image files go on the server" ,
"Where PT STMT files from the dated folder go" ,
"Patient files (server and folder)" ,
"Add practice folders" ,
"Nothing - save and go back"
) 6
switch ( $choice ) {
1 {
$d = Read-ServerDetails "the daily files" $config . ftps
Set-Field $config . ftps "host" $d . host
Set-Field $config . ftps "protocol" $d . protocol
Set-Field $config . ftps "username" $d . username
Set-Field $config . ftps "password" $d . password
}
2 {
Set-Field $config . ftps "tiff_path" ( Read-RemotePath "the daily image files" $config . ftps . tiff_path )
}
3 {
Write-Host ""
if ( Read-YesNo "Do PT STMT files show up in the dated folders?" "n" ) {
Set-Field $config . ftps "pdf_path" ( Read-RemotePath "the PT STMT files" $config . ftps . pdf_path )
} else {
Set-Field $config . ftps "pdf_path" $null
Write-Host " PT STMT files from the dated folder will be ignored." -ForegroundColor Gray
}
}
4 {
Write-Host ""
if ( Read-YesNo "Does $entityName send patient files?" "n" ) {
$same = Read-Choice "Which server do the patient files go to?" @ (
"The same server as the daily files ( $( $config . ftps . host ) )" ,
"A different server"
) 1
if ( $same -eq 1 ) {
Set-Field $config . sftp "host" $config . ftps . host
Set-Field $config . sftp "protocol" $config . ftps . protocol
Set-Field $config . sftp "username" $config . ftps . username
Set-Field $config . sftp "password" $config . ftps . password
} else {
$p = Read-ServerDetails "the patient files" $config . sftp
Set-Field $config . sftp "host" $p . host
Set-Field $config . sftp "protocol" $p . protocol
Set-Field $config . sftp "username" $p . username
Set-Field $config . sftp "password" $p . password
}
Set-Field $config . sftp "patient_path" ( Read-RemotePath "the patient .txt/.tif files" $config . sftp . patient_path )
Set-Field $config "workflow" "insurance+patient"
} else {
Set-Field $config "workflow" "insurance"
Write-Host " Patient files turned off for $entityName ." -ForegroundColor Gray
}
}
5 { Add-Practices $entityName }
6 {
$file = Save-EntityConfig $entityName $config
Copy-RunBat $entityName
Write-Host ""
Write-Host "Saved $file " -ForegroundColor Green
return
}
}
Save-EntityConfig $entityName $config | Out-Null
}
}
function Set-Field($object , $name , $value ) {
$object | Add-Member -NotePropertyName $name -NotePropertyValue $value -Force
}
function Show-Settings($config ) {
Write-Host ""
Write-Host " Daily upload" -ForegroundColor White
2026-08-26 20:27:03 -05:00
Write-Host " Server : $( Show-Value $config . ftps . host ) over $( Show-Protocol $config . ftps 'ftp' ) "
2026-08-26 20:03:00 -05:00
Write-Host " Login : $( Show-Value $config . ftps . username ) / $( Show-Password $config . ftps . password ) "
Write-Host " Images to : $( Show-Value $config . ftps . tiff_path ) "
Write-Host " PT STMT to: $( Show-Value $config . ftps . pdf_path ) "
Write-Host ""
Write-Host " Patient files" -ForegroundColor White
if ( $config . workflow -eq "insurance+patient" ) {
2026-08-26 20:27:03 -05:00
Write-Host " Server : $( Show-Value $config . sftp . host ) over $( Show-Protocol $config . sftp 'sftp' ) "
2026-08-26 20:03:00 -05:00
Write-Host " Login : $( Show-Value $config . sftp . username ) / $( Show-Password $config . sftp . password ) "
Write-Host " Files to : $( Show-Value $config . sftp . patient_path ) "
} else {
Write-Host " Not used for this entity." -ForegroundColor Gray
}
}
2026-08-26 20:27:03 -05:00
# Reports the protocol the upload will actually use, so a legacy config that
# only carries an "ftps://" prefix on the host doesn't read as unset.
function Show-Protocol($conn , $fallback ) {
if ([ string ]:: IsNullOrWhiteSpace ([ string ] $conn . host )) { return "(not set)" }
$protocol = ( Get-ConnProtocol $conn $fallback ). ToUpper ()
if ( $conn . protocol ) { return $protocol }
return " $protocol (assumed)"
}
2026-08-26 20:03:00 -05:00
function Show-Value($value ) {
if ([ string ]:: IsNullOrWhiteSpace ([ string ] $value )) { return "(not set)" }
return [ string ] $value
}
function Show-Password($value ) {
if ([ string ]:: IsNullOrWhiteSpace ([ string ] $value )) { return "(not set)" }
return "*" * ([ string ] $value ). Length
}
# -- Connection test ----------------------------------------------------------
# Works out the protocol exactly the way engine.ps1 does, so a passing test
# here means the real run connects the same way.
function Get-ConnProtocol($conn , $fallback ) {
if ( $conn . protocol ) {
$p = ([ string ] $conn . protocol ). ToLower (). Trim ()
if ( $p -in @ ( "sftp" , "ftps" , "ftp" )) { return $p }
}
if (([ string ] $conn . host ) -imatch '^(\w+)://' ) {
$scheme = $Matches [ 1 ]. ToLower ()
if ( $scheme -in @ ( "sftp" , "ftps" , "ftp" )) { return $scheme }
}
if ( $conn . tls -eq $true ) { return "ftps" }
return $fallback
}
function Get-SessionOptions($conn , $fallback ) {
$opts = New-Object WinSCP . SessionOptions
# Older configs kept the protocol as an "sftp://" prefix on the host.
$opts . HostName = (([ string ] $conn . host ) -replace '^\w+://' , '' ). Split ( '/' )[ 0 ]. Trim ()
$opts . UserName = $conn . username
$opts . Password = $conn . password
$protocol = Get-ConnProtocol $conn $fallback
if ( $protocol -eq "sftp" ) {
$opts . Protocol = [ WinSCP.Protocol ]:: Sftp
$opts . PortNumber = if ( $conn . port ) { [ int ] $conn . port } else { 22 }
$opts . GiveUpSecurityAndAcceptAnySshHostKey = $true
} else {
$opts . Protocol = [ WinSCP.Protocol ]:: Ftp
$opts . PortNumber = if ( $conn . port ) { [ int ] $conn . port } else { 21 }
if ( $protocol -eq "ftps" ) {
$opts . FtpSecure = [ WinSCP.FtpSecure ]:: Explicit
$opts . GiveUpSecurityAndAcceptAnyTlsHostCertificate = $true
} else {
$opts . FtpSecure = [ WinSCP.FtpSecure ]:: None
}
}
return $opts
}
function Test-ServerConnection($label , $conn , $pathTemplate , $practices , $fallback ) {
Write-Host ""
Write-Host " $label " -ForegroundColor White
if ([ string ]:: IsNullOrWhiteSpace ([ string ] $conn . host )) {
Write-Host " Not set up - nothing to test." -ForegroundColor Gray
return
}
$opts = Get-SessionOptions $conn $fallback
$protocol = ( Get-ConnProtocol $conn $fallback ). ToUpper ()
Write-Host " Connecting to $( $opts . HostName ) over $protocol as $( $conn . username ) ... " -NoNewline
$session = New-Object WinSCP . Session
try {
$session . Open ( $opts )
Write-Host "OK" -ForegroundColor Green
} catch {
Write-Host "FAILED" -ForegroundColor Red
Write-Host " $( $_ . Exception . Message ) " -ForegroundColor Red
Write-Host ""
Write-Host " $( Get-ConnectionHint $_ . Exception . Message ) " -ForegroundColor Yellow
$session . Dispose ()
return
}
if ([ string ]:: IsNullOrWhiteSpace ([ string ] $pathTemplate )) {
Write-Host " No folder path set yet - skipping the folder check." -ForegroundColor Gray
$session . Dispose ()
return
}
try {
foreach ( $practice in $practices ) {
$remote = $pathTemplate -replace '\{practice\}' , $practice
Write-Host " $remote ... " -NoNewline
if ( $session . FileExists ( $remote )) {
Write-Host "found" -ForegroundColor Green
} else {
Write-Host "NOT THERE" -ForegroundColor Red
}
}
} catch {
Write-Host "could not check - $( $_ . Exception . Message ) " -ForegroundColor Yellow
} finally {
$session . Dispose ()
}
}
function Get-ConnectionHint($message ) {
if ( $message -imatch "cannot connect to an SFTP server using an FTP" ) {
return "This server wants SFTP. Run setup again and pick SFTP for this server."
}
if ( $message -imatch "cannot connect to an FTP server using an SFTP|expected SSH" ) {
return "This server wants FTP or FTPS. Run setup again and pick FTPS for this server."
}
if ( $message -imatch "authentication|password|login incorrect|530" ) {
return "The username or password was rejected. Run setup again and retype the login."
}
if ( $message -imatch "host does not exist|no such host|could not resolve" ) {
return "That server address could not be found. Check it for a typo."
}
if ( $message -imatch "timed out|timeout|refused" ) {
return "No answer from the server. Check the address, or ask IT whether the firewall allows it."
}
return "Write down this message - it says what the server objected to."
}
function Test-Entity($entityName ) {
Write-Header "Testing $entityName "
if ( -not ( Test-Path $winscpDll )) {
Write-Host "WinSCP is not installed yet - run setup.bat first." -ForegroundColor Red
return
}
Get-ChildItem -Path ( Join-Path $scriptRoot "WinSCP" ) -Recurse -File |
Unblock-File -ErrorAction SilentlyContinue
try {
Add-Type -Path $winscpDll
} catch {
Write-Host "Could not load WinSCP - $( $_ . Exception . Message ) " -ForegroundColor Red
Write-Host "Try deleting the WinSCP folder and running setup.bat again." -ForegroundColor Yellow
return
}
$config = Get-EntityConfig $entityName
if ( -not $config ) {
Write-Host "No entity.json found for $entityName ." -ForegroundColor Red
return
}
$export1 = Join-Path ( Join-Path $entitiesDir $entityName ) "Export1"
$practices = @ ()
if ( Test-Path $export1 ) {
$practices = @ ( Get-ChildItem -Path $export1 -Directory | ForEach-Object { $_ . Name })
}
if ( $practices . Count -eq 0 ) {
Write-Host "No practice folders yet - testing the login only." -ForegroundColor Gray
}
Test-ServerConnection "Daily upload" $config . ftps $config . ftps . tiff_path $practices "ftp"
if ( $config . ftps . pdf_path ) {
Test-ServerConnection "PT STMT folders" $config . ftps $config . ftps . pdf_path $practices "ftp"
}
if ( $config . workflow -eq "insurance+patient" ) {
Test-ServerConnection "Patient files" $config . sftp $config . sftp . patient_path $practices "sftp"
}
Write-Host ""
Write-Host "A folder marked NOT THERE means the upload will fail for that" -ForegroundColor Yellow
Write-Host "practice. Either the path is wrong, or the partner has not made" -ForegroundColor Yellow
Write-Host "the folder yet - check the path first, then ask them." -ForegroundColor Yellow
}
# -- Main menu ----------------------------------------------------------------
function Select-Entity($purpose ) {
$names = Get-EntityNames
if ( $names . Count -eq 0 ) {
Write-Host ""
Write-Host "No entities set up yet - pick 'Set up a new entity' first." -ForegroundColor Yellow
return $null
}
$choice = Read-Choice "Which entity do you want to $purpose " $names 1
return $names [ $choice - 1 ]
}
Write-Header "Melissa Uploader - Setup"
Write-Host ""
Write-Host "This asks a few questions and writes the settings files for you." -ForegroundColor Gray
Write-Host "You never have to open one by hand." -ForegroundColor Gray
while ( $true ) {
$names = Get-EntityNames
Write-Host ""
if ( $names . Count -gt 0 ) {
Write-Host "Entities set up so far: $( $names -join ', ' ) " -ForegroundColor Gray
} else {
Write-Host "No entities set up yet." -ForegroundColor Gray
}
$choice = Read-Choice "What do you want to do?" @ (
"Set up a new entity" ,
"Change an entity's settings" ,
"Test an entity's connection and folders" ,
"Quit"
) 4
switch ( $choice ) {
1 { New-Entity }
2 { $name = Select-Entity "change" ; if ( $name ) { Edit-Entity $name } }
3 { $name = Select-Entity "test" ; if ( $name ) { Test-Entity $name } }
4 {
Write-Host ""
Write-Host "Done. Double-click run-all.bat when you are ready to upload." -ForegroundColor Green
Write-Host ""
exit 0
}
}
}