PowerShell PipelineVariable参数仅包含PSCustomObject集合中的第一个值 [英] PowerShell PipelineVariable parameter contains only first value in a collection of PSCustomObject
问题描述
问题
我只能得到类型为PSCustomObject
的数组中一个文件的代码行数.其余的数组错误中的所有条目都显示以下消息-
I get count for lines of code for only one file in the array of type PSCustomObject
. Rest all entries in the array error out with following message -
Get-Content:由于参数'null'为空,因此无法将其绑定到参数'Path'.
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
在线:42个字符:100
At line:42 char:100
... -Content -Path $ files.UncommentedFileName)|测量对象线| Select-Objec ...
... -Content -Path $files.UncommentedFileName) | Measure-Object -Line | Select-Objec ...
如何克服此错误并显示数组中所有文件的代码行?
How do I overcome this error and display the lines of code for all the files in the array?
约束
- 我打算在必须处理VB6文件的其他情况下重新使用功能
Remove-VBComments
.因此,我无法避免定义和使用Remove-VBComments
- 我打算让函数
Remove-VBComments
接受管道输入,因为它将是管道友好的,以便在其他cmdlet可以在管道中Remove-VBComments
之后运行的情况下使用 - 我必须在客户环境中使用PowerShell 4.0版本.
- I intend to re-use the function
Remove-VBComments
for other scenarios where I have to process VB6 files. Thus, I cannot avoid defining and usingRemove-VBComments
- I intend to have the function
Remove-VBComments
accept pipelined input as will be pipeline friendly to be useable in the scenarios where other cmdlets could operate afterRemove-VBComments
in the pipeline - I am constrained in the customer environment to use PowerShell version 4.0.
详细信息-
意图
我的代码的摘要是总结从注释中剥离的VB6代码文件的代码行.注释始终是single '
,没有多行注释.我尝试遵循PowerShell脚本来实现此目的.
Of my code is to summarize the Lines of Code for a VB6 code file which is stripped off from comments. Comments are always a single '
with no provision for multi-line comments. Following PowerShell script is my attempt to fulfill this intent.
PowerShell代码
$filesToStripComment = @([PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\App.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\App.cls.uncommented"
},[PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\Class1.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\Class1.cls.uncommented"
},[PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\IFilterReporter.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\IFilterReporter.cls.uncommented"
},[PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\ITemplateFilter.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\ITemplateFilter.cls.uncommented"
});
Function Remove-VBComments {
[CmdletBinding()]
Param(
[Parameter(
Mandatory = $True,
ValueFromPipelineByPropertyName=$True
)]
[String]
$SourceFileName,
[Parameter(
Mandatory = $True,
ValueFromPipelineByPropertyName=$True
)]
[String]
$UncommentedFileName
)
Process {
(Get-Content -LiteralPath $SourceFileName) `
-replace "\'.*$",$ReplaceString -notmatch "^\s*$" `
| Out-File -LiteralPath $UncommentedFileName;
$result = [PSCustomObject]@{
SourceFileName=$($SourceFileName);
UncommentedFileName=$($UncommentedFileName)
};
Write-Output $result;
}
}
$filesToStripComment | `
Remove-VBComments -PipelineVariable "files" | `
&{Process{ `
(Get-Content -Path $files.UncommentedFileName) `
| Measure-Object -Line `
| Select-Object -Property `
@{n="FileName";e={$files.UncommentedFileName}}, `
@{n="LoC";e={$_.Lines}} `
} }
cls文件是我从 github 复制的文件项目.
The cls files are the ones I copied from a github project.
上述代码的输出
FileName LoC
------------- -------
.\vb6-master\ClassTemplate\ClassBuilder\App.cls.uncommented 29
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:42 char:100
......
# The above error repeats for all other entries in the array $filesToStripComment.
观察#1
如果在调用Cmdlet Remove-VBComments
之后进行了一些小的更改,我将获得数组$filesToStripComment
中所有文件的LoC计数.
If I make following small change after the call to Cmdlet Remove-VBComments
, I get the LoC count for all files in the array $filesToStripComment
.
... | Remove-VBComments | Select-Object -PipelineVariable "files" | `
& { Process { (Get-Content -Path $files.UncommentedFileName) | `
Measure-Object -Line | `
Select-Object -Property @{n="FileName",e={$files.UncommentedFileName} ...
现在,我不明白为什么管道
Select-Object
的这种细微变化会为我带来所需的结果,但是在CmdletRemove-VBComments
上使用PipelineVariable却无法得到结果吗?!
Now I do not understand why does this subtle change of piping
Select-Object
gets me the desired result but using the PipelineVariable on CmdletRemove-VBComments
does not get me the result?!
观察#2
我没有通过传递PSCustomObject
的数组,而是通过引入新的Cmdlet Get-ClsFilesRecursively
改进了代码.函数看起来像这样-
Instead of passing an array of PSCustomObject
I have improvised the code in the meanwhile by introducing a new Cmdlet Get-ClsFilesRecursively
. The function looks like this -
Function Get-ClsFilesRecursively{
[CmdletBinding()]
Param(
[Parameter(
Mandatory=$True,
ValueFromPipelineByPropertyName=$True,
)]
[String]
$SourceCodePath
)
Process{
Write-Output (Get-ChildItem -Path $SourceCodePath `
-Filter "*.cls" `
-Recurse | `
Select-Object -Property `
@{n="LiteralPath";e={$_.FullName}});
}
}
要使用此功能,我要打这样的电话
To put this function to use I make a call like this
Get-ClsFilesRecursively -SourceCodePath . -PipelineVariable "files" | `
& { Process { `
Get-Content -LiteralPath $files.LiteralPath | `
Measure-Object -Line | `
Select-Object -Property @{n="File name";e={$files.LiteralPath}} `
@{n="LoC"; e={$_.Lines}}
}}
现在,这为目录中的所有文件提供了代码行;没有任何例外.但是,此调用在文件中包括注释.现在,如果按上述调用顺序传送Remove-VBCommments
,我会得到上面问题中提到的问题.
我对导致Remove-VBComments
无法与PipelineVariable
正常工作而导致其他Cmdlet与PipelineVariable
正常运行的原因感到困惑!
Now this gives the me the Lines of Code for all the files in the directory; without any exception. However, this call includes comments in the files. Now if I pipe the Remove-VBCommments
in the above call sequence I get back the problem I mentioned in the question above.
I am perplexed with what causes Remove-VBComments
to fail in working properly with PipelineVariable
whereas other Cmdlets behave properly with PipelineVariable
!
请帮助!
推荐答案
不幸的是,-PipelineVariable
不适用于Remove-VBComments
之类的脚本cmdlet.这就是为什么将Select-Object
运行成功的原因-这是C#cmdlet.但是您实际上并不需要它,因为foreach循环中的$_
具有$files
变量中应包含的所有信息.更新代码看起来像
Unfortunately -PipelineVariable
doesn't work with script cmdlets like Remove-VBComments
. That's why moving if to Select-Object
worked - it's a C# cmdlet. But you don't actually need it since $_
in the foreach loop has all of the information that would have been in the $files
variable. The update code would look something like
$filesToStripComment |
Remove-VBComments |
&{Process{
$UncommentedFileName = $_.UncommentedFileName
Get-Content -Path $UncommentedFileName |
Measure-Object -Line |
Select-Object -Property `
@{n="FileName";e={$UncommentedFileName}},
@{n="LoC";e={$_.Lines}} `
} }
这篇关于PowerShell PipelineVariable参数仅包含PSCustomObject集合中的第一个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!