Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I update the current script before running it?

Tags:

powershell

We have some PowerShell scripts living on network share A, and the latest versions of those scripts living on read-only network share B. The read-only share is the output of our build system, and it has the build number in the path. Partly out of habit, partly because the scripts must create files on disk, but mostly because the paths are predictable, we copy PowerShell scripts to network share A before executing them. The trouble is that we don't always copy the scripts to network share A, so occasionally those scripts are out of date.

I'm trying to create a script that will update the PowerShell scripts on network share A (by copying the latest versions from share B), and then execute those latest scripts. Right now, my idea is to have a tiny script that grabs the latest script from share B, copies it to share A, and then executes that script on share A.

Is it possible to have a script update itself? I.e., instead of having two scripts, can I have one script (that lives on share A) that copies a newer version itself from share B to share A, then restarts execution of itself? (I would put in some logic about file-creation date so that on first execution, it would update itself, and on second execution it would run the actual meat of the script.)

like image 966
PotatoEngineer Avatar asked Aug 02 '13 01:08

PotatoEngineer


People also ask

How do I run a new PowerShell?

From the Start MenuClick Start, type ISE, and then click Windows PowerShell ISE. From the Start menu, click Start, click All Programs, click Accessories, click the Windows PowerShell folder, and then click Windows PowerShell ISE.


1 Answers

Yes, you can update the script you're running, then execute it again. (Just make sure to exit the first script after updating.) Here's some sample code I created:

Write-Host "Starting script"
if ($(Get-Item G:\selfUpdater2.ps1).CreationTimeUtc -gt $(Get-Item G:\selfUpdater.ps1).CreationTimeUtc) {
    Copy-Item G:\selfUpdater2.ps1 G:\selfUpdater.ps1
    $(Get-Item G:\selfUpdater.ps1).CreationTimeUtc = [DateTime]::UtcNow
    &G:\selfUpdater.ps1
    exit
}
Write-Host "Continuing original script; will not get here if we updated."

Note that, if you have parameters to pass around, you'll have to pass them to the target script. Since your updated script may well have more or fewer parameters than your current script (some bound, some unbound by the current script), you'll need to iterate through both $script:MyInvocation.BoundParameters and $script:MyInvocation.UnboundArguments to pick up all of them and pass them on.

(Personally, I've had more luck with random-parameter-passing using Invoke-Expression ".\scriptName.ps1 $stringOfArguments" than with &.\scriptName.ps1 $arguments, but your mileage may vary - or you may know more PowerShell than I do. If you use Invoke-Expression, then be sure to re-add quotes around any parameters that have spaces in them.)

There's one drawback: If a mandatory script parameter is removed in a future version of the script, then you need to run the script at least once with the no-longer-mandatory parameter before it will update itself allow you to drop the parameter.

like image 109
PotatoEngineer Avatar answered Sep 20 '22 01:09

PotatoEngineer