【问题标题】:How can I update the current script before running it?如何在运行之前更新当前脚本?
【发布时间】:2017-12-30 03:26:51
【问题描述】:

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

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

是否可以自己更新脚本?也就是说,我可以使用一个脚本(位于共享 A 上)将更新版本本身从共享 B 复制到,而不是拥有两个脚本共享A,然后重新开始执行自身? (我会加入一些关于文件创建日期的逻辑,以便在第一次执行时,它会自我更新,而在第二次执行时,它会运行脚本的实际内容。)

【问题讨论】:

  • @aphoria 我问了这个问题,这样我就不必尝试了,但是 StackOverflow 让我失望了。所以我必须学习一些东西。 (多么可怕!)

标签: powershell


【解决方案1】:

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

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 ,然后确保在其中包含空格的所有参数周围重新添加引号。)

有一个缺点:如果在脚本的未来版本中删除了强制脚本参数,那么您需要使用不再强制的参数运行该脚本至少一次,然后它才会更新本身允许您删除参数。

【讨论】:

    【解决方案2】:

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

      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
    

    【讨论】:

      猜你喜欢
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多