PowerShell中管道输入的问题

3

希望有人能在这里帮助我。我以前曾寻找解决方案,并总是能够找到一些东西。但这个问题似乎太奇怪了。

我有一个PowerShell函数,可以有效地复制New-ADUser Cmdlet,并接受多个参数来实现此目的。该函数的大多数参数都将“ValueFromPipelineByPropertyName”参数属性设置为True,以便我可以将CSV和其他管道数据馈送到该函数中,而无需编写很多“if”和分配语句。或者至少这是我的想法。

这是我的函数示例(精简以更好地说明问题):

[CmdletBinding()]
Param(
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FirstName,
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$LastName,
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FullName
)

Process {
    if(-not $FullName) {
        $FullName = "$FirstName $LastName"
    }

    $user = "" | select FirstName,LastName,FullName
    $user.FirstName = $FirstName
    $user.LastName = $LastName
    $user.FullName = $FullName
    return $user
}

所以当我对这个 CSV 数据运行它时:

FirstName,LastName
Bob,Smith
Dick,Jones
Sami,Davis
Ray,Charles
Jane,Doe
Keith,Johnson
Ruth,Willson
Genni,Gartner

I get:

FirstName                       LastName                        FullName
---------                       --------                        --------
Bob                             Smith                           Bob Smith
Dick                            Jones                           Bob Smith
Sami                            Davis                           Bob Smith
Ray                             Charles                         Bob Smith
Jane                            Doe                             Bob Smith
Keith                           Johnson                         Bob Smith
Ruth                            Willson                         Bob Smith
Genni                           Gartner                         Bob Smith

现在,我明白了这里发生了什么。管道输入或函数参数中没有指定FullName的值,所以我在process语句中设置一个值,在该迭代中使用。问题是,$FullName变量没有被“重置”为nullundefined值,而保留了设置的值,这个问题需要解决。
如果我改变CSV数据,明确定义FullName的值为空字符串,问题就消失了。但是当管道数据没有定义该属性时,这并没有帮助我。
我试图避免重新编写整个函数来使用不同的变量名或使用$_,因为该函数的复杂性还包括定义参数别名,以便我们可以直接从人力资源程序的数据库中获取数据并将其传递到新用户函数中,无需手动调整数据。这也使我无法在管道数据中添加空值参数。
我知道我在解释中有点啰嗦,但是这种情况似乎很独特(至少根据我在互联网上找到的信息)。
3个回答

1

这里的变量作用域可能有些棘手的问题,也许?

你可以尝试在函数末尾添加Remove-Variable FullName,看看是否有帮助。

我理解你不想使用不同的变量名称,但是使用不同的变量来存储函数内部“生成”的全名可能会使事情更清晰;作用域将会更加整洁,希望如此。

if(-not $FullName) {
    $GeneratedName = "$FirstName $LastName"
} else {
    $GeneratedName = $FullName
}

是的,在与同事进行头脑风暴后,我们唯一能想到的答案是在_Begin_部分定义一个内部变量来捕获任何直接定义的值。 - Chris Davis

0
为什么不直接“重置”$fullname变量呢?
[CmdletBinding()]
Param(
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FirstName,
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$LastName,
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FullName
)

Process {  
            if([string]::IsNullOrEmpty($FullName))
                {
                    $script:Fullname =  "$FirstName $LastName"
                }        

    $user = "" | select FirstName,LastName,FullName
    $user.FirstName = $FirstName
    $user.LastName = $LastName
    $user.FullName = $FullName
    $FullName= [string]::Empty
    $user
}

那种方式的问题在于,如果它在函数调用中被显式定义,那么它也会“重置”该值,这也不好。 - Chris Davis
@ChrisDavis 在 $Fullname 的值被分配给 $user.Fullname 后,不再是一个问题。在同一管道过程中,您可以访问 $user.FullName 来获取其值。 - CB.

0

你需要设置FullName的默认值,这样下面的代码才能正常工作:

[CmdletBinding()]
Param(
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FirstName,
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$LastName,
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FullName=$null
)

Process {
    if(-not $FullName) {
        $FullName = "$FirstName $LastName"
    }

    $user = "" | select FirstName,LastName,FullName
    $user.FirstName = $FirstName
    $user.LastName = $LastName
    $user.FullName = $FullName
    return $user
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接