【问题标题】:Cannot execute same powershell function twice, gives error无法两次执行相同的 powershell 函数,给出错误
【发布时间】:2012-01-27 04:08:23
【问题描述】:

我对 powershell 相当陌生,我基本上是在编写一个脚本,它基于一个主列对几个 .csv 文件执行连接。我正在使用此处的 Join-Collections 脚本:http://poshcode.org/1461

由于我需要合并 5 个 .csv 文件,我需要运行这个函数 4 次。

在第一次运行时,它运行良好,但随后再次尝试运行该函数会出现“没有为 cmd-let 指定对象”错误。

在尝试调试时,我确实复制并粘贴了该行,只更改了变量名以创建一个新变量。

我一定是做错了什么……

$SumFile = "VMSummary.csv"
$MemFile = "VMMemory.csv"
$ProcFile = "VMProcessor.csv"
$OSFile = "VMOS.csv"
$NicFile = "VMNics.csv"

$SumFileCSV = Import-Csv $SumFile | Select VMElementName,GuestOS,Heartbeat,MemoryUsage,IpAddress
$MemFileCSV = Import-Csv $MemFile | Select VMElementName,Reservation
$ProcFileCSV = Import-Csv $ProcFile
$OSFileCSV = Import-Csv $OSFile
$NicFileCSV = Import-Csv $NicFile

$JoinColumn = "VMElementName"

function Join-Collections {
PARAM(
   $FirstCollection
,  [string]$FirstJoinColumn
,  $SecondCollection
,  [string]$SecondJoinColumn=$FirstJoinColumn
)
PROCESS {
   $ErrorActionPreference = "Inquire"
   foreach($first in $FirstCollection) {
      $SecondCollection | Where{ $_."$SecondJoinColumn" -eq $first."$FirstJoinColumn" } | Join-Object $first
   }
}
BEGIN {
   function Join-Object {
   Param(
      [Parameter(Position=0)]
      $First
   ,
      [Parameter(ValueFromPipeline=$true)]
      $Second
   )
   BEGIN {
      [string[]] $p1 = $First | gm -type Properties | select -expand Name
   }
   Process {
      $Output = $First | Select $p1
      foreach($p in $Second | gm -type Properties | Where { $p1 -notcontains $_.Name } | select -expand Name) {
         Add-Member -in $Output -type NoteProperty -name $p -value $Second."$p"
      }
      $Output
   }
   }
}
}

$Temp = Join-Collections $SumFileCSV $JoinColumn $MemFileCSV $JoinColumn

$Temp

##BREAKS HERE
$Temp2 = Join-Collections $SumFileCSV $JoinColumn $MemFileCSV $JoinColumn

更新

它给出了以下错误:

No object has been specified to the get-member cmdlet
+ foreach($p) in $Second | gm <<<<  -type Properties | Where { $p1 -notcontains     $_.Name } | select -expand Name) 

csv 数据非常简单。当我在 $Temp 中断之前打印出它时,它会吐出:

GuestOS       : Windows Server (R) 2008 Standard
Heartbeat     : OK
IpAddress     : 192.168.48.92
MemoryUsage   : 1024
VMElementName : VM015
Reservation   : 1024

GuestOS       : Windows Server (R) 2008 Standard
Heartbeat     : OK
IpAddress     : 192.168.48.151
MemoryUsage   : 1028
VMElementName : VM053
Reservation   : 1028

GuestOS       : Windows Server (R) 2008 Standard
Heartbeat     : OK
IpAddress     : 192.168.48.214
MemoryUsage   : 3084
VMElementName : VM065
Reservation   : 3084

GuestOS       : 
Heartbeat     : 
IpAddress     : 
MemoryUsage   : 
VMElementName : VM074
Reservation   : 1024

GuestOS       : Windows Server 2008 R2 Standard
Heartbeat     : OK
IpAddress     : 192.168.48.32
MemoryUsage   : 3072
VMElementName : VM088
Reservation   : 3072

GuestOS       : Windows Server (R) 2008 Enterprise
Heartbeat     : OK
IpAddress     : 192.168.48.81
MemoryUsage   : 3084
VMElementName : VM090
Reservation   : 3084

GuestOS       : Windows Server 2008 R2 Enterprise
Heartbeat     : OK
IpAddress     : 192.168.48.82
MemoryUsage   : 5120
VMElementName : VM106
Reservation   : 5120

.csv 数据的其余部分是同一种东西——只是不同服务器上的统计数据。

理想情况下我想做的是:

$Temp = Join-Collections $SumFileCSV $JoinColumn $MemFileCSV $JoinColumn

$Temp = Join-Collections $Temp $JoinColumn $ProcFileCSV $JoinColumn

$Temp = Join-Collections $Temp $JoinColumn $OSFileCSV $JoinColumn

$Temp = Join-Collections $Temp $JoinColumn $NicFileCSV $JoinColumn | Export-Csv "VMJoined.csv" -NoTypeInformation -UseCulture

【问题讨论】:

  • 它给出了什么错误?同时发布您正在合并的 CSV 数据的示例。

标签: powershell


【解决方案1】:

此代码在 Powershell v3 CTP 2 上运行良好(这可能是 @manojlds 正在使用的)。然而,在 Powershell V2 中,Join-Object 函数的参数 $second 在第二次调用 Join-Collections 时未绑定。这可以通过在Join-Object 函数内的进程块中添加以下行来轻松验证:

$psboundparameters | out-host

您会注意到,第一次调用 Join-Collections 时(Join-Object 的两个参数都已绑定,但第二次调用 $second 时不再绑定。

目前尚不清楚是什么导致了这种行为,但由于它似乎在 Powershell V3 中工作,我猜这是一个错误。

要使该功能在 Powershell V2 中工作,可以通过替换此行来显式绑定参数:

$SecondCollection | Where{ $_."$SecondJoinColumn" -eq $first."$FirstJoinColumn" } | Join-Object $first

通过这一行:

$SecondCollection | Where{ $_."$SecondJoinColumn" -eq $first."$FirstJoinColumn" } | %{Join-Object -first $first -second $_}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多