简体   繁体   中英

-PipelineVariable isnt working as intended

I have this script that changes services per a csv file input

Import-CSV .\SSAS_services.csv |
    ForEach-Object{
        Get-Service $_.Service -ComputerName $_.Server -PipelineVariable svc|
            Set-Service -Status $_.Task -StartupType $_.'Startup Type' -PassThru
    } |
    Select-Object MachineName, Name, Status, StartType, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}} | 
    tee-object -FilePath '.\ChangeServices_LOG.txt' #-Append
Server,Service,Startup Type,Task
DCVPIM108,SQL Server Analysis Services (MSSQLSERVER),automatic,start
server2,"SQL Server Analysis Services (MSSQLSERVER), SQL Server Analysis Services (MSSQLSERVER) CEIP",Manual,stop

it works great, except for my -PipelineVariable svc is not working as intended. if a service was "stopped" and "Manual" before being changed to "running" and "automatic", it doesnt get the old values "stopped" and "Manual" for OldStatus and OldStartType

MachineName  : DCVPIM108
Name         : MSSQLServerOLAPService
Status       : Running
StartType    : Automatic
OldStatus    : Running
OldStartType : Automatic

why is that?

I guess what you want is to pass same object down the multiple pipes. I haven't use -PipeLineVariable much, but looks like it just creating a nicer alias for $_ . If you need to push something specific down the pipeline I guess you need to use write-ouput with custom object or hashtable. Below is a dummy sample, pushing down and modifying a hastable:

$services = "xagt" , "xbgm" , "XblGameSave"
$list = new-object System.Collections.ArrayList

$serv | foreach { 

    $svc =  Get-Service $_ ; Write-Output @{Name = $svc.Name; Stat=$svc.Status}

 } | foreach {$_.SomeNewItem = "new stuff"; $list.Add($_)}

But in your case one pipeline might be sufficient. Try something like that:

Import-CSV .\SSAS_services.csv | foreach  { 
  $old = Get-Service $_.Service;
  Set-Service -Name $_.Service -Status Running
  $new = Get-Service $_.Service;
  $data = $_.MachineName, $_.Service, $old.Status, $new.Status -join ","
  Write-Host $data
  $data >> Log.txt

  }

The -PipelineVariable / -pv common parameter only works:

  • within a single pipeline.
  • in script blocks in later segments of the same pipeline .

Since you're using it in a pipeline that is nested inside the ForEach-Object script block, the commands in the outer pipeline cannot use it.

However, I suggest restructuring your command so that you don't need a pipeline variable for Get-Service anymore. Instead,

  • -PipelineVariable $csvRow is used with Import-Csv , so that you can more easily refer to it even in nested pipelines (the alternative would be to define the variable explicitly at the start of the ForEach-Object script block as $csvRow = $_ ).

  • $svc is then declared as an -OutVariable , so that the original service state is captured before Set-Service is called to change it.

  • Getting a service, setting its startup type, and enriching the CSV-row object with additional information now all happen inside the ForEach-Object script block.

Import-CSV .\SSAS_services.csv -PipelineVariable csvRow | ForEach-Object {
  Get-Service -Name $csvRow.Service -ComputerName $csvRow.Server -OutVariable svc |
    Set-Service -Status $csvRow.Task -StartupType $csvRow.'Startup Type'
  $csvRow | Select-Object MachineName, Name, Status, StartType,
                          @{n='OldStatus';e={$svc.Status}},
                          @{n='OldStartType';e={$svc.StartType}}
} | Tee-object -FilePath '.\ChangeServices_LOG.txt'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM