2014-08-29 62 views
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

可能执行并关闭返回$ null?尝试将这些调用的结果分配给$ null,例如$ null =&$ InvokeMethod -Object $ View -MethodName Close -ArgumentList @() – 2014-08-29 02:18:24

+0

就是这样。你先生是个天才。在PowerShell中执行C#代码时,我遇到了这种类型的问题,但它从来没有想过可能是这种情况。如果您将其作为回答发布,我会将其标记为答案。 – user1367200 2014-08-29 03:20:32

+0

原始帖子已被编辑,将有问题的代码行发送给Out-Null,如Jason Shirk上面提出的那样。 – user1367200 2014-08-29 11:58:01

回答

1

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

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

当$ ProductCode被键入为一个字符串时,$ null值被格式化为一个空格,例如,

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

相比之下,与非类型化(使用输出字符串-stream到数组转换为字符串,而不是一个类型转换):

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

的$空值通常来自.NET方法调用,或者在这种情况下,COM方法调用。我通常将类似这样的方法调用的结果赋值给$ null,因为它在所有版本的PowerShell中都有最好的性能,但是对Out-Null或者cast到void的管道都是等效的,所以你可以选择你喜欢的任何一个。