# WinRM Setup Package for Shopfloor PCs This package provides scripts to configure WinRM (Windows Remote Management) on shopfloor PCs and execute remote maintenance tasks. ## Contents | File | Description | |------|-------------| | `Setup-WinRM.bat` | Run on each PC to enable and configure WinRM | | `Invoke-RemoteTask.ps1` | PowerShell script to execute tasks on remote PCs | | `hosts.txt` | List of target computers (edit before use) | | `README.md` | This documentation | --- ## Quick Start ### Step 1: Configure Your Admin Workstation Before connecting to remote PCs, run this once on your admin workstation (as Administrator): ```powershell Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*.logon.ds.ge.com" -Force ``` This allows your workstation to connect to any PC in the domain. ### Step 2: Configure the Setup Script Edit `Setup-WinRM.bat` and update these values at the top: ```batch REM Default security group - who can use WinRM to connect set "DEFAULT_SECURITY_GROUP=logon\groupid" REM Where to log the inventory CSV (network share recommended) set "DEFAULT_LOG_PATH=\\server\share\winrm-inventory" REM Domain suffix for TrustedHosts set "TRUSTED_DOMAIN=*.logon.ds.ge.com" REM Optional: Trust a specific subnet (uncomment and set) REM set "TRUSTED_SUBNET=10.48.130.*" ``` ### Step 3: Create Security Group in Active Directory 1. Open **Active Directory Users and Computers** 2. Create a new Security Group (or use existing group matching `groupid`) 3. Add users who should have remote management access ### Step 4: Run Setup on Each Shopfloor PC Run as Administrator on each PC: ```cmd Setup-WinRM.bat ``` Or with parameters: ```cmd Setup-WinRM.bat "logon\groupid" "\\server\share\winrm-inventory" ``` The script will: - Enable WinRM service - Configure authentication (Negotiate/Kerberos) - Set firewall rules (domain profile only) - Restrict access to the security group - Log hostname/IP to CSV inventory ### Step 5: Run Remote Tasks From your admin workstation, edit `hosts.txt` with target PCs, then: ```powershell # Test connectivity .\Invoke-RemoteTask.ps1 -Task TestConnection # Restart print spooler on all hosts .\Invoke-RemoteTask.ps1 -Task RestartSpooler # Check disk space .\Invoke-RemoteTask.ps1 -Task GetDiskSpace # Run on a single PC .\Invoke-RemoteTask.ps1 -ComputerName "PC001" -Task FlushDNS ``` --- ## Setup Script Details ### What Setup-WinRM.bat Configures | Setting | Value | Purpose | |---------|-------|---------| | WinRM Service | Auto-start | Ensures WinRM starts on boot | | AllowUnencrypted | false | Security: require encrypted connections | | Negotiate Auth | true | Enables Kerberos/NTLM authentication | | CredSSP Auth | true | Enables credential delegation (double-hop) | | Firewall | Domain profile | Opens port 5985 for domain connections only | | TrustedHosts | *.logon.ds.ge.com | Trusts domain-joined PCs | | RootSDDL | Security group | Restricts who can connect | ### CSV Inventory The setup script logs each PC to a CSV file: ```csv Hostname,IPAddress,SetupDate,OSVersion,SecurityGroup PC001,10.48.130.101,2026-01-08 09:30:00,10.0,logon\groupid PC002,10.48.130.102,2026-01-08 09:35:00,10.0,logon\groupid ``` You can use this CSV as your hosts file: ```powershell # Extract hostnames from CSV Import-Csv "\\server\share\winrm-inventory\winrm-inventory.csv" | Select-Object -ExpandProperty Hostname | Set-Content .\hosts.txt ``` --- ## Available Remote Tasks | Task | Description | |------|-------------| | `TestConnection` | Verify WinRM connectivity | | `GetUptime` | Show system uptime and last boot time | | `GetDiskSpace` | Show free space on all drives | | `RestartSpooler` | Restart Print Spooler service | | `FlushDNS` | Clear DNS resolver cache | | `ClearTempFiles` | Delete Windows temp files | | `DiskCleanup` | Run Windows Disk Cleanup | | `OptimizeDisk` | TRIM (SSD) or Defrag (HDD) | | `SyncTime` | Force time sync with domain controller | | `RestartService` | Restart any Windows service (requires `-ServiceName`) | | `RunCommand` | Run custom PowerShell command (requires `-Command`) | | `RestartComputer` | Restart the remote PC (requires YES confirmation) | ### Examples ```powershell # Check uptime on all hosts .\Invoke-RemoteTask.ps1 -Task GetUptime # Restart a specific service .\Invoke-RemoteTask.ps1 -Task RestartService -ServiceName "Spooler" # Run custom command .\Invoke-RemoteTask.ps1 -Task RunCommand -Command "Get-Process | Sort CPU -Desc | Select -First 5" # Use custom hosts file .\Invoke-RemoteTask.ps1 -HostsFile ".\cnc-machines.txt" -Task FlushDNS # Specify DNS suffix for short hostnames .\Invoke-RemoteTask.ps1 -DnsSuffix "logon.ds.ge.com" -Task TestConnection # Restart a remote PC (will prompt for confirmation) .\Invoke-RemoteTask.ps1 -ComputerName "PC001" -Task RestartComputer # Increase parallelism for faster execution on many PCs .\Invoke-RemoteTask.ps1 -Task FlushDNS -ThrottleLimit 20 # Save results to a log file .\Invoke-RemoteTask.ps1 -Task GetDiskSpace -LogResults ``` ### Logging Results Use `-LogResults` to save task output to a timestamped log file in the script directory: ```powershell .\Invoke-RemoteTask.ps1 -Task RestartSpooler -LogResults # Creates: RemoteTask_20260108_143022.log ``` Log files contain: - Task name and parameters - Execution time - Status of each computer (OK/FAIL) - Result messages - Summary totals ### Targeting Multiple PCs ```powershell # Comma-separated list .\Invoke-RemoteTask.ps1 -ComputerName "PC001","PC002","PC003" -Task GetUptime # Array variable $pcs = @("PC001", "PC002", "PC003") .\Invoke-RemoteTask.ps1 -ComputerName $pcs -Task FlushDNS # From hosts.txt file (default) .\Invoke-RemoteTask.ps1 -Task RestartSpooler # From CSV inventory $pcs = (Import-Csv "\\server\share\winrm-inventory.csv").Hostname .\Invoke-RemoteTask.ps1 -ComputerName $pcs -Task GetDiskSpace # From Active Directory query $pcs = (Get-ADComputer -Filter "Name -like 'SHOPFLOOR-*'").Name .\Invoke-RemoteTask.ps1 -ComputerName $pcs -Task SyncTime ``` All commands run in parallel (default: 10 concurrent connections, adjust with `-ThrottleLimit`). --- ## Troubleshooting ### "Access Denied" when connecting 1. Verify you're a member of the WinRM security group 2. Check that your credentials are correct 3. Verify the target PC ran Setup-WinRM.bat successfully ### "WinRM cannot complete the operation" 1. Verify the target PC is reachable: `ping PC001` 2. Check WinRM is running on target: `sc query winrm` (on target PC) 3. Verify firewall allows port 5985 ### "The WinRM client cannot process the request" 1. Add target to TrustedHosts on your admin workstation: ```powershell Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*.logon.ds.ge.com" -Force ``` ### Test WinRM Configuration On your admin workstation: ```powershell # Test basic connectivity Test-WSMan -ComputerName PC001 # Test with credentials $cred = Get-Credential Test-WSMan -ComputerName PC001 -Credential $cred -Authentication Negotiate # Enter interactive session Enter-PSSession -ComputerName PC001 -Credential $cred -Authentication Negotiate ``` On the target PC: ```cmd winrm enumerate winrm/config/listener winrm get winrm/config/service ``` --- ## Security Considerations 1. **Use Security Groups**: Always restrict WinRM access to a specific AD group 2. **Domain Profile Only**: Firewall rules only allow connections on domain networks 3. **No Unencrypted Traffic**: AllowUnencrypted is set to false 4. **Audit Access**: Enable Windows Security auditing for logon events 5. **Credential Protection**: Use dedicated admin accounts, not personal accounts --- ## Adding Custom Tasks Edit `Invoke-RemoteTask.ps1` and add to the `$TaskScripts` hashtable: ```powershell 'MyCustomTask' = { $result = @{ Success = $false Hostname = $env:COMPUTERNAME Output = "" Error = $null } try { # Your code here $result.Output = "Task completed" $result.Success = $true } catch { $result.Error = $_.Exception.Message } return $result } ``` Then add the task name to the `ValidateSet` in the param block. --- ## Support For issues or questions, contact your IT support team.