Powershell 是否有一个“问题”;“功能如物”;可以作为模板吗?

Powershell 是否有一个“问题”;“功能如物”;可以作为模板吗?,powershell,Powershell,我有一个这样的代码,在我的每个条件语句/案例中重复多次。我有3个条件…现在,一切都很好,但我正在考虑重新格式化脚本,以便于阅读 我想到的一种方法是生成函数,但问题是,我有一个while循环,用于每个条件语句中的特定场景,它从包含文件中某些列名的队列中出列 因此,根据下面我想放入某种模板的代码,我想不出这是如何工作的,因为正如您所看到的,$tb代表$table,这是我在代码中的条件语句之前打开的。 如果我在一个函数中包含关于服务器连接和表的所有内容,这意味着当我将包含代码的“函数”传递给while

我有一个这样的代码,在我的每个条件语句/案例中重复多次。我有3个条件…现在,一切都很好,但我正在考虑重新格式化脚本,以便于阅读

我想到的一种方法是生成函数,但问题是,我有一个while循环,用于每个条件语句中的特定场景,它从包含文件中某些列名的队列中出列

因此,根据下面我想放入某种模板的代码,我想不出这是如何工作的,因为正如您所看到的,$tb代表$table,这是我在代码中的条件语句之前打开的。 如果我在一个函数中包含关于服务器连接和表的所有内容,这意味着当我将包含代码的“函数”传递给while循环时,它将在每次迭代中创建/实例化表,这是没有意义的,也不会起作用

所以我考虑使用注释之类的东西,比如模板之类的东西,它不会像函数那样期望返回任何东西或者需要合理的参数。问题是,这样的事情存在吗

这段代码在我所有的while循环中都是相同的,我想将其“存储”在某个地方,然后将其传递给他们:

$dqHeader = $csvFileHeadersQueue.Dequeue()

$column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType1)

if ($dqHeader -in $PrimaryKeys)
{
    # We require a primary key.

    $column.Nullable = $false
    #$column.Identity = $true #not needed with VarChar
    #$column.IdentitySeed = 1 #not needed with VarChar
    $tb.Columns.Add($column)

    $primaryKey = New-Object Microsoft.SqlServer.Management.Smo.Index($tb, "PK_$csvFileBaseName")
    $primaryKey.IndexType = [Microsoft.SqlServer.Management.Smo.IndexType]::ClusteredIndex
    $primaryKey.IndexKeyType = [Microsoft.SqlServer.Management.Smo.IndexKeyType]::DriPrimaryKey #Referential Integrity to prevent data inconsistency. Changes in primary keys must be updated in foreign keys.
    $primaryKey.IndexedColumns.Add((New-Object Microsoft.SqlServer.Management.Smo.IndexedColumn($primaryKey, $dqHeader)))
    $tb.Indexes.Add($primaryKey)
}
else
{
    $tb.Columns.Add($column)
}
把它想象成一个拼图块,当被要求在while循环中完成这个“拼图”时,它就可以正确地嵌入其中。

如注释所示:
您可以与While循环(或函数)共享(硬编码)[ScriptBlock](
$template={code in post goes here}
)并使用调用命令$template或调用操作符调用它:
和$template
。动态修改表达式并使用诸如
Invoke expression
[ScriptBlock]::Create()
之类的命令不是一个好主意,因为存在恶意代码注入的风险(请参阅:)

您甚至可以将参数添加到共享的
[ScriptBlock]
,如:

$Template = {
    [CmdletBinding()]Param ($DataType)
    $column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType)
    ...
}

ForEach ($MyDataType in @('MyDataType')) {
    Invoke-Command $Template -ArgumentList $MyDataType
}
但反问题仍然存在:为什么不创建一个函数?

Function template($DataType) {
    $column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType)
    ...
}

ForEach ($MyDataType in @('MyDataType')) {
    template $MyDataType
}
根据评论:
您可以与While循环(或函数)共享(硬编码)[ScriptBlock](
$template={code in post goes here}
)并使用调用命令$template或调用操作符调用它:
和$template
。动态修改表达式并使用诸如
Invoke expression
[ScriptBlock]::Create()
之类的命令不是一个好主意,因为存在恶意代码注入的风险(请参阅:)

您甚至可以将参数添加到共享的
[ScriptBlock]
,如:

$Template = {
    [CmdletBinding()]Param ($DataType)
    $column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType)
    ...
}

ForEach ($MyDataType in @('MyDataType')) {
    Invoke-Command $Template -ArgumentList $MyDataType
}
但反问题仍然存在:为什么不创建一个函数?

Function template($DataType) {
    $column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType)
    ...
}

ForEach ($MyDataType in @('MyDataType')) {
    template $MyDataType
}

我认为您需要解释更多关于常规设置的内容,为什么您不能只使用普通的
函数
(变量应该可以读取,并且通常引用对象),是否涉及(远程)作业、多线程?试着建立一个你想要实现的目标的框架。一般来说,我认为你的答案在
$Global:csvFileHeadersQueue=…
??@iRon中,我知道它有点模糊,但我的脚本是600 LOC,在这里发布是不可行的。实际上,这背后的要点是通过某种方式将我发布的这段代码制作成一个“模板”,我可以插入脚本中当前代码所在的位置,从而减少LOC。我想可能是范围,我会调查一下。基本上,我会把$template看作是
$template=@“post中的代码放在这里”@
,我只会在while循环中传递$template,只要有必要/只要这个代码已经存在,就用它来替换。我想你找错了方向,无论如何,你可以共享一个(硬编码的)
[ScriptBlock]
$template={code in post goes here}
)使用
While
循环(或函数)调用它,例如
调用命令$template
。动态修改它并使用
调用表达式
[ScriptBlock]::Create()
这不是一个好主意,因为存在恶意代码注入的风险。请参阅:@iRon有趣,我不打算修改$template中的代码,因为我确实希望它是那样硬编码的。不过,修改语法的某些方式会是什么样子?我会尝试一下,谢谢!@iRon举个例子,假设一切都是一样的除了$DataType1。这是我可以作为invoke的一部分专门修改的东西吗?如果是,它会像invoke Expression$template一样。modify(替换“$DataType1”“$DataType2”)我想你需要解释更多关于一般设置的内容,为什么你不能只使用一个普通的
函数
(变量应该可以读取,并且对象通常会被引用),是否涉及(远程)jobs,multi-threading?试着建立一个你想要实现的目标。一般来说,我认为你的答案是在
$Global:csvFileHeadersQueue=…
??@iRon我知道它有点模糊,但我的脚本是600 LOC,在这里发布是不可行的。实际上,这背后的要点是通过某种方式使我发布的这段代码减少LOC插入一个“模板”中,我可以插入脚本中当前代码所在的位置。我认为范围可能就是它,我将对此进行研究。基本上可以将其想象为
$template=@“这里是post中的代码”@
我只会在while循环中传递$template,只要有必要/只要这个代码已经存在,就用它替换它。我认为你看错了方向,无论如何,你可以用
while
循环(或函数)共享一个(硬编码的)
[ScriptBlock]
$template={code in post goes here}
)并使用例如
invoke Command$template
调用它。动态修改它并使用
invoke Expression
[ScriptBlock]::Create()等命令<