如何在运行之前更新当前脚本?

问题描述 投票:5回答:2

我们有一些PowerShell脚本存在于网络共享A上,并且这些脚本的最新版本位于只读网络共享B上。只读共享是构建系统的输出,它在路径中具有内部版本号。部分是出于习惯,部分原因是脚本必须在磁盘上创建文件,但主要是因为路径是可预测的,我们在执行它们之前将PowerShell脚本复制到网络共享A.问题是我们并不总是将脚本复制到网络共享A,所以有时这些脚本已经过时了。

我正在尝试创建一个脚本来更新网络共享A上的PowerShell脚本(通过从共享B复制最新版本),然后执行这些最新脚本。现在,我的想法是创建一个小脚本,从共享B中获取最新脚本,将其复制到共享A,然后在共享A上执行该脚本。

是否可以自行更新脚本?即,我可以拥有一个脚本(位于共享A上)而不是拥有两个脚本,它可以将较新版本本身从共享B复制到共享A,然后重新启动自身的执行? (我会提出一些关于文件创建日期的逻辑,这样在第一次执行时,它会自行更新,在第二次执行时,它将运行脚本的实际内容。)

powershell
2个回答
3
投票

是的,您可以更新正在运行的脚本,然后再次执行。 (只需确保在更新后退出第一个脚本。)这是我创建的一些示例代码:

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."

请注意,如果要传递参数,则必须将它们传递给目标脚本。由于您更新的脚本可能具有比当前脚本更多或更少的参数(一些绑定,一些绑定当前脚本),您需要遍历$script:MyInvocation.BoundParameters$script:MyInvocation.UnboundArguments以获取所有这些并传递它们。

(就我个人而言,使用Invoke-Expression ".\scriptName.ps1 $stringOfArguments"比使用&.\scriptName.ps1 $arguments的随机参数传递更幸运,但你的里程可能会有所不同 - 或者你可能比我更了解PowerShell。如果你使用Invoke-Expression,那么一定要重新添加引号围绕任何有空格的参数。)

有一个缺点:如果在脚本的未来版本中删除了必需的脚本参数,那么您需要使用no-longer-mandatory参数至少运行一次脚本,然后才能更新自身允许您删除参数。


3
投票

这是我放在一起的功能。将它传递给可能包含较新版本的文件的路径。这将自动更新,然后使用传递给原始脚本的任何参数重新运行。

  function Update-Myself
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 0)]
        [string]$SourcePath
    )
    #check that the destination file exists
    if (Test-Path $SourcePath)
    {
    #The path of THIS script
    $CurrentScript = $MyInvocation.ScriptName
        if (!($SourcePath -eq $CurrentScript ))
        {
            if ($(Get-Item $SourcePath).LastWriteTimeUtc -gt $(Get-Item $CurrentScript ).LastWriteTimeUtc)
            {
                write-host "Updating..."
                Copy-Item $SourcePath $CurrentScript 
                #If the script was updated, run it with orginal parameters
                &$CurrentScript $script:args
                exit
            }
        }
    }
    write-host "No update required"
}

Update-Myself \\path\to\newest\release\of\file.ps1
© www.soinside.com 2019 - 2024. All rights reserved.