为什么设置字符串变量类型会为结果添加空格?

时间:2014-08-29 00:11:25

标签: powershell powershell-v3.0

我有以下功能:

Function Get-MsiProperty
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)]
        [ValidateScript({$_ | Test-Path -PathType Leaf})]
        [string]$Path,

        [Parameter(Mandatory=$true)]
        [string]$Property
    )

    Begin
    {       
        $GetProperty = {
            Param
            (
                $Object,
                $PropertyName,
                [object[]]$ArgumentList
            )
            Return $Object.GetType().InvokeMember($PropertyName, 'Public, Instance, GetProperty', $null, $Object, $ArgumentList)
        }

        $InvokeMethod = {
            Param
            (
                $Object,
                $MethodName,
                $ArgumentList
            )
            Return $Object.GetType().InvokeMember($MethodName, 'Public, Instance, InvokeMethod', $null, $Object, $ArgumentList)
        }

        ${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
        $PSParameters = $PSBoundParameters | Format-Table -Auto | Out-String
    }
    Process
    {
        Try
        {
            Set-StrictMode -Version Latest

            # http://msdn.microsoft.com/en-us/library/aa369432(v=vs.85).aspx
            $msiOpenDatabaseModeReadOnly = 0
            $Installer = New-Object -ComObject WindowsInstaller.Installer -ErrorAction 'Stop'

            $Database = &$InvokeMethod -Object $Installer -MethodName OpenDatabase -ArgumentList @($Path, $msiOpenDatabaseModeReadOnly)

            $View = &$InvokeMethod -Object $Database -MethodName OpenView -ArgumentList @("SELECT Value FROM Property WHERE Property='$Property'")

            &$InvokeMethod -Object $View -MethodName Execute | Out-Null

            $MSIProperty = $null
            $Record = &$InvokeMethod -Object $View -MethodName Fetch
            If ($Record)
            {
                $MSIProperty = &$GetProperty -Object $Record -PropertyName StringData -ArgumentList 1
            }
            Write-Output $MSIProperty
        }
        Catch
        {
            Write-Host -Message "Failed to get the MSI property [$Property]"
        }
        Finally
        {
             &$InvokeMethod -Object $View -MethodName Close -ArgumentList @() | Out-Null
        }
    }
}

如果我按下面的方式调用该函数,我会得到正确的结果:

$ProductCode = Get-MsiProperty -Path "ConfigMgrTools.msi" -Property 'ProductCode'

如果我按下面的方式调用该函数,结果在结果之前和之后都有一个空格。为什么会这样?我已经使用Get-Member来分析它显示为'system.string'的变量。

[string]$ProductCode = Get-MsiProperty -Path "ConfigMgrTools.msi" -Property 'ProductCode'

1 个答案:

答案 0 :(得分:1)

原始的未经编辑的代码无意中在两个地方写出了$ null。

当$ ProductCode是无类型时,结果是一个数组,格式化数组时,数组中的$ null值将被忽略。

当$ ProductCode作为字符串输入时,$ null值用空格格式化,例如

PS> "__{0}__" -f ([string]@($null, "abc", $null))
__ abc __

将其与无类型进行比较(使用Out-String -Stream将数组转换为字符串而不是类型转换):

PS> "_{0}_" -f (@($null, "abc", $null) | out-string -Stream)
_abc_

$ null值通常来自.Net方法调用,或者在这种情况下,来自COM方法调用。我通常将这样的方法调用的结果分配给$ null,因为它在所有版本的PowerShell中都具有最佳性能,但是Out-Null或者转换为[void]的管道都等效地工作,因此您可以选择您喜欢的任何一个。