问题
我只计算PSCustomObject
类型数组中的一个文件的代码行数。使用以下消息 -
Get-Content:无法将参数绑定到参数'Path',因为它为null。
在行:42字符:100
... -Content -Path $ files.UncommentedFileName)| Measure-Object -Line | Select-Objec ......
如何克服此错误并显示数组中所有文件的代码行?
约束
Remove-VBComments
。因此,我无法避免定义和使用Remove-VBComments
Remove-VBComments
接受流水线输入,因为管道友好,可以在其他cmdlet可以在管道中Remove-VBComments
之后运行的情况下使用详细信息如下 -
意图
我的代码是总结一行VB6代码文件的代码行,该文件从注释中删除。评论始终为single '
,不提供多行评论。以下PowerShell脚本是我尝试实现此目的。
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项目中复制的文件。
输出上述代码
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计数。
... | 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并不能得到结果?!
观察#2
我没有传递PSCustomObject
数组,而是通过引入新的Cmdlet Get-ClsFilesRecursively
来实现代码。该函数看起来像这样 -
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}});
}
}
要使用此功能,我可以像这样打电话
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
的行为正常!
请帮忙!
答案 0 :(得分:1)
不幸的是,-PipelineVariable
无法使用Remove-VBComments
等脚本cmdlet。这就是为什么移动到Select-Object
工作的原因 - 它是一个C#cmdlet。但是你并不需要它,因为foreach循环中的$_
具有$files
变量中的所有信息。更新代码看起来像
$filesToStripComment |
Remove-VBComments |
&{Process{
$UncommentedFileName = $_.UncommentedFileName
Get-Content -Path $UncommentedFileName |
Measure-Object -Line |
Select-Object -Property `
@{n="FileName";e={$UncommentedFileName}},
@{n="LoC";e={$_.Lines}} `
} }