Files
powershell-scripts/docs/Invoke-RemoteMaintenance.html
cproudlock 7d3519f613 Add comprehensive documentation and update deployment paths
Documentation:
- Add ShopDB-API.md with full API reference (all GET/POST endpoints)
- Add detailed docs for Update-ShopfloorPCs-Remote, Invoke-RemoteMaintenance, Update-PC-CompleteAsset
- Add DATA_COLLECTION_PARITY.md comparing local vs remote data collection
- Add HTML versions of all documentation with styled code blocks
- Document software deployment mechanism and how to add new apps
- Document deprecated scripts (Invoke-RemoteAssetCollection, Install-KioskApp)

Script Updates:
- Update deployment source paths to network share (tsgwp00525.wjs.geaerospace.net)
  - InstallDashboard: \\...\scripts\Dashboard\GEAerospaceDashboardSetup.exe
  - InstallLobbyDisplay: \\...\scripts\LobbyDisplay\GEAerospaceLobbyDisplaySetup.exe
  - UpdateEMxAuthToken: \\...\scripts\eMx\eMxInfo.txt
  - DeployUDCWebServerConfig: \\...\scripts\UDC\udc_webserver_settings.json
- Update machine network detection to include 100.0.0.* for CMM cases
- Rename PC Type #9 from "Part Marker" to "Inspection"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 11:45:00 -05:00

1024 lines
38 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Invoke-RemoteMaintenance.ps1</title>
<style>
* {
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
max-width: 900px;
margin: 0 auto;
padding: 20px 40px;
background-color: #ffffff;
color: #333;
}
h1 {
color: #1a5276;
border-bottom: 3px solid #1a5276;
padding-bottom: 10px;
margin-top: 0;
}
h2 {
color: #2874a6;
border-bottom: 2px solid #d5dbdb;
padding-bottom: 8px;
margin-top: 40px;
}
h3 {
color: #2e86ab;
margin-top: 30px;
}
h4 {
color: #5d6d7e;
margin-top: 25px;
}
a {
color: #2980b9;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
code {
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
background-color: #f4f4f4;
padding: 2px 6px;
border-radius: 3px;
font-size: 0.9em;
border: 1px solid #e1e1e1;
}
pre {
background-color: #2d2d2d;
color: #f8f8f2;
padding: 15px 20px;
border-radius: 6px;
overflow-x: auto;
font-family: 'Cascadia Mono', 'JetBrains Mono', 'Fira Code', 'Source Code Pro', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 14px;
line-height: 1.4;
border: 1px solid #444;
margin: 15px 0;
-webkit-font-feature-settings: "liga" 0;
font-feature-settings: "liga" 0;
letter-spacing: 0;
}
pre code {
background-color: transparent;
padding: 0;
border: none;
color: inherit;
font-size: inherit;
}
table {
border-collapse: collapse;
width: 100%;
margin: 15px 0;
font-size: 14px;
}
th, td {
border: 1px solid #ddd;
padding: 10px 12px;
text-align: left;
}
th {
background-color: #34495e;
color: white;
font-weight: 600;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #f1f1f1;
}
ul, ol {
padding-left: 25px;
}
li {
margin-bottom: 5px;
}
blockquote {
border-left: 4px solid #3498db;
margin: 15px 0;
padding: 10px 20px;
background-color: #f8f9fa;
color: #555;
}
hr {
border: none;
border-top: 2px solid #eee;
margin: 30px 0;
}
.toc {
background-color: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 6px;
padding: 20px;
margin-bottom: 30px;
}
.toc h2 {
margin-top: 0;
border-bottom: none;
font-size: 1.2em;
}
.toc ul {
list-style-type: none;
padding-left: 0;
}
.toc li {
margin-bottom: 8px;
}
.toc a {
color: #2c3e50;
}
.note {
background-color: #fff3cd;
border-left: 4px solid #ffc107;
padding: 10px 15px;
margin: 15px 0;
}
.warning {
background-color: #f8d7da;
border-left: 4px solid #dc3545;
padding: 10px 15px;
margin: 15px 0;
}
@media print {
body {
max-width: 100%;
padding: 20px;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
h2 {
page-break-before: auto;
}
pre, table {
page-break-inside: avoid;
}
}
</style>
</head>
<body>
<h1 id="invoke-remotemaintenanceps1">Invoke-RemoteMaintenance.ps1</h1>
<p>Remote maintenance toolkit for executing maintenance tasks on shopfloor PCs via WinRM.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a href="#overview">Overview</a></li>
<li><a href="#api-integration">API Integration</a></li>
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#quick-start">Quick Start</a></li>
<li><a href="#parameters-reference">Parameters Reference</a></li>
<li><a href="#available-tasks">Available Tasks</a></li>
<li><a href="#software-deployment-mechanism">Software Deployment Mechanism</a></li>
<li><a href="#how-to-guides">How-To Guides</a></li>
<li><a href="#how-to-repair-system-files">System Repair</a></li>
<li><a href="#how-to-optimize-disks">Disk Optimization</a></li>
<li><a href="#how-to-manage-services">Service Management</a></li>
<li><a href="#how-to-fix-time-sync-issues">Time Synchronization</a></li>
<li><a href="#how-to-update-dnc-configurations">DNC Configuration</a></li>
<li><a href="#how-to-deploy-software">Software Deployment</a></li>
<li><a href="#how-to-run-batch-operations">Batch Operations</a></li>
<li><a href="#targeting-strategies">Targeting Strategies</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
<li><a href="#best-practices">Best Practices</a></li>
</ul>
<hr>
<h2 id="overview">Overview</h2>
<p>This script provides a comprehensive remote maintenance toolkit for managing shopfloor PCs. It executes maintenance tasks via WinRM (Windows Remote Management) and can target PCs individually, by type, by business unit, or all at once.</p>
<p><strong>Location:</strong> <code>S:\dt\shopfloor\scripts\remote-execution\Invoke-RemoteMaintenance.ps1</code></p>
<p><strong>Key Features:</strong></p>
<ul>
<li>19 maintenance tasks available</li>
<li>Multiple targeting options (by name, type, business unit, or all)</li>
<li>Concurrent execution with configurable throttling</li>
<li>Integration with ShopDB for PC discovery</li>
</ul>
<hr>
<h2 id="api-integration">API Integration</h2>
<p>When using <code>-All</code>, <code>-PcType</code>, or <code>-BusinessUnit</code> targeting, the script retrieves PC lists from the ShopDB API:</p>
<pre><code>GET /api.asp?action=getShopfloorPCs
GET /api.asp?action=getShopfloorPCs&amp;pctypeid=2 # CMM PCs only
GET /api.asp?action=getShopfloorPCs&amp;businessunitid=1 # Specific business unit</code></pre>
<p><strong>PC Type IDs:</strong></p>
<table>
<thead><tr>
<th>ID</th>
<th>Type</th>
<th>ID</th>
<th>Type</th>
</tr></thead>
<tbody>
<tr>
<td>1</td>
<td>Shopfloor</td>
<td>7</td>
<td>Heat Treat</td>
</tr>
<tr>
<td>2</td>
<td>CMM</td>
<td>8</td>
<td>Engineer</td>
</tr>
<tr>
<td>3</td>
<td>Wax Trace</td>
<td>9</td>
<td>Standard</td>
</tr>
<tr>
<td>4</td>
<td>Keyence</td>
<td>10</td>
<td>Inspection</td>
</tr>
<tr>
<td>5</td>
<td>EAS1000</td>
<td>11</td>
<td>Dashboard</td>
</tr>
<tr>
<td>6</td>
<td>Genspect</td>
<td>12</td>
<td>Lobby Display</td>
</tr>
</tbody></table>
<p><strong>See:</strong> <a href="ShopDB-API.html">ShopDB API Reference</a> for complete API documentation.</p>
<hr>
<h2 id="prerequisites">Prerequisites</h2>
<h3 id="on-your-workstation">On Your Workstation</h3>
<ol>
<li><strong>PowerShell 5.1 or higher</strong></li>
<li><strong>Network access to target PCs</strong> (TCP port 5985)</li>
<li><strong>Admin credentials</strong> for target PCs</li>
</ol>
<h3 id="on-target-pcs">On Target PCs</h3>
<ol>
<li><strong>WinRM enabled</strong> (<code>Enable-PSRemoting -Force</code>)</li>
<li><strong>Firewall rules</strong> allowing WinRM traffic</li>
</ol>
<h3 id="verify-connectivity">Verify Connectivity</h3>
<pre><code class="language-powershell"># Test WinRM connectivity
Test-WSMan -ComputerName &quot;SHOPFLOOR-PC01&quot;
# Test with credentials
$cred = Get-Credential
Test-WSMan -ComputerName &quot;SHOPFLOOR-PC01&quot; -Credential $cred</code></pre>
<hr>
<h2 id="quick-start">Quick Start</h2>
<h3 id="step-1-get-credentials">Step 1: Get Credentials</h3>
<pre><code class="language-powershell">$cred = Get-Credential -Message &quot;Enter domain admin credentials&quot;</code></pre>
<h3 id="step-2-run-a-simple-task">Step 2: Run a Simple Task</h3>
<pre><code class="language-powershell"># Flush DNS on a single PC
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;SHOPFLOOR-PC01&quot; -Task FlushDNS -Credential $cred</code></pre>
<h3 id="step-3-check-results">Step 3: Check Results</h3>
<p>The script outputs status for each PC:</p>
<pre><code>[SHOPFLOOR-PC01] FlushDNS: SUCCESS
DNS Resolver Cache flushed successfully</code></pre>
<hr>
<h2 id="parameters-reference">Parameters Reference</h2>
<h3 id="targeting-parameters-mutually-exclusive">Targeting Parameters (Mutually Exclusive)</h3>
<table>
<thead><tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr></thead>
<tbody>
<tr>
<td><code>-ComputerName</code></td>
<td>string[]</td>
<td>One or more computer names or IPs</td>
</tr>
<tr>
<td><code>-ComputerListFile</code></td>
<td>string</td>
<td>Path to text file with hostnames</td>
</tr>
<tr>
<td><code>-All</code></td>
<td>switch</td>
<td>Target all shopfloor PCs from ShopDB</td>
</tr>
<tr>
<td><code>-PcType</code></td>
<td>string</td>
<td>Target by PC type (see PC Types)</td>
</tr>
<tr>
<td><code>-BusinessUnit</code></td>
<td>string</td>
<td>Target by business unit (see Business Units)</td>
</tr>
</tbody></table>
<h3 id="task-parameter-required">Task Parameter (Required)</h3>
<table>
<thead><tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr></thead>
<tbody>
<tr>
<td><code>-Task</code></td>
<td>string</td>
<td>Maintenance task to execute</td>
</tr>
</tbody></table>
<h3 id="optional-parameters">Optional Parameters</h3>
<table>
<thead><tr>
<th>Parameter</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr></thead>
<tbody>
<tr>
<td><code>-Credential</code></td>
<td>PSCredential</td>
<td>Prompt</td>
<td>Remote authentication</td>
</tr>
<tr>
<td><code>-ApiUrl</code></td>
<td>string</td>
<td>Production</td>
<td>ShopDB API endpoint</td>
</tr>
<tr>
<td><code>-ThrottleLimit</code></td>
<td>int</td>
<td>5</td>
<td>Max concurrent sessions</td>
</tr>
<tr>
<td><code>-DnsSuffix</code></td>
<td>string</td>
<td>logon.ds.ge.com</td>
<td>DNS suffix for resolution</td>
</tr>
</tbody></table>
<h3 id="pc-types">PC Types</h3>
<pre><code>Standard, Engineer, Shopfloor, CMM, Wax / Trace, Keyence,
Genspect, Heat Treat, Inspection, Dashboard, Lobby Display, Uncategorized</code></pre>
<h3 id="business-units">Business Units</h3>
<pre><code>TBD, Blisk, HPT, Spools, Inspection, Venture, Turn/Burn, DT</code></pre>
<hr>
<h2 id="available-tasks">Available Tasks</h2>
<h3 id="repair-tasks">Repair Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>DISM</code></td>
<td>Repair Windows component store</td>
<td>15-60 min</td>
<td>Low</td>
</tr>
<tr>
<td><code>SFC</code></td>
<td>System File Checker scan</td>
<td>10-30 min</td>
<td>Low</td>
</tr>
</tbody></table>
<h3 id="optimization-tasks">Optimization Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>OptimizeDisk</code></td>
<td>TRIM (SSD) or Defrag (HDD)</td>
<td>5-60 min</td>
<td>Medium</td>
</tr>
<tr>
<td><code>DiskCleanup</code></td>
<td>Remove temp files, updates</td>
<td>5-15 min</td>
<td>Low</td>
</tr>
<tr>
<td><code>ClearUpdateCache</code></td>
<td>Clear Windows Update cache</td>
<td>1-2 min</td>
<td>Low</td>
</tr>
<tr>
<td><code>ClearBrowserCache</code></td>
<td>Clear Chrome/Edge cache</td>
<td>1-2 min</td>
<td>Low</td>
</tr>
</tbody></table>
<h3 id="service-tasks">Service Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>RestartSpooler</code></td>
<td>Restart Print Spooler</td>
<td><1 min</td>
<td>Low</td>
</tr>
<tr>
<td><code>FlushDNS</code></td>
<td>Clear DNS cache</td>
<td><1 min</td>
<td>None</td>
</tr>
<tr>
<td><code>RestartWinRM</code></td>
<td>Restart WinRM service</td>
<td><1 min</td>
<td>Temp disconnect</td>
</tr>
</tbody></table>
<h3 id="timedate-tasks">Time/Date Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>SetTimezone</code></td>
<td>Set to Eastern Time</td>
<td><1 min</td>
<td>None</td>
</tr>
<tr>
<td><code>SyncTime</code></td>
<td>Force time sync with DC</td>
<td><1 min</td>
<td>None</td>
</tr>
</tbody></table>
<h3 id="dnc-tasks">DNC Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>UpdateEMxAuthToken</code></td>
<td>Update eMx auth from share</td>
<td>1-2 min</td>
<td>None</td>
</tr>
<tr>
<td><code>DeployUDCWebServerConfig</code></td>
<td>Deploy UDC config</td>
<td>1-2 min</td>
<td>None</td>
</tr>
</tbody></table>
<h3 id="system-tasks">System Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>Reboot</code></td>
<td>Restart PC (30s delay)</td>
<td>2-5 min</td>
<td>High</td>
</tr>
</tbody></table>
<h3 id="software-deployment-tasks">Software Deployment Tasks</h3>
<table>
<thead><tr>
<th>Task</th>
<th>Description</th>
<th>Duration</th>
<th>Impact</th>
</tr></thead>
<tbody>
<tr>
<td><code>InstallDashboard</code></td>
<td>Install GE Dashboard app</td>
<td>2-5 min</td>
<td>Medium</td>
</tr>
<tr>
<td><code>InstallLobbyDisplay</code></td>
<td>Install Lobby Display app</td>
<td>2-5 min</td>
<td>Medium</td>
</tr>
<tr>
<td><code>UninstallDashboard</code></td>
<td>Remove GE Dashboard</td>
<td>1-2 min</td>
<td>Low</td>
</tr>
<tr>
<td><code>UninstallLobbyDisplay</code></td>
<td>Remove Lobby Display</td>
<td>1-2 min</td>
<td>Low</td>
</tr>
</tbody></table>
<hr>
<h2 id="software-deployment-mechanism">Software Deployment Mechanism</h2>
<h3 id="source-file-locations">Source File Locations</h3>
<p>Deployment tasks require source files to be available before execution:</p>
<table>
<thead><tr>
<th>Task</th>
<th>Source File Path</th>
</tr></thead>
<tbody>
<tr>
<td><code>InstallDashboard</code></td>
<td><code>\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\Dashboard\GEAerospaceDashboardSetup.exe</code></td>
</tr>
<tr>
<td><code>InstallLobbyDisplay</code></td>
<td><code>\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\LobbyDisplay\GEAerospaceLobbyDisplaySetup.exe</code></td>
</tr>
<tr>
<td><code>UpdateEMxAuthToken</code></td>
<td><code>\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\eMx\eMxInfo.txt</code></td>
</tr>
<tr>
<td><code>DeployUDCWebServerConfig</code></td>
<td><code>\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\UDC\udc_webserver_settings.json</code></td>
</tr>
</tbody></table>
<h3 id="how-deployment-works">How Deployment Works</h3>
<ol>
<li><strong>Pre-flight Check:</strong> Script verifies source file exists</li>
<li><strong>WinRM Session:</strong> Opens remote session to target PC</li>
<li><strong>File Push:</strong> Copies source file to <code>C:\Windows\Temp\</code> on remote PC</li>
<li><strong>Execution:</strong> Runs install/copy task using pushed file</li>
<li><strong>Cleanup:</strong> Removes temp file from remote PC</li>
</ol>
<pre><code>+---------------------+ WinRM +---------------------+
| Your Workstation | ------------&gt; | Target PC |
| | | |
| Source Files: | Push File | Temp Location: |
| - Setup.exe | ------------&gt; | C:\Windows\Temp |
| - config.json | | |
| - eMxInfo.txt | Execute | Final Location: |
| (network) | ------------&gt; | C:\Program Files |
+---------------------+ +---------------------+</code></pre>
<h3 id="directory-structure">Directory Structure</h3>
<p>Ensure your script directory contains the required files:</p>
<pre><code>S:\dt\shopfloor\scripts\remote-execution\
├── Invoke-RemoteMaintenance.ps1
├── GEAerospaceDashboardSetup.exe # For InstallDashboard
├── GEAerospaceLobbyDisplaySetup.exe # For InstallLobbyDisplay
└── udc_webserver_settings.json # For DeployUDCWebServerConfig</code></pre>
<h3 id="emx-auth-token-details">eMx Auth Token Details</h3>
<p>The <code>UpdateEMxAuthToken</code> task:</p>
<ol>
<li><strong>Source:</strong> <code>\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\eMx\eMxInfo.txt</code></li>
<li><strong>Destinations:</strong> (both paths if they exist)</li>
</ol>
<ul>
<li><code>C:\Program Files\GE Aircraft Engines\DNC\eMxInfo.txt</code></li>
<li><code>C:\Program Files (x86)\GE Aircraft Engines\DNC\eMxInfo.txt</code></li>
</ul>
<ol>
<li><strong>Backup:</strong> Creates <code>eMxInfo-old-YYYYMMDD-HHMMSS.txt</code> before overwriting</li>
<li><strong>Post-action:</strong> Restarts DNC service (<code>LDnc.exe</code>)</li>
</ol>
<h3 id="udc-web-server-config-details">UDC Web Server Config Details</h3>
<p>The <code>DeployUDCWebServerConfig</code> task:</p>
<ol>
<li><strong>Pre-check:</strong> Verifies UDC is installed (<code>C:\Program Files\UDC</code> exists)</li>
<li><strong>Skip:</strong> PCs without UDC are skipped (not counted as failures)</li>
<li><strong>Destination:</strong> <code>C:\ProgramData\UDC\udc_webserver_settings.json</code></li>
<li><strong>Backup:</strong> Creates backup before overwriting</li>
</ol>
<h3 id="dashboardlobby-display-install-details">Dashboard/Lobby Display Install Details</h3>
<p>Both kiosk app installers:</p>
<ol>
<li><strong>Installer type:</strong> Inno Setup (supports <code>/VERYSILENT</code>)</li>
<li><strong>Execution:</strong> Silent install with no user prompts</li>
<li><strong>Cleanup:</strong> Installer removed from temp after execution</li>
</ol>
<p><strong>Uninstall GUIDs:</strong></p>
<ul>
<li>Dashboard: <code>{9D9EEE25-4D24-422D-98AF-2ADEDA4745ED}</code></li>
<li>Lobby Display: <code>{42FFB952-0B72-493F-8869-D957344CA305}</code></li>
</ul>
<h3 id="adding-new-deployable-applications">Adding New Deployable Applications</h3>
<p>To add a new application for deployment, edit the script in two places:</p>
<p><strong>Step 1: Add to <code>$KioskAppConfig</code> hashtable (~line 1388)</strong></p>
<pre><code class="language-powershell">$KioskAppConfig = @{
# Existing entries...
# Add new application
&#x27;InstallNewApp&#x27; = @{
Action = &#x27;Install&#x27;
InstallerPath = &#x27;\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\NewApp\NewAppSetup.exe&#x27;
InstallerName = &#x27;NewAppSetup.exe&#x27;
AppName = &#x27;New Application Name&#x27;
UninstallGuid = &#x27;{YOUR-GUID-HERE}&#x27; # Find in registry after manual install
}
&#x27;UninstallNewApp&#x27; = @{
Action = &#x27;Uninstall&#x27;
InstallerName = &#x27;NewAppSetup.exe&#x27;
AppName = &#x27;New Application Name&#x27;
UninstallGuid = &#x27;{YOUR-GUID-HERE}&#x27;
}
}</code></pre>
<p><strong>Step 2: Add task names to ValidateSet (~line 142)</strong></p>
<pre><code class="language-powershell">[ValidateSet(
&#x27;DISM&#x27;, &#x27;SFC&#x27;, &#x27;OptimizeDisk&#x27;, &#x27;DiskCleanup&#x27;, &#x27;ClearUpdateCache&#x27;,
&#x27;RestartSpooler&#x27;, &#x27;FlushDNS&#x27;, &#x27;RestartWinRM&#x27;, &#x27;ClearBrowserCache&#x27;,
&#x27;SetTimezone&#x27;, &#x27;SyncTime&#x27;, &#x27;UpdateEMxAuthToken&#x27;, &#x27;DeployUDCWebServerConfig&#x27;, &#x27;Reboot&#x27;,
&#x27;InstallDashboard&#x27;, &#x27;InstallLobbyDisplay&#x27;, &#x27;UninstallDashboard&#x27;, &#x27;UninstallLobbyDisplay&#x27;,
&#x27;InstallNewApp&#x27;, &#x27;UninstallNewApp&#x27; # Add new tasks here
)]
[string]$Task</code></pre>
<p><strong>Step 3: Place installer on network share</strong></p>
<pre><code>\\tsgwp00525.wjs.geaerospace.net\dt\shopfloor\scripts\NewApp\NewAppSetup.exe</code></pre>
<p><strong>Finding the Uninstall GUID:</strong></p>
<p>After manually installing the application on a test PC, find the GUID in registry:</p>
<pre><code class="language-powershell"># Search for app in registry
Get-ChildItem &quot;HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall&quot; |
Get-ItemProperty | Where-Object { $_.DisplayName -like &quot;*AppName*&quot; } |
Select-Object DisplayName, PSChildName, UninstallString</code></pre>
<p>The <code>PSChildName</code> is typically the GUID (e.g., <code>{9D9EEE25-4D24-422D-98AF-2ADEDA4745ED}</code>).</p>
<p><strong>Installer Requirements:</strong></p>
<ul>
<li>Must support silent installation flags</li>
<li>Inno Setup: <code>/VERYSILENT /SUPPRESSMSGBOXES /NORESTART</code></li>
<li>MSI: <code>/qn /norestart</code></li>
<li>NSIS: <code>/S</code></li>
</ul>
<p>If your installer uses different flags, modify the <code>InstallKioskApp</code> scriptblock.</p>
<hr>
<h2 id="how-to-guides">How-To Guides</h2>
<h3 id="how-to-repair-system-files">How to Repair System Files</h3>
<p><strong>Scenario:</strong> A PC has corrupted system files causing crashes or errors.</p>
<h4 id="option-1-dism-component-store-repair">Option 1: DISM (Component Store Repair)</h4>
<pre><code class="language-powershell"># Run DISM repair on a single PC
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PROBLEM-PC&quot; -Task DISM -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ul>
<li>Downloads missing/corrupted files from Windows Update</li>
<li>Repairs the Windows component store</li>
<li>Required before SFC if component store is damaged</li>
</ul>
<p><strong>Expected output:</strong></p>
<pre><code>[PROBLEM-PC] DISM: SUCCESS
Deployment Image Servicing and Management tool
The restore operation completed successfully.</code></pre>
<h4 id="option-2-sfc-system-file-checker">Option 2: SFC (System File Checker)</h4>
<pre><code class="language-powershell"># Run SFC after DISM
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PROBLEM-PC&quot; -Task SFC -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ul>
<li>Scans all protected system files</li>
<li>Replaces corrupted files from component store</li>
<li>Creates log at <code>C:\Windows\Logs\CBS\CBS.log</code></li>
</ul>
<p><strong>Best Practice - Full Repair Sequence:</strong></p>
<pre><code class="language-powershell"># Step 1: Run DISM first
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PROBLEM-PC&quot; -Task DISM -Credential $cred
# Step 2: Run SFC after DISM completes
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PROBLEM-PC&quot; -Task SFC -Credential $cred
# Step 3: Reboot to apply changes
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PROBLEM-PC&quot; -Task Reboot -Credential $cred</code></pre>
<hr>
<h3 id="how-to-optimize-disks">How to Optimize Disks</h3>
<p><strong>Scenario:</strong> PCs are running slow due to disk fragmentation or lack of TRIM.</p>
<h4 id="single-pc-optimization">Single PC Optimization</h4>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;SLOW-PC&quot; -Task OptimizeDisk -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ul>
<li>Detects drive type (SSD vs HDD)</li>
<li>For SSDs: Runs TRIM to reclaim deleted blocks</li>
<li>For HDDs: Runs defragmentation</li>
</ul>
<h4 id="optimize-all-cmm-pcs-after-hours">Optimize All CMM PCs (After Hours)</h4>
<pre><code class="language-powershell"># CMM PCs often have large files - optimize overnight
.\Invoke-RemoteMaintenance.ps1 -PcType CMM -Task OptimizeDisk -Credential $cred -ThrottleLimit 3</code></pre>
<h4 id="full-cleanup-sequence">Full Cleanup Sequence</h4>
<pre><code class="language-powershell"># Step 1: Clear update cache
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PC01&quot; -Task ClearUpdateCache -Credential $cred
# Step 2: Run disk cleanup
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PC01&quot; -Task DiskCleanup -Credential $cred
# Step 3: Optimize disk
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PC01&quot; -Task OptimizeDisk -Credential $cred</code></pre>
<hr>
<h3 id="how-to-fix-stuck-windows-updates">How to Fix Stuck Windows Updates</h3>
<p><strong>Scenario:</strong> Windows Update is stuck or failing repeatedly.</p>
<pre><code class="language-powershell"># Clear the Windows Update cache
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;UPDATE-STUCK-PC&quot; -Task ClearUpdateCache -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ol>
<li>Stops Windows Update service</li>
<li>Stops BITS service</li>
<li>Clears <code>C:\Windows\SoftwareDistribution\Download</code></li>
<li>Restarts services</li>
</ol>
<p><strong>After clearing, trigger new update check:</strong></p>
<pre><code class="language-powershell"># On the target PC (optional follow-up)
wuauclt /detectnow</code></pre>
<hr>
<h3 id="how-to-clear-browser-cache">How to Clear Browser Cache</h3>
<p><strong>Scenario:</strong> CMM or inspection PCs have slow browser performance.</p>
<pre><code class="language-powershell"># Single PC
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;CMM-PC01&quot; -Task ClearBrowserCache -Credential $cred
# All CMM PCs
.\Invoke-RemoteMaintenance.ps1 -PcType CMM -Task ClearBrowserCache -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ul>
<li>Clears Chrome cache directories</li>
<li>Clears Edge cache directories</li>
<li>Does NOT clear saved passwords or bookmarks</li>
</ul>
<hr>
<h3 id="how-to-manage-services">How to Manage Services</h3>
<h4 id="fix-printing-issues">Fix Printing Issues</h4>
<pre><code class="language-powershell"># Restart print spooler on a PC with stuck print jobs
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PRINT-PROBLEM-PC&quot; -Task RestartSpooler -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ol>
<li>Stops Print Spooler service</li>
<li>Clears print queue</li>
<li>Restarts Print Spooler service</li>
</ol>
<h4 id="fix-dns-resolution-issues">Fix DNS Resolution Issues</h4>
<pre><code class="language-powershell"># Flush DNS cache when a PC can&#x27;t resolve hostnames
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;DNS-ISSUE-PC&quot; -Task FlushDNS -Credential $cred
# Flush DNS on all PCs in a business unit
.\Invoke-RemoteMaintenance.ps1 -BusinessUnit Blisk -Task FlushDNS -Credential $cred</code></pre>
<h4 id="fix-remote-management-issues">Fix Remote Management Issues</h4>
<pre><code class="language-powershell"># Restart WinRM if subsequent remote commands fail
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;WINRM-ISSUE-PC&quot; -Task RestartWinRM -Credential $cred</code></pre>
<p><strong>Note:</strong> Connection will briefly drop during restart.</p>
<hr>
<h3 id="how-to-fix-time-sync-issues">How to Fix Time Sync Issues</h3>
<p><strong>Scenario:</strong> PC clock is wrong, causing certificate errors or login issues.</p>
<h4 id="set-correct-timezone">Set Correct Timezone</h4>
<pre><code class="language-powershell"># Single PC
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;WRONG-TIME-PC&quot; -Task SetTimezone -Credential $cred
# All shopfloor PCs
.\Invoke-RemoteMaintenance.ps1 -All -Task SetTimezone -Credential $cred</code></pre>
<p><strong>Sets timezone to:</strong> Eastern Standard Time</p>
<h4 id="force-time-synchronization">Force Time Synchronization</h4>
<pre><code class="language-powershell"># Sync time with domain controller
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;WRONG-TIME-PC&quot; -Task SyncTime -Credential $cred</code></pre>
<p><strong>Full time fix sequence:</strong></p>
<pre><code class="language-powershell"># Step 1: Set correct timezone
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PC01&quot; -Task SetTimezone -Credential $cred
# Step 2: Sync time
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PC01&quot; -Task SyncTime -Credential $cred</code></pre>
<hr>
<h3 id="how-to-update-dnc-configurations">How to Update DNC Configurations</h3>
<h4 id="update-emx-authentication-token">Update eMx Authentication Token</h4>
<p><strong>Scenario:</strong> eMx authentication is failing on DNC PCs.</p>
<pre><code class="language-powershell"># Single PC
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;DNC-PC01&quot; -Task UpdateEMxAuthToken -Credential $cred
# All shopfloor PCs
.\Invoke-RemoteMaintenance.ps1 -All -Task UpdateEMxAuthToken -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ol>
<li>Backs up existing <code>eMxInfo.txt</code> with timestamp</li>
<li>Copies new token file from network share</li>
<li>Verifies file was updated</li>
</ol>
<h4 id="deploy-udc-web-server-configuration">Deploy UDC Web Server Configuration</h4>
<p><strong>Scenario:</strong> UDC web server settings need to be updated.</p>
<pre><code class="language-powershell"># Deploy to PCs with UDC installed
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;UDC-PC01&quot;,&quot;UDC-PC02&quot; -Task DeployUDCWebServerConfig -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ol>
<li>Checks if UDC is installed</li>
<li>Backs up existing configuration</li>
<li>Deploys new web server settings</li>
<li>Does NOT restart UDC (requires manual restart)</li>
</ol>
<hr>
<h3 id="how-to-deploy-software">How to Deploy Software</h3>
<h4 id="install-ge-aerospace-dashboard">Install GE Aerospace Dashboard</h4>
<p><strong>Scenario:</strong> Convert a PC to a Dashboard kiosk.</p>
<pre><code class="language-powershell"># Single PC installation
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;NEWKIOSK-01&quot; -Task InstallDashboard -Credential $cred
# Multiple PCs from a list
$kiosks = @(&quot;KIOSK-01&quot;, &quot;KIOSK-02&quot;, &quot;KIOSK-03&quot;)
.\Invoke-RemoteMaintenance.ps1 -ComputerName $kiosks -Task InstallDashboard -Credential $cred</code></pre>
<p><strong>What it does:</strong></p>
<ol>
<li>Copies installer from network share</li>
<li>Runs silent installation</li>
<li>Configures auto-start</li>
<li>Cleans up installer</li>
</ol>
<p><strong>After installation:</strong></p>
<ul>
<li>Run data collection to update PC type</li>
<li>Reboot PC to complete setup</li>
</ul>
<pre><code class="language-powershell"># Complete Dashboard deployment sequence
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;KIOSK-01&quot; -Task InstallDashboard -Credential $cred
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;KIOSK-01&quot; -Task Reboot -Credential $cred
# After reboot, update ShopDB
.\Update-ShopfloorPCs-Remote.ps1 -ComputerName &quot;KIOSK-01&quot; -Credential $cred</code></pre>
<h4 id="install-lobby-display">Install Lobby Display</h4>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;LOBBY-01&quot; -Task InstallLobbyDisplay -Credential $cred</code></pre>
<h4 id="uninstall-dashboard-or-lobby-display">Uninstall Dashboard or Lobby Display</h4>
<pre><code class="language-powershell"># Remove Dashboard
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;OLD-KIOSK&quot; -Task UninstallDashboard -Credential $cred
# Remove Lobby Display
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;OLD-LOBBY&quot; -Task UninstallLobbyDisplay -Credential $cred</code></pre>
<hr>
<h3 id="how-to-reboot-pcs">How to Reboot PCs</h3>
<h4 id="single-pc-reboot">Single PC Reboot</h4>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PC-TO-REBOOT&quot; -Task Reboot -Credential $cred</code></pre>
<p><strong>Note:</strong> Reboot has a 30-second delay to allow graceful shutdown.</p>
<h4 id="reboot-all-dashboard-pcs">Reboot All Dashboard PCs</h4>
<pre><code class="language-powershell"># Reboot all Dashboard PCs (e.g., for software update)
.\Invoke-RemoteMaintenance.ps1 -PcType Dashboard -Task Reboot -Credential $cred</code></pre>
<h4 id="reboot-all-lobby-display-pcs">Reboot All Lobby Display PCs</h4>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -PcType &quot;Lobby Display&quot; -Task Reboot -Credential $cred</code></pre>
<h4 id="reboot-pcs-by-business-unit">Reboot PCs by Business Unit</h4>
<pre><code class="language-powershell"># Reboot all HPT PCs during maintenance window
.\Invoke-RemoteMaintenance.ps1 -BusinessUnit HPT -Task Reboot -Credential $cred</code></pre>
<hr>
<h3 id="how-to-run-batch-operations">How to Run Batch Operations</h3>
<h4 id="using-a-computer-list-file">Using a Computer List File</h4>
<p>Create a text file with one hostname per line:</p>
<pre><code class="language-text"># shopfloor-pcs.txt
PC001
PC002
PC003
PC004
PC005</code></pre>
<p>Run tasks against the list:</p>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -ComputerListFile &quot;.\shopfloor-pcs.txt&quot; -Task FlushDNS -Credential $cred</code></pre>
<h4 id="running-multiple-tasks-in-sequence">Running Multiple Tasks in Sequence</h4>
<pre><code class="language-powershell"># Maintenance routine for a PC
$pc = &quot;SHOPFLOOR-PC01&quot;
# Step 1: Clear caches
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task ClearUpdateCache -Credential $cred
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task ClearBrowserCache -Credential $cred
# Step 2: Disk cleanup
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task DiskCleanup -Credential $cred
# Step 3: Repair
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task DISM -Credential $cred
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task SFC -Credential $cred
# Step 4: Sync time
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task SetTimezone -Credential $cred
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task SyncTime -Credential $cred
# Step 5: Reboot
.\Invoke-RemoteMaintenance.ps1 -ComputerName $pc -Task Reboot -Credential $cred</code></pre>
<hr>
<h2 id="targeting-strategies">Targeting Strategies</h2>
<h3 id="by-individual-pcs">By Individual PCs</h3>
<p><strong>Best for:</strong> Specific troubleshooting, targeted fixes</p>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;PROBLEM-PC&quot; -Task DISM -Credential $cred</code></pre>
<h3 id="by-pc-type">By PC Type</h3>
<p><strong>Best for:</strong> Type-specific maintenance, software updates</p>
<pre><code class="language-powershell"># All CMM PCs
.\Invoke-RemoteMaintenance.ps1 -PcType CMM -Task DiskCleanup -Credential $cred
# All Dashboard kiosks
.\Invoke-RemoteMaintenance.ps1 -PcType Dashboard -Task Reboot -Credential $cred</code></pre>
<h3 id="by-business-unit">By Business Unit</h3>
<p><strong>Best for:</strong> Department-specific maintenance windows</p>
<pre><code class="language-powershell"># All Blisk area PCs
.\Invoke-RemoteMaintenance.ps1 -BusinessUnit Blisk -Task SyncTime -Credential $cred</code></pre>
<h3 id="all-shopfloor-pcs">All Shopfloor PCs</h3>
<p><strong>Best for:</strong> Global maintenance, security updates</p>
<pre><code class="language-powershell"># Flush DNS everywhere
.\Invoke-RemoteMaintenance.ps1 -All -Task FlushDNS -Credential $cred -ThrottleLimit 10</code></pre>
<h3 id="using-a-list-file">Using a List File</h3>
<p><strong>Best for:</strong> Custom groups, staged rollouts</p>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -ComputerListFile &quot;.\phase1-pcs.txt&quot; -Task DISM -Credential $cred</code></pre>
<hr>
<h2 id="troubleshooting">Troubleshooting</h2>
<h3 id="task-times-out">Task Times Out</h3>
<p><strong>Cause:</strong> Task takes longer than session timeout.</p>
<p><strong>Solution:</strong> DISM and SFC can take a long time. Check if task completed on target:</p>
<pre><code class="language-powershell"># Check DISM log
Invoke-Command -ComputerName &quot;PC01&quot; -Credential $cred -ScriptBlock {
Get-Content &quot;C:\Windows\Logs\DISM\dism.log&quot; -Tail 50
}</code></pre>
<h3 id="access-denied-on-some-pcs">"Access Denied" on Some PCs</h3>
<p><strong>Cause:</strong> Credentials don't have admin rights on that PC.</p>
<p><strong>Solutions:</strong></p>
<ol>
<li>Use different credentials</li>
<li>Add account to local Administrators group on target</li>
<li>Check if UAC is blocking remote admin</li>
</ol>
<h3 id="software-installation-fails">Software Installation Fails</h3>
<p><strong>Cause:</strong> Network share not accessible or installer missing.</p>
<p><strong>Solutions:</strong></p>
<ol>
<li>Verify network share path is accessible</li>
<li>Check installer exists at expected location</li>
<li>Verify credentials can access the share</li>
</ol>
<h3 id="reboot-doesnt-happen">Reboot Doesn't Happen</h3>
<p><strong>Cause:</strong> User cancelled shutdown or application blocked it.</p>
<p><strong>Solutions:</strong></p>
<pre><code class="language-powershell"># Force immediate reboot (no 30-second delay)
Invoke-Command -ComputerName &quot;PC01&quot; -Credential $cred -ScriptBlock {
Restart-Computer -Force
}</code></pre>
<hr>
<h2 id="best-practices">Best Practices</h2>
<h3 id="1-start-small">1. Start Small</h3>
<p>Test on one PC before running against groups:</p>
<pre><code class="language-powershell"># Test on single PC first
.\Invoke-RemoteMaintenance.ps1 -ComputerName &quot;TEST-PC&quot; -Task DISM -Credential $cred</code></pre>
<h3 id="2-use-appropriate-throttle-limits">2. Use Appropriate Throttle Limits</h3>
<table>
<thead><tr>
<th>Scenario</th>
<th>Recommended ThrottleLimit</th>
</tr></thead>
<tbody>
<tr>
<td>Fast network, light tasks</td>
<td>10-25</td>
</tr>
<tr>
<td>Normal operations</td>
<td>5 (default)</td>
</tr>
<tr>
<td>Heavy tasks (DISM, Defrag)</td>
<td>2-3</td>
</tr>
<tr>
<td>Slow network</td>
<td>2-3</td>
</tr>
</tbody></table>
<h3 id="3-schedule-disruptive-tasks">3. Schedule Disruptive Tasks</h3>
<p>Run reboots and heavy tasks during maintenance windows:</p>
<ul>
<li>DISM/SFC: After hours</li>
<li>Disk optimization: After hours</li>
<li>Reboots: During shift changes or maintenance windows</li>
</ul>
<h3 id="4-verify-before-rebooting">4. Verify Before Rebooting</h3>
<p>Always confirm which PCs will be affected:</p>
<pre><code class="language-powershell"># Check PC type before reboot
.\Update-ShopfloorPCs-Remote.ps1 -PcType Dashboard -WhatIf</code></pre>
<h3 id="5-keep-logs">5. Keep Logs</h3>
<p>Redirect output for audit trail:</p>
<pre><code class="language-powershell">.\Invoke-RemoteMaintenance.ps1 -All -Task SyncTime -Credential $cred | Tee-Object -FilePath &quot;maintenance-log-$(Get-Date -Format &#x27;yyyyMMdd&#x27;).txt&quot;</code></pre>
</body>
</html>