Параметр PowerShell PipelineVariable содержит только первое значение в коллекции PSCustomObject. - PullRequest
0 голосов
/ 25 мая 2018

Вопрос

Я получаю счетчик строк кода только для одного файла в массиве типа PSCustomObject.Отключите все записи в массиве с помощью следующего сообщения -

Get-Content: Невозможно привязать аргумент к параметру 'Path', так как он равен нулю.

В строке: 42 символа:100

... -Контент -Path $ files.UncommentedFileName) |Measure-Object-Line |Select-Objec ...

Как мне преодолеть эту ошибку и отобразить строки кода для всех файлов в массиве?

Ограничения

  1. Я намерен повторно использовать функцию Remove-VBComments для других сценариев, в которых мне приходится обрабатывать файлы VB6.Таким образом, я не могу избежать определения и использования Remove-VBComments
  2. Я намереваюсь иметь функцию Remove-VBComments принимать конвейерный ввод, так как она будет дружественной для конвейера, чтобы ее можно было использовать в сценариях, где другие командлеты могут работать после Remove-VBComments вконвейер
  3. Я вынужден в среде клиента использовать PowerShell версии 4.0.

Подробности следуют -

Намерение

Мой код состоит в обобщении строк кода дляФайл кода 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

Если я сделаю следующее небольшое изменение после звонкаКомандлет Remove-VBComments, я получаю количество LoC для всех файлов в массиве $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 дает мне желаемый результат, но использование PipelineVariable в командлете Remove-VBComments не дает мне результат?!

Observation # 2

Вместо передачи массива PSCustomObject Я тем временем импровизировал код, представив новый командлет 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, тогда как другие командлеты работают с PipelineVariable!

Пожалуйста, помогите!

1 Ответ

0 голосов
/ 25 мая 2018

К сожалению -PipelineVariable не работает с командлетами скриптов, такими как Remove-VBComments.Поэтому переход на Select-Object сработал - это командлет C #.Но вам это на самом деле не нужно, поскольку $_ в цикле 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}} `
     } }
...