问题描述
我正在尝试使用Powershell 7-Preview执行Powershell脚本(7.0)文件,该文件将遍历所有数据库并在所有DB中执行sql Server脚本。
该脚本可以正确提取所有数据库,但是,在执行Parallel块时,出现此错误(请查找下面的屏幕截图以获取详细信息)。
无法验证参数“用户名”上的参数。参数为null或为空。提供一个不为null或为空的参数,然后重试该命令。
命令-C:\ GitHub \ TempApp \ CompanyTemplate \ bin \ debug \ DeploymentScripts \ PowerShell \ DeployCompanyDatabases.ps1
Param
(
[string]$SystemWorkingDir,[string]$DatabaseUsername,[string]$DatabasePassword,[string]$DacpacLocation,[string]$OngoingChangesScriptLocation,[string]$PreDeploymentBugFixScriptLocation,[string]$DropExternalTablesScriptLocation
)
$SystemWorkingDir = "C:\GitHub\TempAPP\CompanyTemplate\bin\Debug"
$DatabaseUsername = "tempDB"
$DatabasePassword = "tempPassword"
$DacpacLocation = "CompanyTemplate.dacpac"
$OngoingChangesScriptLocation = "DeploymentScripts\OnGoingDataChanges.sql"
$PreDeploymentBugFixScriptLocation = "DeploymentScripts\PreDeployment.sql"
$DropExternalTablesScriptLocation = "DeploymentScripts\DropExternalTables.sql"
[string]$ServerInstance = "tempDB"
$GetDatabasesParams = @{
"Database" = "master"
"ServerInstance" = "tempDB"
"Username" = "$DatabaseUsername"
"Password" = "$DatabasePassword"
"Query" = "select [name] from sys.databases where [name] like 'Company%'"
"ConnectionTimeout" = 9999
}
echo "Retrieving company database names"
[string[]]$DatabaseNames = Invoke-sqlcmd @GetDatabasesParams | select -expand name
[int]$ErrorCount = 0
$DatabaseNames | ForEach-Object -Parallel {
try
{
$OngoingChangesScriptParams = @{
"Database" = "$_"
"ServerInstance" = "$ServerInstance"
"Username" = "$DatabaseUsername"
"Password" = "$DatabasePassword"
"InputFile" ="$SystemWorkingDir\$OngoingChangesScriptLocation"
"OutputsqlErrors" = 1
"QueryTimeout" = 9999
"ConnectionTimeout" = 9999
}
Invoke-sqlcmd @OngoingChangesScriptParams
}
catch
{
$ErrorCount++
echo "Internal Error. The remaining databases will still be processed."
echo $_.Exception|Format-List -force
}
}
错误:
解决方法
此问题并非完全等同于Send string parameters to a Start-Job script block,但答案与https://stackoverflow.com/a/63702220/3156906..几乎相同。
问题在于,$DatabaseUsername
脚本块中的$DatabasePassword
和foreach-object
等变量在不同的范围内,并且实际上是与主脚本中的变量不同的变量。
您可以使用Using scope modifier
来解决此问题对于在会话外执行的任何脚本或命令,您需要使用“作用域”修饰符从调用会话作用域中嵌入变量值,以便会话外代码可以访问它们。
所以代替:
$DatabaseUsername = "myusername"
foreach-object -parallel {
...
"Username" = $DatabaseUsername
...
}
尝试
$DatabaseUsername = "myusername"
foreach-object -parallel {
...
"Username" = $using:DatabaseUsername
...
}