代码之家  ›  专栏  ›  技术社区  ›  user1367200

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

  •  0
  • user1367200  · 技术社区  · 11 年前

    我有以下功能:

    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'
    

    如果我调用下面的函数,结果前后都有一个空格。为什么会发生这种情况?我已经使用GetMember分析了两次显示为“system.string”的变量。

    [string]$ProductCode = Get-MsiProperty -Path "ConfigMgrTools.msi" -Property 'ProductCode'
    
    1 回复  |  直到 11 年前
        1
  •  1
  •   Jason Shirk    11 年前

    最初未经编辑的代码无意中在两个地方写出了$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]两者都等效,因此您可以选择自己喜欢的方法。

    推荐文章