-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInvoke-RemoteScript.ps1
More file actions
334 lines (273 loc) · 14.4 KB
/
Invoke-RemoteScript.ps1
File metadata and controls
334 lines (273 loc) · 14.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
<##############################################################################
LEGAL DISCLAIMER
This Sample Code is provided for the purpose of illustration only and is not
intended to be used in a production environment. THIS SAMPLE CODE AND ANY
RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a
nonexclusive, royalty-free right to use and modify the Sample Code and to
reproduce and distribute the object code form of the Sample Code, provided
that You agree: (i) to not use Our name, logo, or trademarks to market Your
software product in which the Sample Code is embedded; (ii) to include a valid
copyright notice on Your software product in which the Sample Code is embedded;
and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and
against any claims or lawsuits, including attorneys’ fees, that arise or result
from the use or distribution of the Sample Code.
This posting is provided "AS IS" with no warranties, and confers no rights. Use
of included script samples are subject to the terms specified
at https://www.microsoft.com/en-us/legal/copyright.
##############################################################################>
<#
.SYNOPSIS
Executes a PowerShell script on a remote computer with optional cleanup.
.DESCRIPTION
This script copies a local PowerShell script to a remote computer, executes it,
and optionally removes it after execution. Uses New-PSSession for connectivity
testing and all remote operations.
.INPUTS
Computer name (string), Local script path (string), Remote folder path (string)
.OUTPUTS
Execution status messages and script output
.NOTES
Name: Invoke-RemoteScript.ps1
Authors/Contributors: Nick OConnor
DateCreated:
Revisions: 2025-09-27 - Initial version
#>
# Clear any previous errors
$Error.Clear()
# Script banner
Write-Host "`n=================================================" -ForegroundColor Cyan
Write-Host " Remote PowerShell Script Executor v2.0" -ForegroundColor Cyan
Write-Host "=================================================" -ForegroundColor Cyan
Write-Host "This script will copy and execute a PS1 file on a remote computer`n" -ForegroundColor Gray
#region Step 1: Prompt for remote computer name
Write-Host "[Step 1] Remote Computer Configuration" -ForegroundColor Yellow
Write-Host "--------------------------------------" -ForegroundColor Gray
$remoteComputer = Read-Host "Enter the remote computer name or IP address"
# Validate computer name is not empty
if ([string]::IsNullOrWhiteSpace($remoteComputer)) {
Write-Host "`n[ERROR] Computer name cannot be empty!" -ForegroundColor Red
Write-Host "Script terminated.`n" -ForegroundColor Red
exit 1
}
Write-Host "[OK] Target computer: $remoteComputer" -ForegroundColor Green
#endregion
#region Step 2: Configure local script path
Write-Host "`n[Step 2] Local Script Configuration" -ForegroundColor Yellow
Write-Host "-----------------------------------" -ForegroundColor Gray
# Variable for local PS1 script location
# IMPORTANT: Update this path to point to your actual script
$localScriptPath = "C:\_Hold\YourScript.ps1" # << MODIFY THIS PATH
# Alternative: Uncomment below to prompt for script path
# $localScriptPath = Read-Host "Enter the full path to the local PS1 script"
# Check if local script exists
if (-not (Test-Path -Path $localScriptPath -PathType Leaf)) {
Write-Host "`n[ERROR] Local script not found at: $localScriptPath" -ForegroundColor Red
Write-Host "Please update the `$localScriptPath variable with the correct path" -ForegroundColor Yellow
Write-Host "Script terminated.`n" -ForegroundColor Red
exit 1
}
# Get script filename for later use
$scriptFileName = Split-Path -Path $localScriptPath -Leaf
Write-Host "[OK] Local script found: $scriptFileName" -ForegroundColor Green
#endregion
#region Step 3: Configure remote folder location
Write-Host "`n[Step 3] Remote Folder Configuration" -ForegroundColor Yellow
Write-Host "------------------------------------" -ForegroundColor Gray
# Default remote folder location
$defaultRemoteFolder = "C:\windows\Temp" # << MODIFY THIS PATH IF NEEDED
Write-Host "Default remote folder: $defaultRemoteFolder" -ForegroundColor Cyan
$userInput = Read-Host "Press [Enter] to use default or type a custom path"
# Use default if user pressed Enter, otherwise use their input
if ([string]::IsNullOrWhiteSpace($userInput)) {
$remoteFolder = $defaultRemoteFolder
Write-Host "[OK] Using default folder: $remoteFolder" -ForegroundColor Green
} else {
$remoteFolder = $userInput.Trim()
Write-Host "[OK] Using custom folder: $remoteFolder" -ForegroundColor Green
}
# Build the complete remote script path
$remoteScriptPath = Join-Path -Path $remoteFolder -ChildPath $scriptFileName
#endregion
#region Step 4: Test connectivity and validate remote folder
Write-Host "`n[Step 4] Testing Connectivity & Validating Remote Folder" -ForegroundColor Yellow
Write-Host "--------------------------------------------------------" -ForegroundColor Gray
$session = $null
try {
Write-Host "Establishing connection to $remoteComputer..." -NoNewline
# Create a PSSession - this tests connectivity
# If this fails, it means we cannot connect to the remote computer
$session = New-PSSession -ComputerName $remoteComputer -ErrorAction Stop
Write-Host " SUCCESS" -ForegroundColor Green
Write-Host "[OK] Connected to remote computer successfully" -ForegroundColor Green
Write-Host "`nChecking if folder exists: $remoteFolder..." -NoNewline
# Check if the folder exists on the remote computer
$folderExists = Invoke-Command -Session $session -ScriptBlock {
param($folder)
Test-Path -Path $folder -PathType Container
} -ArgumentList $remoteFolder -ErrorAction Stop
if (-not $folderExists) {
Write-Host " NOT FOUND" -ForegroundColor Red
Write-Host "`n[ERROR] The folder '$remoteFolder' does not exist on '$remoteComputer'" -ForegroundColor Red
Write-Host "Please create the folder on the remote computer or specify a different path" -ForegroundColor Yellow
Write-Host "`nTo create the folder remotely, run this command:" -ForegroundColor Cyan
Write-Host " Invoke-Command -ComputerName $remoteComputer -ScriptBlock {New-Item -Path '$remoteFolder' -ItemType Directory -Force}" -ForegroundColor White
Write-Host "`nScript terminated.`n" -ForegroundColor Red
# Clean up session before exiting
Remove-PSSession -Session $session -ErrorAction SilentlyContinue
exit 1
}
Write-Host " EXISTS" -ForegroundColor Green
Write-Host "[OK] Remote folder validated successfully" -ForegroundColor Green
} catch {
Write-Host " FAILED" -ForegroundColor Red
Write-Host "`n[ERROR] Cannot connect to remote computer '$remoteComputer'" -ForegroundColor Red
Write-Host "Error details: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "`nTroubleshooting steps:" -ForegroundColor Yellow
Write-Host " 1. Verify the computer name or IP address is correct" -ForegroundColor Yellow
Write-Host " 2. Ensure the remote computer is powered on and connected to network" -ForegroundColor Yellow
Write-Host " 3. Enable WinRM on the remote computer (run as Administrator):" -ForegroundColor Yellow
Write-Host " Enable-PSRemoting -Force" -ForegroundColor White
Write-Host " 4. Check if Windows Firewall is blocking WinRM (port 5985/5986)" -ForegroundColor Yellow
Write-Host " 5. Ensure you have administrative privileges on '$remoteComputer'" -ForegroundColor Yellow
Write-Host " 6. Verify both computers are in the same domain or workgroup" -ForegroundColor Yellow
Write-Host " 7. For non-domain computers, you may need to add to TrustedHosts:" -ForegroundColor Yellow
Write-Host " Set-Item WSMan:\localhost\Client\TrustedHosts -Value '$remoteComputer' -Force" -ForegroundColor White
Write-Host "`nScript terminated.`n" -ForegroundColor Red
# Clean up session if it was created
if ($session) {
Remove-PSSession -Session $session -ErrorAction SilentlyContinue
}
exit 1
}
#endregion
#region Step 5: Copy script to remote computer
Write-Host "`n[Step 5] Copying Script to Remote Computer" -ForegroundColor Yellow
Write-Host "------------------------------------------" -ForegroundColor Gray
try {
Write-Host "Copying '$scriptFileName' to remote computer..." -NoNewline
# Copy the file using the existing session
Copy-Item -Path $localScriptPath -Destination $remoteScriptPath -ToSession $session -Force -ErrorAction Stop
Write-Host " COMPLETE" -ForegroundColor Green
Write-Host "[OK] Script copied to: $remoteScriptPath" -ForegroundColor Green
} catch {
Write-Host " FAILED" -ForegroundColor Red
Write-Host "`n[ERROR] Failed to copy script: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Script terminated.`n" -ForegroundColor Red
# Clean up session
if ($session) {
Remove-PSSession -Session $session -ErrorAction SilentlyContinue
}
exit 1
}
#endregion
#region Step 6: Execute script on remote computer
Write-Host "`n[Step 6] Executing Script on Remote Computer" -ForegroundColor Yellow
Write-Host "--------------------------------------------" -ForegroundColor Gray
$executionSuccess = $false
try {
Write-Host "Executing '$scriptFileName'..." -ForegroundColor Cyan
Write-Host "=" * 50 -ForegroundColor Gray
# Execute the script and capture output
$scriptOutput = Invoke-Command -Session $session -ScriptBlock {
param($scriptPath)
# Temporarily set execution policy for this process
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force -ErrorAction SilentlyContinue
# Execute the script and return any output
& $scriptPath
} -ArgumentList $remoteScriptPath -ErrorAction Stop
# Display the output if any
if ($scriptOutput) {
Write-Host $scriptOutput
} else {
Write-Host "(No output returned from script)" -ForegroundColor Gray
}
Write-Host "=" * 50 -ForegroundColor Gray
Write-Host "[OK] Script executed successfully!" -ForegroundColor Green
$executionSuccess = $true
} catch {
Write-Host "=" * 50 -ForegroundColor Gray
Write-Host "[ERROR] Script execution failed: $($_.Exception.Message)" -ForegroundColor Red
$executionSuccess = $false
}
#endregion
#region Step 7: Cleanup - Delete script from remote computer (if execution was successful)
if ($executionSuccess) {
Write-Host "`n[Step 7] Cleanup Options" -ForegroundColor Yellow
Write-Host "------------------------" -ForegroundColor Gray
# Prompt for cleanup only after successful execution
Write-Host "The script has been executed successfully." -ForegroundColor Green
Write-Host "Do you want to delete the script from the remote computer?" -ForegroundColor Cyan
Write-Host "Remote path: $remoteScriptPath" -ForegroundColor Gray
$cleanup = Read-Host "`nDelete '$scriptFileName' from $remoteComputer`? (Y/N)"
if ($cleanup -eq 'Y' -or $cleanup -eq 'y') {
try {
Write-Host "`nDeleting script from remote computer..." -NoNewline
# Delete the script using the same session
Invoke-Command -Session $session -ScriptBlock {
param($scriptPath)
if (Test-Path -Path $scriptPath) {
Remove-Item -Path $scriptPath -Force -ErrorAction Stop
return $true
} else {
return $false
}
} -ArgumentList $remoteScriptPath -ErrorAction Stop | Out-Null
Write-Host " COMPLETE" -ForegroundColor Green
Write-Host "[OK] Script deleted from remote computer" -ForegroundColor Green
} catch {
Write-Host " FAILED" -ForegroundColor Red
Write-Host "[WARNING] Could not delete script: $($_.Exception.Message)" -ForegroundColor Yellow
Write-Host "You may need to manually delete: $remoteScriptPath" -ForegroundColor Yellow
}
} else {
Write-Host "`n[INFO] Script retained at: $remoteScriptPath" -ForegroundColor Cyan
Write-Host "Remember to clean it up later if needed" -ForegroundColor Gray
}
} else {
Write-Host "`n[INFO] Skipping cleanup due to execution failure" -ForegroundColor Yellow
Write-Host "The script remains at: $remoteScriptPath" -ForegroundColor Yellow
Write-Host "You may want to manually investigate or remove it" -ForegroundColor Yellow
}
#endregion
#region Cleanup and finish
# Always clean up the PSSession
if ($session) {
Write-Host "`nClosing remote session..." -NoNewline
Remove-PSSession -Session $session -ErrorAction SilentlyContinue
Write-Host " DONE" -ForegroundColor Green
}
# Final summary
Write-Host "`n=================================================" -ForegroundColor Cyan
if ($executionSuccess) {
Write-Host " EXECUTION COMPLETED SUCCESSFULLY!" -ForegroundColor Green
} else {
Write-Host " EXECUTION COMPLETED WITH ERRORS" -ForegroundColor Yellow
}
Write-Host "=================================================" -ForegroundColor Cyan
# Display summary information
Write-Host "`nExecution Summary:" -ForegroundColor White
Write-Host " Remote Computer: $remoteComputer" -ForegroundColor Gray
Write-Host " Script Name: $scriptFileName" -ForegroundColor Gray
Write-Host " Local Source: $localScriptPath" -ForegroundColor Gray
Write-Host " Remote Location: $remoteScriptPath" -ForegroundColor Gray
if ($executionSuccess) {
Write-Host " Execution Status: " -NoNewline -ForegroundColor Gray
Write-Host "Success" -ForegroundColor Green
if ($cleanup -eq 'Y' -or $cleanup -eq 'y') {
Write-Host " Cleanup Status: " -NoNewline -ForegroundColor Gray
Write-Host "Deleted" -ForegroundColor Green
} else {
Write-Host " Cleanup Status: " -NoNewline -ForegroundColor Gray
Write-Host "Retained" -ForegroundColor Yellow
}
} else {
Write-Host " Execution Status: " -NoNewline -ForegroundColor Gray
Write-Host "Failed" -ForegroundColor Red
Write-Host " Cleanup Status: " -NoNewline -ForegroundColor Gray
Write-Host "Not performed" -ForegroundColor Gray
}
Write-Host "`nTimestamp: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Gray
Write-Host ""
#endregion