Initial commit: Organized PowerShell scripts for ShopDB asset collection
Structure: - asset-collection/: Local PC data collection scripts - remote-execution/: WinRM remote execution scripts - setup-utilities/: Configuration and testing utilities - registry-backup/: GE registry backup scripts - winrm-https/: WinRM HTTPS certificate setup - docs/: Complete documentation Each folder includes a README with detailed documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
559
remote-execution/Invoke-RemoteAssetCollection-HTTPS.ps1
Normal file
559
remote-execution/Invoke-RemoteAssetCollection-HTTPS.ps1
Normal file
@@ -0,0 +1,559 @@
|
||||
#Requires -RunAsAdministrator
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remotely executes asset collection script on shopfloor PCs using WinRM over HTTPS.
|
||||
|
||||
.DESCRIPTION
|
||||
This script uses WinRM HTTPS to securely execute the Update-PC-CompleteAsset.ps1 script
|
||||
on multiple shopfloor PCs. It handles:
|
||||
1. Secure HTTPS connections using wildcard certificates
|
||||
2. Automatic FQDN resolution from hostnames
|
||||
3. Credential management for remote connections
|
||||
4. Parallel execution across multiple PCs
|
||||
5. Error handling and logging for remote operations
|
||||
6. Collection of results from each remote PC
|
||||
|
||||
.PARAMETER HostnameList
|
||||
Array of computer hostnames (without domain suffix).
|
||||
|
||||
.PARAMETER HostnameListFile
|
||||
Path to a text file containing hostnames (one per line, without domain suffix).
|
||||
|
||||
.PARAMETER Domain
|
||||
Domain suffix for FQDNs (e.g., "logon.ds.ge.com").
|
||||
Will construct FQDNs as: hostname.domain
|
||||
|
||||
.PARAMETER Credential
|
||||
PSCredential object for authenticating to remote computers.
|
||||
If not provided, will prompt for credentials.
|
||||
|
||||
.PARAMETER MaxConcurrent
|
||||
Maximum number of concurrent remote sessions (default: 5).
|
||||
|
||||
.PARAMETER Port
|
||||
HTTPS port for WinRM (default: 5986).
|
||||
|
||||
.PARAMETER ProxyURL
|
||||
URL for the warranty proxy server (passed to remote script).
|
||||
|
||||
.PARAMETER DashboardURL
|
||||
URL for the dashboard API (passed to remote script).
|
||||
|
||||
.PARAMETER SkipWarranty
|
||||
Skip warranty lookups on remote PCs (passed to remote script).
|
||||
|
||||
.PARAMETER LogPath
|
||||
Path for log files (default: .\logs\remote-collection-https.log).
|
||||
|
||||
.PARAMETER TestConnections
|
||||
Test remote HTTPS connections without running the full collection.
|
||||
|
||||
.PARAMETER ScriptPath
|
||||
Path to the Update-PC-CompleteAsset.ps1 script on remote computers.
|
||||
Default: C:\Scripts\Update-PC-CompleteAsset.ps1
|
||||
|
||||
.PARAMETER SkipCertificateCheck
|
||||
Skip SSL certificate validation (not recommended for production).
|
||||
|
||||
.EXAMPLE
|
||||
# Collect from specific hostnames
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameList @("PC001", "PC002") -Domain "logon.ds.ge.com"
|
||||
|
||||
.EXAMPLE
|
||||
# Collect from hostnames in file
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameListFile ".\shopfloor-hostnames.txt" -Domain "logon.ds.ge.com"
|
||||
|
||||
.EXAMPLE
|
||||
# Test HTTPS connections only
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameList @("PC001") -Domain "logon.ds.ge.com" -TestConnections
|
||||
|
||||
.EXAMPLE
|
||||
# Use stored credentials
|
||||
$cred = Get-Credential
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameListFile ".\shopfloor-hostnames.txt" `
|
||||
-Domain "logon.ds.ge.com" -Credential $cred
|
||||
|
||||
.NOTES
|
||||
Author: System Administrator
|
||||
Date: 2025-10-17
|
||||
Version: 1.0
|
||||
|
||||
Prerequisites:
|
||||
1. WinRM HTTPS must be configured on target computers (use Setup-WinRM-HTTPS.ps1)
|
||||
2. Wildcard certificate installed on target computers
|
||||
3. PowerShell 5.1 or later
|
||||
4. Update-PC-CompleteAsset.ps1 must be present on target computers
|
||||
5. Credentials with admin rights on target computers
|
||||
6. Network connectivity to target computers on port 5986
|
||||
|
||||
Advantages over HTTP WinRM:
|
||||
- Encrypted traffic (credentials and data)
|
||||
- No TrustedHosts configuration required
|
||||
- Better security posture for production environments
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string[]]$HostnameList = @(),
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$HostnameListFile,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Domain,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[PSCredential]$Credential,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]$MaxConcurrent = 5,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]$Port = 5986,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ProxyURL = "http://10.48.130.158/vendor-api-proxy.php",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$DashboardURL = "https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$SkipWarranty = $true,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$LogPath = ".\logs\remote-collection-https.log",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$TestConnections = $false,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ScriptPath = "C:\Scripts\Update-PC-CompleteAsset.ps1",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$SkipCertificateCheck = $false
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# SSL/TLS Certificate Bypass for HTTPS connections
|
||||
# =============================================================================
|
||||
try {
|
||||
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type) {
|
||||
Add-Type @"
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
public class TrustAllCertsPolicy : ICertificatePolicy {
|
||||
public bool CheckValidationResult(
|
||||
ServicePoint srvPoint, X509Certificate certificate,
|
||||
WebRequest request, int certificateProblem) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
"@
|
||||
}
|
||||
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
||||
} catch { }
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
# Initialize logging
|
||||
function Initialize-Logging {
|
||||
param([string]$LogPath)
|
||||
|
||||
$logDir = Split-Path $LogPath -Parent
|
||||
if (-not (Test-Path $logDir)) {
|
||||
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Add-Content -Path $LogPath -Value "[$timestamp] Remote asset collection (HTTPS) started"
|
||||
}
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message, [string]$LogPath, [string]$Level = "INFO")
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] $Message"
|
||||
|
||||
Add-Content -Path $LogPath -Value $logEntry
|
||||
|
||||
switch ($Level) {
|
||||
"ERROR" { Write-Host $logEntry -ForegroundColor Red }
|
||||
"WARN" { Write-Host $logEntry -ForegroundColor Yellow }
|
||||
"SUCCESS" { Write-Host $logEntry -ForegroundColor Green }
|
||||
default { Write-Host $logEntry -ForegroundColor White }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ComputerTargets {
|
||||
param([string[]]$HostnameList, [string]$HostnameListFile, [string]$Domain)
|
||||
|
||||
$hostnames = @()
|
||||
|
||||
# Add hostnames from direct list
|
||||
if ($HostnameList.Count -gt 0) {
|
||||
$hostnames += $HostnameList
|
||||
}
|
||||
|
||||
# Add hostnames from file
|
||||
if (-not [string]::IsNullOrEmpty($HostnameListFile)) {
|
||||
if (Test-Path $HostnameListFile) {
|
||||
$fileHostnames = Get-Content $HostnameListFile |
|
||||
Where-Object { $_.Trim() -ne "" -and -not $_.StartsWith("#") } |
|
||||
ForEach-Object { $_.Trim() }
|
||||
$hostnames += $fileHostnames
|
||||
} else {
|
||||
Write-Log "Hostname list file not found: $HostnameListFile" $LogPath "ERROR"
|
||||
}
|
||||
}
|
||||
|
||||
# Remove duplicates and construct FQDNs
|
||||
$fqdns = $hostnames |
|
||||
Sort-Object -Unique |
|
||||
ForEach-Object {
|
||||
$hostname = $_.Trim()
|
||||
# Remove domain if already present
|
||||
if ($hostname -like "*.$Domain") {
|
||||
$hostname
|
||||
} else {
|
||||
"$hostname.$Domain"
|
||||
}
|
||||
}
|
||||
|
||||
return $fqdns
|
||||
}
|
||||
|
||||
function Resolve-ComputerIP {
|
||||
param([string]$FQDN)
|
||||
|
||||
try {
|
||||
$result = Resolve-DnsName -Name $FQDN -Type A -ErrorAction Stop
|
||||
if ($result -and $result[0].IPAddress) {
|
||||
return $result[0].IPAddress
|
||||
}
|
||||
return $null
|
||||
}
|
||||
catch {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Test-WinRMHTTPSConnection {
|
||||
param([string]$ComputerName, [PSCredential]$Credential, [int]$Port, [bool]$SkipCertCheck)
|
||||
|
||||
try {
|
||||
$sessionOptions = New-PSSessionOption -SkipCACheck:$SkipCertCheck -SkipCNCheck:$SkipCertCheck
|
||||
|
||||
$session = New-PSSession -ComputerName $ComputerName `
|
||||
-Credential $Credential `
|
||||
-UseSSL `
|
||||
-Port $Port `
|
||||
-SessionOption $sessionOptions `
|
||||
-ErrorAction Stop
|
||||
|
||||
Remove-PSSession $session
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Test-RemoteScriptExists {
|
||||
param([string]$ComputerName, [PSCredential]$Credential, [string]$ScriptPath, [int]$Port, [bool]$SkipCertCheck)
|
||||
|
||||
try {
|
||||
$sessionOptions = New-PSSessionOption -SkipCACheck:$SkipCertCheck -SkipCNCheck:$SkipCertCheck
|
||||
|
||||
$result = Invoke-Command -ComputerName $ComputerName `
|
||||
-Credential $Credential `
|
||||
-UseSSL `
|
||||
-Port $Port `
|
||||
-SessionOption $sessionOptions `
|
||||
-ScriptBlock {
|
||||
param($Path)
|
||||
Test-Path $Path
|
||||
} -ArgumentList $ScriptPath
|
||||
|
||||
return $result
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-RemoteAssetScript {
|
||||
param(
|
||||
[string]$ComputerName,
|
||||
[PSCredential]$Credential,
|
||||
[string]$ScriptPath,
|
||||
[string]$ProxyURL,
|
||||
[string]$DashboardURL,
|
||||
[bool]$SkipWarranty,
|
||||
[int]$Port,
|
||||
[bool]$SkipCertCheck,
|
||||
[string]$LogPath
|
||||
)
|
||||
|
||||
try {
|
||||
Write-Log "Starting asset collection on $ComputerName (HTTPS)" $LogPath "INFO"
|
||||
|
||||
$sessionOptions = New-PSSessionOption -SkipCACheck:$SkipCertCheck -SkipCNCheck:$SkipCertCheck
|
||||
|
||||
# Execute the script remotely
|
||||
$result = Invoke-Command -ComputerName $ComputerName `
|
||||
-Credential $Credential `
|
||||
-UseSSL `
|
||||
-Port $Port `
|
||||
-SessionOption $sessionOptions `
|
||||
-ScriptBlock {
|
||||
param($ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty)
|
||||
|
||||
# Change to script directory
|
||||
$scriptDir = Split-Path $ScriptPath -Parent
|
||||
Set-Location $scriptDir
|
||||
|
||||
# Build parameters
|
||||
$params = @{
|
||||
ProxyURL = $ProxyURL
|
||||
DashboardURL = $DashboardURL
|
||||
}
|
||||
|
||||
if ($SkipWarranty) {
|
||||
$params.SkipWarranty = $true
|
||||
}
|
||||
|
||||
# Execute the script and capture output
|
||||
try {
|
||||
& $ScriptPath @params
|
||||
return @{
|
||||
Success = $true
|
||||
Output = "Script completed successfully"
|
||||
Error = $null
|
||||
}
|
||||
}
|
||||
catch {
|
||||
return @{
|
||||
Success = $false
|
||||
Output = $null
|
||||
Error = $_.Exception.Message
|
||||
}
|
||||
}
|
||||
} -ArgumentList $ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty
|
||||
|
||||
if ($result.Success) {
|
||||
Write-Log "Asset collection completed successfully on $ComputerName" $LogPath "SUCCESS"
|
||||
return @{ Success = $true; Computer = $ComputerName; Message = $result.Output }
|
||||
} else {
|
||||
Write-Log "Asset collection failed on $ComputerName: $($result.Error)" $LogPath "ERROR"
|
||||
return @{ Success = $false; Computer = $ComputerName; Message = $result.Error }
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$errorMsg = "Failed to execute on $ComputerName: $($_.Exception.Message)"
|
||||
Write-Log $errorMsg $LogPath "ERROR"
|
||||
return @{ Success = $false; Computer = $ComputerName; Message = $errorMsg }
|
||||
}
|
||||
}
|
||||
|
||||
function Show-SetupInstructions {
|
||||
param([string]$Domain)
|
||||
|
||||
Write-Host "`n=== WinRM HTTPS Setup Instructions ===" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "On each target computer, run the Setup-WinRM-HTTPS.ps1 script:" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host " # With certificate PFX file:" -ForegroundColor Gray
|
||||
Write-Host " `$certPass = ConvertTo-SecureString 'Password' -AsPlainText -Force" -ForegroundColor White
|
||||
Write-Host " .\Setup-WinRM-HTTPS.ps1 -CertificatePath 'C:\Certs\wildcard.pfx' ``" -ForegroundColor White
|
||||
Write-Host " -CertificatePassword `$certPass -Domain '$Domain'" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host " # Or with existing certificate:" -ForegroundColor Gray
|
||||
Write-Host " .\Setup-WinRM-HTTPS.ps1 -CertificateThumbprint 'THUMBPRINT' -Domain '$Domain'" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "This will:" -ForegroundColor Yellow
|
||||
Write-Host " 1. Install/locate the wildcard certificate" -ForegroundColor White
|
||||
Write-Host " 2. Create HTTPS listener on port 5986" -ForegroundColor White
|
||||
Write-Host " 3. Configure Windows Firewall" -ForegroundColor White
|
||||
Write-Host " 4. Enable WinRM service" -ForegroundColor White
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Main execution
|
||||
try {
|
||||
Write-Host "=== Remote Asset Collection Script (HTTPS) ===" -ForegroundColor Cyan
|
||||
Write-Host "Starting at $(Get-Date)" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
# Initialize logging
|
||||
Initialize-Logging -LogPath $LogPath
|
||||
|
||||
# Get target computers
|
||||
$fqdns = Get-ComputerTargets -HostnameList $HostnameList -HostnameListFile $HostnameListFile -Domain $Domain
|
||||
|
||||
if ($fqdns.Count -eq 0) {
|
||||
Write-Log "No target computers specified. Use -HostnameList or -HostnameListFile parameter." $LogPath "ERROR"
|
||||
Show-SetupInstructions -Domain $Domain
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Target computers (FQDNs): $($fqdns -join ', ')" $LogPath "INFO"
|
||||
|
||||
# Resolve IP addresses
|
||||
Write-Host "`nResolving IP addresses..." -ForegroundColor Yellow
|
||||
$resolvedComputers = @()
|
||||
foreach ($fqdn in $fqdns) {
|
||||
Write-Host "Resolving $fqdn..." -NoNewline
|
||||
$ip = Resolve-ComputerIP -FQDN $fqdn
|
||||
if ($ip) {
|
||||
Write-Host " [$ip]" -ForegroundColor Green
|
||||
$resolvedComputers += @{ FQDN = $fqdn; IP = $ip }
|
||||
Write-Log "Resolved $fqdn to $ip" $LogPath "INFO"
|
||||
} else {
|
||||
Write-Host " [DNS FAILED]" -ForegroundColor Red
|
||||
Write-Log "Failed to resolve $fqdn" $LogPath "WARN"
|
||||
}
|
||||
}
|
||||
|
||||
if ($resolvedComputers.Count -eq 0) {
|
||||
Write-Log "No computers could be resolved via DNS" $LogPath "ERROR"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get credentials if not provided
|
||||
if (-not $Credential) {
|
||||
Write-Host "`nEnter credentials for remote computer access:" -ForegroundColor Yellow
|
||||
$Credential = Get-Credential
|
||||
if (-not $Credential) {
|
||||
Write-Log "No credentials provided" $LogPath "ERROR"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Test connections if requested
|
||||
if ($TestConnections) {
|
||||
Write-Host "`nTesting HTTPS connections only..." -ForegroundColor Yellow
|
||||
foreach ($comp in $resolvedComputers) {
|
||||
$fqdn = $comp.FQDN
|
||||
Write-Host "Testing $fqdn..." -NoNewline
|
||||
if (Test-WinRMHTTPSConnection -ComputerName $fqdn -Credential $Credential -Port $Port -SkipCertCheck $SkipCertificateCheck) {
|
||||
Write-Host " [OK]" -ForegroundColor Green
|
||||
Write-Log "HTTPS connection test successful for $fqdn" $LogPath "SUCCESS"
|
||||
} else {
|
||||
Write-Host " [FAIL]" -ForegroundColor Red
|
||||
Write-Log "HTTPS connection test failed for $fqdn" $LogPath "ERROR"
|
||||
}
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Validate all connections and script existence before starting collection
|
||||
Write-Host "`nValidating remote HTTPS connections and script availability..." -ForegroundColor Yellow
|
||||
$validComputers = @()
|
||||
|
||||
foreach ($comp in $resolvedComputers) {
|
||||
$fqdn = $comp.FQDN
|
||||
Write-Host "Validating $fqdn..." -NoNewline
|
||||
|
||||
if (-not (Test-WinRMHTTPSConnection -ComputerName $fqdn -Credential $Credential -Port $Port -SkipCertCheck $SkipCertificateCheck)) {
|
||||
Write-Host " [CONNECTION FAILED]" -ForegroundColor Red
|
||||
Write-Log "Cannot connect to $fqdn via WinRM HTTPS" $LogPath "ERROR"
|
||||
continue
|
||||
}
|
||||
|
||||
if (-not (Test-RemoteScriptExists -ComputerName $fqdn -Credential $Credential -ScriptPath $ScriptPath -Port $Port -SkipCertCheck $SkipCertificateCheck)) {
|
||||
Write-Host " [SCRIPT NOT FOUND]" -ForegroundColor Red
|
||||
Write-Log "Script not found on $fqdn at $ScriptPath" $LogPath "ERROR"
|
||||
continue
|
||||
}
|
||||
|
||||
Write-Host " [OK]" -ForegroundColor Green
|
||||
$validComputers += $comp
|
||||
}
|
||||
|
||||
if ($validComputers.Count -eq 0) {
|
||||
Write-Log "No valid computers found for data collection" $LogPath "ERROR"
|
||||
Show-SetupInstructions -Domain $Domain
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Valid computers for collection: $($validComputers.FQDN -join ', ')" $LogPath "INFO"
|
||||
|
||||
# Execute asset collection
|
||||
Write-Host "`nStarting asset collection on $($validComputers.Count) computers..." -ForegroundColor Cyan
|
||||
Write-Host "Max concurrent sessions: $MaxConcurrent" -ForegroundColor Gray
|
||||
Write-Host "Using HTTPS on port: $Port" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
$results = @()
|
||||
$jobs = @()
|
||||
$completed = 0
|
||||
|
||||
# Process computers in batches
|
||||
for ($i = 0; $i -lt $validComputers.Count; $i += $MaxConcurrent) {
|
||||
$batch = $validComputers[$i..($i + $MaxConcurrent - 1)]
|
||||
|
||||
Write-Host "Processing batch: $($batch.FQDN -join ', ')" -ForegroundColor Yellow
|
||||
|
||||
# Start jobs for current batch
|
||||
foreach ($comp in $batch) {
|
||||
$fqdn = $comp.FQDN
|
||||
|
||||
$job = Start-Job -ScriptBlock {
|
||||
param($FQDN, $Credential, $ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty, $Port, $SkipCertCheck, $LogPath, $Functions)
|
||||
|
||||
# Import functions into job scope
|
||||
Invoke-Expression $Functions
|
||||
|
||||
Invoke-RemoteAssetScript -ComputerName $FQDN -Credential $Credential `
|
||||
-ScriptPath $ScriptPath -ProxyURL $ProxyURL -DashboardURL $DashboardURL `
|
||||
-SkipWarranty $SkipWarranty -Port $Port -SkipCertCheck $SkipCertCheck -LogPath $LogPath
|
||||
|
||||
} -ArgumentList $fqdn, $Credential, $ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty, $Port, $SkipCertificateCheck, $LogPath, (Get-Content $PSCommandPath | Out-String)
|
||||
|
||||
$jobs += $job
|
||||
}
|
||||
|
||||
# Wait for batch to complete
|
||||
$jobs | Wait-Job | Out-Null
|
||||
|
||||
# Collect results
|
||||
foreach ($job in $jobs) {
|
||||
$result = Receive-Job $job
|
||||
$results += $result
|
||||
Remove-Job $job
|
||||
$completed++
|
||||
|
||||
$computer = $result.Computer
|
||||
if ($result.Success) {
|
||||
Write-Host "[OK] $computer - Completed successfully" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] $computer - Failed: $($result.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
$jobs = @()
|
||||
Write-Host "Batch completed. Progress: $completed/$($validComputers.Count)" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Summary
|
||||
$successful = ($results | Where-Object { $_.Success }).Count
|
||||
$failed = ($results | Where-Object { -not $_.Success }).Count
|
||||
|
||||
Write-Host "=== Collection Summary ===" -ForegroundColor Cyan
|
||||
Write-Host "Total computers: $($validComputers.Count)" -ForegroundColor White
|
||||
Write-Host "Successful: $successful" -ForegroundColor Green
|
||||
Write-Host "Failed: $failed" -ForegroundColor Red
|
||||
|
||||
if ($failed -gt 0) {
|
||||
Write-Host "`nFailed computers:" -ForegroundColor Yellow
|
||||
$results | Where-Object { -not $_.Success } | ForEach-Object {
|
||||
Write-Host " $($_.Computer): $($_.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Collection completed. Success: $successful, Failed: $failed" $LogPath "INFO"
|
||||
|
||||
} catch {
|
||||
Write-Log "Fatal error: $($_.Exception.Message)" $LogPath "ERROR"
|
||||
exit 1
|
||||
}
|
||||
484
remote-execution/Invoke-RemoteAssetCollection.ps1
Normal file
484
remote-execution/Invoke-RemoteAssetCollection.ps1
Normal file
@@ -0,0 +1,484 @@
|
||||
#Requires -RunAsAdministrator
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remotely executes asset collection script on shopfloor PCs using WinRM.
|
||||
|
||||
.DESCRIPTION
|
||||
This script uses WinRM to remotely execute the Update-PC-CompleteAsset.ps1 script
|
||||
on multiple shopfloor PCs. It handles:
|
||||
1. WinRM configuration and trusted hosts setup
|
||||
2. Credential management for remote connections
|
||||
3. Parallel or sequential execution across multiple PCs
|
||||
4. Error handling and logging for remote operations
|
||||
5. Collection of results from each remote PC
|
||||
|
||||
.PARAMETER ComputerList
|
||||
Array of computer names or IP addresses to collect data from.
|
||||
|
||||
.PARAMETER ComputerListFile
|
||||
Path to a text file containing computer names/IPs (one per line).
|
||||
|
||||
.PARAMETER Credential
|
||||
PSCredential object for authenticating to remote computers.
|
||||
If not provided, will prompt for credentials.
|
||||
|
||||
.PARAMETER MaxConcurrent
|
||||
Maximum number of concurrent remote sessions (default: 5).
|
||||
|
||||
.PARAMETER ProxyURL
|
||||
URL for the warranty proxy server (passed to remote script).
|
||||
|
||||
.PARAMETER DashboardURL
|
||||
URL for the dashboard API (passed to remote script).
|
||||
|
||||
.PARAMETER SkipWarranty
|
||||
Skip warranty lookups on remote PCs (passed to remote script).
|
||||
|
||||
.PARAMETER LogPath
|
||||
Path for log files (default: .\logs\remote-collection.log).
|
||||
|
||||
.PARAMETER TestConnections
|
||||
Test remote connections without running the full collection.
|
||||
|
||||
.PARAMETER ScriptPath
|
||||
Path to the Update-PC-CompleteAsset.ps1 script on remote computers.
|
||||
Default: C:\Scripts\Update-PC-CompleteAsset.ps1
|
||||
|
||||
.EXAMPLE
|
||||
# Collect from specific computers with prompted credentials
|
||||
.\Invoke-RemoteAssetCollection.ps1 -ComputerList @("10.48.130.100", "10.48.130.101")
|
||||
|
||||
.EXAMPLE
|
||||
# Collect from computers listed in file with stored credentials
|
||||
$cred = Get-Credential
|
||||
.\Invoke-RemoteAssetCollection.ps1 -ComputerListFile ".\shopfloor-pcs.txt" -Credential $cred
|
||||
|
||||
.EXAMPLE
|
||||
# Test connections only
|
||||
.\Invoke-RemoteAssetCollection.ps1 -ComputerList @("10.48.130.100") -TestConnections
|
||||
|
||||
.NOTES
|
||||
Author: System Administrator
|
||||
Date: 2025-09-26
|
||||
Version: 1.0
|
||||
|
||||
Prerequisites:
|
||||
1. WinRM must be enabled on target computers
|
||||
2. PowerShell remoting must be enabled on target computers
|
||||
3. Update-PC-CompleteAsset.ps1 must be present on target computers
|
||||
4. Credentials with admin rights on target computers
|
||||
|
||||
WinRM Setup Commands (run on management server):
|
||||
Enable-PSRemoting -Force
|
||||
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force
|
||||
|
||||
WinRM Setup Commands (run on target computers):
|
||||
Enable-PSRemoting -Force
|
||||
Set-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" -Enabled True
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string[]]$ComputerList = @(),
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ComputerListFile,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[PSCredential]$Credential,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]$MaxConcurrent = 5,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ProxyURL = "http://10.48.130.158/vendor-api-proxy.php",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$DashboardURL = "https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$SkipWarranty = $true,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$LogPath = ".\logs\remote-collection.log",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$TestConnections = $false,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ScriptPath = "C:\Scripts\Update-PC-CompleteAsset.ps1"
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# SSL/TLS Certificate Bypass for HTTPS connections
|
||||
# =============================================================================
|
||||
# This allows connections to servers with self-signed or untrusted certificates
|
||||
try {
|
||||
# For PowerShell 5.x - use .NET callback
|
||||
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type) {
|
||||
Add-Type @"
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
public class TrustAllCertsPolicy : ICertificatePolicy {
|
||||
public bool CheckValidationResult(
|
||||
ServicePoint srvPoint, X509Certificate certificate,
|
||||
WebRequest request, int certificateProblem) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
"@
|
||||
}
|
||||
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
||||
} catch {
|
||||
# Silently continue if already set
|
||||
}
|
||||
|
||||
# Set TLS 1.2 as minimum (required for modern HTTPS)
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
# Initialize logging
|
||||
function Initialize-Logging {
|
||||
param([string]$LogPath)
|
||||
|
||||
$logDir = Split-Path $LogPath -Parent
|
||||
if (-not (Test-Path $logDir)) {
|
||||
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Add-Content -Path $LogPath -Value "[$timestamp] Remote asset collection started"
|
||||
}
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message, [string]$LogPath, [string]$Level = "INFO")
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] $Message"
|
||||
|
||||
Add-Content -Path $LogPath -Value $logEntry
|
||||
|
||||
switch ($Level) {
|
||||
"ERROR" { Write-Host $logEntry -ForegroundColor Red }
|
||||
"WARN" { Write-Host $logEntry -ForegroundColor Yellow }
|
||||
"SUCCESS" { Write-Host $logEntry -ForegroundColor Green }
|
||||
default { Write-Host $logEntry -ForegroundColor White }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ComputerTargets {
|
||||
param([string[]]$ComputerList, [string]$ComputerListFile)
|
||||
|
||||
$targets = @()
|
||||
|
||||
# Add computers from direct list
|
||||
if ($ComputerList.Count -gt 0) {
|
||||
$targets += $ComputerList
|
||||
}
|
||||
|
||||
# Add computers from file
|
||||
if (-not [string]::IsNullOrEmpty($ComputerListFile)) {
|
||||
if (Test-Path $ComputerListFile) {
|
||||
$fileTargets = Get-Content $ComputerListFile | Where-Object { $_.Trim() -ne "" -and -not $_.StartsWith("#") }
|
||||
$targets += $fileTargets
|
||||
} else {
|
||||
Write-Log "Computer list file not found: $ComputerListFile" $LogPath "ERROR"
|
||||
}
|
||||
}
|
||||
|
||||
# Remove duplicates and return
|
||||
return ($targets | Sort-Object -Unique)
|
||||
}
|
||||
|
||||
function Test-WinRMConnection {
|
||||
param([string]$ComputerName, [PSCredential]$Credential)
|
||||
|
||||
try {
|
||||
$session = New-PSSession -ComputerName $ComputerName -Credential $Credential -ErrorAction Stop
|
||||
Remove-PSSession $session
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Test-RemoteScriptExists {
|
||||
param([string]$ComputerName, [PSCredential]$Credential, [string]$ScriptPath)
|
||||
|
||||
try {
|
||||
$result = Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock {
|
||||
param($Path)
|
||||
Test-Path $Path
|
||||
} -ArgumentList $ScriptPath
|
||||
|
||||
return $result
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-RemoteAssetScript {
|
||||
param(
|
||||
[string]$ComputerName,
|
||||
[PSCredential]$Credential,
|
||||
[string]$ScriptPath,
|
||||
[string]$ProxyURL,
|
||||
[string]$DashboardURL,
|
||||
[bool]$SkipWarranty,
|
||||
[string]$LogPath
|
||||
)
|
||||
|
||||
try {
|
||||
Write-Log "Starting asset collection on $ComputerName" $LogPath "INFO"
|
||||
|
||||
# Execute the script remotely
|
||||
$result = Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock {
|
||||
param($ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty)
|
||||
|
||||
# Change to script directory
|
||||
$scriptDir = Split-Path $ScriptPath -Parent
|
||||
Set-Location $scriptDir
|
||||
|
||||
# Build parameters
|
||||
$params = @{
|
||||
ProxyURL = $ProxyURL
|
||||
DashboardURL = $DashboardURL
|
||||
}
|
||||
|
||||
if ($SkipWarranty) {
|
||||
$params.SkipWarranty = $true
|
||||
}
|
||||
|
||||
# Execute the script and capture output
|
||||
try {
|
||||
& $ScriptPath @params
|
||||
return @{
|
||||
Success = $true
|
||||
Output = "Script completed successfully"
|
||||
Error = $null
|
||||
}
|
||||
}
|
||||
catch {
|
||||
return @{
|
||||
Success = $false
|
||||
Output = $null
|
||||
Error = $_.Exception.Message
|
||||
}
|
||||
}
|
||||
} -ArgumentList $ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty
|
||||
|
||||
if ($result.Success) {
|
||||
Write-Log "Asset collection completed successfully on $ComputerName" $LogPath "SUCCESS"
|
||||
|
||||
# Update WinRM status in database - WinRM connection was successful
|
||||
# Get the actual hostname from the remote PC (in case we connected via IP)
|
||||
try {
|
||||
$remoteHostname = Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock {
|
||||
$env:COMPUTERNAME
|
||||
} -ErrorAction SilentlyContinue
|
||||
|
||||
if ([string]::IsNullOrEmpty($remoteHostname)) {
|
||||
$remoteHostname = $ComputerName
|
||||
}
|
||||
|
||||
$winrmBody = @{
|
||||
action = "updateWinRMStatus"
|
||||
hostname = $remoteHostname
|
||||
hasWinRM = "1"
|
||||
}
|
||||
Write-Log "Updating WinRM status for hostname: $remoteHostname (connected as: $ComputerName)" $LogPath "INFO"
|
||||
$winrmResponse = Invoke-RestMethod -Uri $DashboardURL -Method Post -Body $winrmBody -ErrorAction Stop
|
||||
if ($winrmResponse.success) {
|
||||
Write-Log "WinRM status updated for $remoteHostname" $LogPath "INFO"
|
||||
} else {
|
||||
Write-Log "WinRM update response: $($winrmResponse | ConvertTo-Json -Compress)" $LogPath "WARN"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Failed to update WinRM status for $ComputerName - $($_.Exception.Message)" $LogPath "WARN"
|
||||
}
|
||||
|
||||
return @{ Success = $true; Computer = $ComputerName; Message = $result.Output }
|
||||
} else {
|
||||
Write-Log "Asset collection failed on $ComputerName: $($result.Error)" $LogPath "ERROR"
|
||||
return @{ Success = $false; Computer = $ComputerName; Message = $result.Error }
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$errorMsg = "Failed to execute on $ComputerName: $($_.Exception.Message)"
|
||||
Write-Log $errorMsg $LogPath "ERROR"
|
||||
return @{ Success = $false; Computer = $ComputerName; Message = $errorMsg }
|
||||
}
|
||||
}
|
||||
|
||||
function Show-WinRMSetupInstructions {
|
||||
Write-Host "=== WinRM Setup Instructions ===" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "On Management Server (this computer):" -ForegroundColor Yellow
|
||||
Write-Host " Enable-PSRemoting -Force" -ForegroundColor White
|
||||
Write-Host " Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "On Target Computers:" -ForegroundColor Yellow
|
||||
Write-Host " Enable-PSRemoting -Force" -ForegroundColor White
|
||||
Write-Host " Set-NetFirewallRule -DisplayName 'Windows Remote Management (HTTP-In)' -Enabled True" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "For specific computer trust:" -ForegroundColor Yellow
|
||||
Write-Host " Set-Item WSMan:\localhost\Client\TrustedHosts -Value '10.48.130.100,10.48.130.101' -Force" -ForegroundColor White
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Main execution
|
||||
try {
|
||||
Write-Host "=== Remote Asset Collection Script ===" -ForegroundColor Cyan
|
||||
Write-Host "Starting at $(Get-Date)" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
# Initialize logging
|
||||
Initialize-Logging -LogPath $LogPath
|
||||
|
||||
# Get target computers
|
||||
$computers = Get-ComputerTargets -ComputerList $ComputerList -ComputerListFile $ComputerListFile
|
||||
|
||||
if ($computers.Count -eq 0) {
|
||||
Write-Log "No target computers specified. Use -ComputerList or -ComputerListFile parameter." $LogPath "ERROR"
|
||||
Show-WinRMSetupInstructions
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Target computers: $($computers -join ', ')" $LogPath "INFO"
|
||||
|
||||
# Get credentials if not provided
|
||||
if (-not $Credential) {
|
||||
Write-Host "Enter credentials for remote computer access:" -ForegroundColor Yellow
|
||||
$Credential = Get-Credential
|
||||
if (-not $Credential) {
|
||||
Write-Log "No credentials provided" $LogPath "ERROR"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Test connections if requested
|
||||
if ($TestConnections) {
|
||||
Write-Host "`nTesting connections only..." -ForegroundColor Yellow
|
||||
foreach ($computer in $computers) {
|
||||
Write-Host "Testing $computer..." -NoNewline
|
||||
if (Test-WinRMConnection -ComputerName $computer -Credential $Credential) {
|
||||
Write-Host " [OK]" -ForegroundColor Green
|
||||
Write-Log "Connection test successful for $computer" $LogPath "SUCCESS"
|
||||
} else {
|
||||
Write-Host " [FAIL]" -ForegroundColor Red
|
||||
Write-Log "Connection test failed for $computer" $LogPath "ERROR"
|
||||
}
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Validate all connections and script existence before starting collection
|
||||
Write-Host "`nValidating remote connections and script availability..." -ForegroundColor Yellow
|
||||
$validComputers = @()
|
||||
|
||||
foreach ($computer in $computers) {
|
||||
Write-Host "Validating $computer..." -NoNewline
|
||||
|
||||
if (-not (Test-WinRMConnection -ComputerName $computer -Credential $Credential)) {
|
||||
Write-Host " [CONNECTION FAILED]" -ForegroundColor Red
|
||||
Write-Log "Cannot connect to $computer via WinRM" $LogPath "ERROR"
|
||||
continue
|
||||
}
|
||||
|
||||
if (-not (Test-RemoteScriptExists -ComputerName $computer -Credential $Credential -ScriptPath $ScriptPath)) {
|
||||
Write-Host " [SCRIPT NOT FOUND]" -ForegroundColor Red
|
||||
Write-Log "Script not found on $computer at $ScriptPath" $LogPath "ERROR"
|
||||
continue
|
||||
}
|
||||
|
||||
Write-Host " [OK]" -ForegroundColor Green
|
||||
$validComputers += $computer
|
||||
}
|
||||
|
||||
if ($validComputers.Count -eq 0) {
|
||||
Write-Log "No valid computers found for data collection" $LogPath "ERROR"
|
||||
Show-WinRMSetupInstructions
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Valid computers for collection: $($validComputers -join ', ')" $LogPath "INFO"
|
||||
|
||||
# Execute asset collection
|
||||
Write-Host "`nStarting asset collection on $($validComputers.Count) computers..." -ForegroundColor Cyan
|
||||
Write-Host "Max concurrent sessions: $MaxConcurrent" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
$results = @()
|
||||
$jobs = @()
|
||||
$completed = 0
|
||||
|
||||
# Process computers in batches
|
||||
for ($i = 0; $i -lt $validComputers.Count; $i += $MaxConcurrent) {
|
||||
$batch = $validComputers[$i..($i + $MaxConcurrent - 1)]
|
||||
|
||||
Write-Host "Processing batch: $($batch -join ', ')" -ForegroundColor Yellow
|
||||
|
||||
# Start jobs for current batch
|
||||
foreach ($computer in $batch) {
|
||||
$job = Start-Job -ScriptBlock {
|
||||
param($Computer, $Credential, $ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty, $LogPath, $Functions)
|
||||
|
||||
# Import functions into job scope
|
||||
Invoke-Expression $Functions
|
||||
|
||||
Invoke-RemoteAssetScript -ComputerName $Computer -Credential $Credential `
|
||||
-ScriptPath $ScriptPath -ProxyURL $ProxyURL -DashboardURL $DashboardURL `
|
||||
-SkipWarranty $SkipWarranty -LogPath $LogPath
|
||||
|
||||
} -ArgumentList $computer, $Credential, $ScriptPath, $ProxyURL, $DashboardURL, $SkipWarranty, $LogPath, (Get-Content $PSCommandPath | Out-String)
|
||||
|
||||
$jobs += $job
|
||||
}
|
||||
|
||||
# Wait for batch to complete
|
||||
$jobs | Wait-Job | Out-Null
|
||||
|
||||
# Collect results
|
||||
foreach ($job in $jobs) {
|
||||
$result = Receive-Job $job
|
||||
$results += $result
|
||||
Remove-Job $job
|
||||
$completed++
|
||||
|
||||
$computer = $result.Computer
|
||||
if ($result.Success) {
|
||||
Write-Host "[✓] $computer - Completed successfully" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[✗] $computer - Failed: $($result.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
$jobs = @()
|
||||
Write-Host "Batch completed. Progress: $completed/$($validComputers.Count)" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Summary
|
||||
$successful = ($results | Where-Object { $_.Success }).Count
|
||||
$failed = ($results | Where-Object { -not $_.Success }).Count
|
||||
|
||||
Write-Host "=== Collection Summary ===" -ForegroundColor Cyan
|
||||
Write-Host "Total computers: $($validComputers.Count)" -ForegroundColor White
|
||||
Write-Host "Successful: $successful" -ForegroundColor Green
|
||||
Write-Host "Failed: $failed" -ForegroundColor Red
|
||||
|
||||
if ($failed -gt 0) {
|
||||
Write-Host "`nFailed computers:" -ForegroundColor Yellow
|
||||
$results | Where-Object { -not $_.Success } | ForEach-Object {
|
||||
Write-Host " $($_.Computer): $($_.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Collection completed. Success: $successful, Failed: $failed" $LogPath "INFO"
|
||||
|
||||
} catch {
|
||||
Write-Log "Fatal error: $($_.Exception.Message)" $LogPath "ERROR"
|
||||
exit 1
|
||||
}
|
||||
171
remote-execution/README.md
Normal file
171
remote-execution/README.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# Remote Execution Scripts
|
||||
|
||||
Scripts for remotely executing asset collection on multiple shopfloor PCs via WinRM.
|
||||
|
||||
## Scripts
|
||||
|
||||
### Invoke-RemoteAssetCollection.ps1
|
||||
**Remote collection via WinRM HTTP** - Execute asset collection on multiple PCs using WinRM over HTTP (port 5985).
|
||||
|
||||
**What it does:**
|
||||
1. Establishes WinRM connections to target PCs
|
||||
2. Executes `Update-PC-CompleteAsset.ps1` remotely
|
||||
3. Collects and logs results from each PC
|
||||
4. Supports parallel execution for efficiency
|
||||
|
||||
**Usage:**
|
||||
```powershell
|
||||
# From file with prompted credentials
|
||||
.\Invoke-RemoteAssetCollection.ps1 -ComputerListFile ".\shopfloor-pcs.txt"
|
||||
|
||||
# Specific computers with stored credentials
|
||||
$cred = Get-Credential
|
||||
.\Invoke-RemoteAssetCollection.ps1 -ComputerList @("PC001","PC002") -Credential $cred
|
||||
|
||||
# Test connections only
|
||||
.\Invoke-RemoteAssetCollection.ps1 -ComputerList @("PC001") -TestConnections
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `-ComputerList` | - | Array of computer names/IPs |
|
||||
| `-ComputerListFile` | - | Path to text file with computer list |
|
||||
| `-Credential` | - | PSCredential for authentication |
|
||||
| `-MaxConcurrent` | `5` | Maximum parallel sessions |
|
||||
| `-TestConnections` | `$false` | Test connectivity only |
|
||||
| `-ScriptPath` | `C:\Scripts\Update-PC-CompleteAsset.ps1` | Path to script on remote PCs |
|
||||
|
||||
**Prerequisites:**
|
||||
- WinRM enabled on target PCs (`Enable-PSRemoting -Force`)
|
||||
- Admin credentials for remote PCs
|
||||
- Port 5985 (HTTP) open in firewall
|
||||
|
||||
---
|
||||
|
||||
### Invoke-RemoteAssetCollection-HTTPS.ps1
|
||||
**Secure remote collection via WinRM HTTPS** - Same as above but uses encrypted HTTPS connections (port 5986).
|
||||
|
||||
**What it does:**
|
||||
- Uses HTTPS/TLS encryption for secure communication
|
||||
- Supports wildcard certificates for domain-wide deployment
|
||||
- Automatic FQDN construction from hostnames
|
||||
|
||||
**Usage:**
|
||||
```powershell
|
||||
# With domain suffix
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameList @("PC001","PC002") -Domain "logon.ds.ge.com"
|
||||
|
||||
# From file
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameListFile ".\hostnames.txt" -Domain "logon.ds.ge.com"
|
||||
|
||||
# Test HTTPS connections
|
||||
.\Invoke-RemoteAssetCollection-HTTPS.ps1 -HostnameList @("PC001") -Domain "logon.ds.ge.com" -TestConnections
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `-HostnameList` | - | Array of hostnames (without domain) |
|
||||
| `-HostnameListFile` | - | Path to text file with hostnames |
|
||||
| `-Domain` | - | Domain suffix (e.g., "logon.ds.ge.com") |
|
||||
| `-Port` | `5986` | HTTPS port |
|
||||
| `-SkipCertificateCheck` | `$false` | Skip SSL validation |
|
||||
|
||||
**Prerequisites:**
|
||||
- WinRM HTTPS configured on targets (see `winrm-https/` folder)
|
||||
- Valid SSL certificates installed
|
||||
- Port 5986 open in firewall
|
||||
|
||||
---
|
||||
|
||||
### Update-ShopfloorPCs-Remote.ps1
|
||||
**Query and update all shopfloor PCs** - Queries ShopDB for PC list and updates them remotely.
|
||||
|
||||
**What it does:**
|
||||
1. Queries ShopDB API for list of all shopfloor PCs
|
||||
2. Establishes WinRM connections to each PC
|
||||
3. Collects system info remotely and POSTs to API
|
||||
4. Logs success/failure for each PC
|
||||
|
||||
**Usage:**
|
||||
```powershell
|
||||
# Update all shopfloor PCs from ShopDB database
|
||||
.\Update-ShopfloorPCs-Remote.ps1 -All
|
||||
|
||||
# Update specific PCs
|
||||
.\Update-ShopfloorPCs-Remote.ps1 -ComputerName "PC001","PC002"
|
||||
|
||||
# Setup WinRM trusted hosts first
|
||||
.\Update-ShopfloorPCs-Remote.ps1 -SetupTrustedHosts
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `-ComputerName` | - | Specific PC(s) to update |
|
||||
| `-All` | `$false` | Update all shopfloor PCs from ShopDB |
|
||||
| `-SetupTrustedHosts` | `$false` | Configure WinRM trusted hosts |
|
||||
| `-Credential` | - | PSCredential for authentication |
|
||||
| `-ApiUrl` | Production URL | ShopDB API URL |
|
||||
|
||||
---
|
||||
|
||||
## Batch File Launchers
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `Run-RemoteCollection.bat` | Launcher for remote collection script |
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- PowerShell 5.1 or later
|
||||
- **Administrator privileges** (required)
|
||||
- WinRM enabled on management server and target PCs
|
||||
- Network access to target PCs (ports 5985 or 5986)
|
||||
- Admin credentials for target PCs
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Management Server │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Invoke-RemoteAssetCollection │ │
|
||||
│ │ Update-ShopfloorPCs-Remote │ │
|
||||
│ └──────────────┬────────────────┘ │
|
||||
└─────────────────┼───────────────────┘
|
||||
│ WinRM (5985/5986)
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Shopfloor PC 1 │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Update-PC-CompleteAsset.ps1 │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
┌─────────────────────────────────────┐
|
||||
│ Shopfloor PC 2 │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ Update-PC-CompleteAsset.ps1 │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
... (parallel execution)
|
||||
```
|
||||
|
||||
## WinRM Setup
|
||||
|
||||
### On Management Server:
|
||||
```powershell
|
||||
Enable-PSRemoting -Force
|
||||
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force
|
||||
```
|
||||
|
||||
### On Target PCs:
|
||||
```powershell
|
||||
Enable-PSRemoting -Force
|
||||
Set-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" -Enabled True
|
||||
```
|
||||
|
||||
For HTTPS setup, see the `winrm-https/` folder documentation.
|
||||
25
remote-execution/Run-RemoteCollection.bat
Normal file
25
remote-execution/Run-RemoteCollection.bat
Normal file
@@ -0,0 +1,25 @@
|
||||
@echo off
|
||||
REM Batch file to run remote asset collection
|
||||
REM Requires administrator privileges
|
||||
|
||||
echo === Remote Asset Collection ===
|
||||
echo.
|
||||
|
||||
REM Check for admin privileges
|
||||
net session >nul 2>&1
|
||||
if %errorLevel% neq 0 (
|
||||
echo This script requires administrator privileges.
|
||||
echo Please run as administrator.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Starting PowerShell script...
|
||||
echo.
|
||||
|
||||
REM Run the PowerShell script with execution policy bypass
|
||||
powershell.exe -ExecutionPolicy Bypass -File "%~dp0Invoke-RemoteAssetCollection.ps1" -ComputerListFile "%~dp0shopfloor-pcs.txt"
|
||||
|
||||
echo.
|
||||
echo Collection completed. Check logs folder for details.
|
||||
pause
|
||||
1194
remote-execution/Update-ShopfloorPCs-Remote.ps1
Normal file
1194
remote-execution/Update-ShopfloorPCs-Remote.ps1
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user