8

我有很多脚本。进行更改后,我喜欢将它们全部运行以查看是否有任何损坏。我编写了一个脚本来遍历每个脚本,并在新数据上运行它。

在我的循环中,我目前正在运行powershell.exe -command <path to script>. 我不知道这是否是最好的方法,或者这两个实例是否完全分开。

在干净的 PowerShell 实例中运行脚本的首选方法是什么?还是我应该说“会话”?

4

4 回答 4

8

使用powershell.exe似乎是一种很好的方法,但当然也有其优点和缺点。

优点:

  • 每个脚本都在单独的干净会话中调用。
  • 即使崩溃也不会停止整个测试过程。

缺点:

  • 调用powershell.exe有点慢。
  • 测试取决于退出代码,但 0 并不总是意味着成功。

没有提到的缺点是一个潜在问题。

演示脚本如下。它已经通过 PS v2 和 v3 进行了测试。脚本名称可能包含特殊字符,如空格、撇号、方括号、反引号、美元。注释要求中提到的一项是能够在其代码中获取脚本路径。使用建议的方法,脚本可以获得自己的路径 $MyInvocation.MyCommand.Path

# make a script list, use the full paths or explicit relative paths
$scripts = @(
    '.\test1.ps1' # good name
    '.\test 2.ps1' # with a space
    ".\test '3'.ps1" # with apostrophes
    ".\test [4].ps1" # with brackets
    '.\test `5`.ps1' # with backticks
    '.\test $6.ps1' # with a dollar
    '.\test ''3'' [4] `5` $6.ps1' # all specials
)

# process each script in the list
foreach($script in $scripts) {
    # make a command; mind &, ' around the path, and escaping '
    $command = "& '" + $script.Replace("'", "''") + "'"

    # invoke the command, i.e. the script in a separate process
    powershell.exe -command $command

    # check for the exit code (assuming 0 is for success)
    if ($LastExitCode) {
        # in this demo just write a warning
        Write-Warning "Script $script failed."
    }
    else {
        Write-Host "Script $script succeeded."
    }
}
于 2012-11-11T07:41:09.920 回答
6

如果您使用的是 PowerShell 2.0 或更高版本,则可以使用作业来执行此操作。每个作业在单独的 PowerShell 进程中运行,例如:

$scripts = ".\script1.ps1", ".\script2.ps1"

$jobs = @()
foreach ($script in $scripts)
{
    $jobs += Start-Job -FilePath $script
}

Wait-Job $jobs

foreach ($job in $jobs)
{
    "*" * 60
    "Status of '$($job.Command)' is $($job.State)"
    "Script output:"
    Receive-Job $job
}

此外,请查看PowerShell 社区扩展。它有一个Test-Script命令可以检测脚本文件中的语法错误。当然,它不会捕获运行时错误。

于 2012-10-27T02:13:28.083 回答
3

给 PowerShell V3 用户的一个提示:我们(PowerShell 团队)在 Runspace 类上添加了一个名为 ResetRunspace() 的新 API。此 API 将全局变量表重置回该运行空间的初始状态(以及清理其他一些东西)。它不做的是清除函数定义、类型和格式文件或卸载模块。这允许 API 更快。另请注意,必须使用 InitialSessionState 对象而不是 RunspaceConfiguration 实例创建运行空间。ResetRunspace() 作为工作流功能的一部分添加到 V3 中,以支持脚本中有效的并行执行。

于 2012-11-10T05:12:15.423 回答
2

这两个实例是完全独立的,因为它们是两个不同的进程。通常,为每个脚本运行启动 Powershell 进程并不是最有效的方法。根据脚本的数量以及重新运行它们的频率,它可能会影响您的整体性能。如果不是,我会保持原样。

另一种选择是在同一个运行空间中运行(这是一个正确的词),但每次都清理所有内容。请参阅此答案以获取方法。或使用以下提取物:

$sysvars = get-variable | select -Expand name
function remove-uservars {
 get-variable |
   where {$sysvars -notcontains $_.name} |
     remove-variable
}
于 2012-10-27T00:46:40.837 回答