-PipelineVariable isnt working correctly

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

csv file

Server,Service,Startup Type,Task
DCVPIM108,SQL Server Analysis Services (MSSQLSERVER),automatic,running
server2,“SQL Server Analysis Services (MSSQLSERVER), SQL Server Analysis Services (MSSQLSERVER) CEIP”,Manual,stopped

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`
<p class=“lang-none prettyprint prettyprinted”>MachineName : DCVPIM108
Name : MSSQLServerOLAPService
Status : Running
StartType : Automatic
OldStatus : Running
OldStartType : Automatic</p>

I don’t know what’s in the csv file, but maybe you should put the select-object inside the foreach-object loop, which is probably running multiple times.

[quote quote=121320]I don’t know what’s in the csv file, but maybe you should put the select-object inside the foreach-object loop, which is probably running multiple times.

[/quote]
i added the csv to my post, if i put select object inside then wouldnt it overwrite?

Can’t you use “-append” like you have commented out?

[quote quote=121326]Can’t you use “-append” like you have commented out?

[/quote]
well append just appends to the file instead of overwriting it…

anyways I did try putting the select inside the for loop for the suggestion, and it returned the same result as having it outside…

Looks like it dynamically updates those properties.

PS C:\> get-service adobearmservice | gm | where name -match 'starttype|^status' 


   TypeName: System.ServiceProcess.ServiceController

Name      MemberType Definition
----      ---------- ----------
StartType Property   System.ServiceProcess.ServiceStartMode StartType {get;}
Status    Property   System.ServiceProcess.ServiceControllerStatus Status {get;}

[quote quote=121336]Looks like it dynamically updates those properties.

PowerShell
10 lines
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59781px; left: 51px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
2
3
4
5
6
7
8
9
10
PS C:\> get-service adobearmservice | gm | where name -match 'starttype|^status'
TypeName: System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
StartType Property System.ServiceProcess.ServiceStartMode StartType {get;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[/quote] so in terms of my script, what should i do?

Maybe save things to a $oldstatus and a $oldstartype.

[quote quote=121342][/quote]
but the whole point of e={$svc.Status} is it should be able to solve the expression from the -PipelineVariable…so then i would have to remove it from my script as its useless huh?

Yep.

[quote quote=121345]Yep.

[/quote]
lol great. and the person who suggested this to me claimed he was an expert on microsoft support. i ended up wasting my time with this N and E expression…

It’s a valid technique. This situation is unusual.

Why do you have two service specified in your csv on the same line for server2?
These should, IMHO, be separate line items relative to the types of getter / setter effort you are trying to do.
The results are as shown below, and no issues observed even with the ‘manual’ or ‘stopped’ status.

$SSAS_services = @"
Server,Service,Startup Type,Task
SQL01,Audiosrv,start
SP01,Browser,Manual,stop
SP01,BITS,Manual,stop
"@  > 'C:\scripts\SSAS_services.csv'


Clear-Host
Import-CSV 'C:\Scripts\SSAS_services.csv' |
ForEach-Object{Get-Service $_.Service -ComputerName $_.Server -PipelineVariable svc} | 
Select-Object MachineName, Name, Status, StartType, 
@{n='OldStatus';e={$svc.Status}}, 
@{n='OldStartType';e={$svc.StartType}}

# Results

MachineName  : SQL01
Name         : Audiosrv
Status       : Running
StartType    : Automatic
OldStatus    : Running
OldStartType : Automatic

MachineName  : SP01
Name         : Browser
Status       : Stopped
StartType    : Disabled
OldStatus    : Stopped
OldStartType : Disabled

MachineName  : SP01
Name         : BITS
Status       : Stopped
StartType    : Manual
OldStatus    : Stopped
OldStartType : Manual

[quote quote=121431]Why do you have two service specified in your csv on the same line for server2?

These should, IMHO, be separate line items relative to the types of getter / setter effort you are trying to do.

The results are as shown below, and no issues observed even with the ‘manual’ or ‘stopped’ status.

PowerShell
38 lines
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 7.20125px; left: 52px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$SSAS_services = @"
Server,Service,Startup Type,Task
SQL01,Audiosrv,start
SP01,Browser,Manual,stop
SP01,BITS,Manual,stop
"@ > 'C:\scripts\SSAS_services.csv'
Clear-Host
Import-CSV 'C:\Scripts\SSAS_services.csv' |
ForEach-Object{Get-Service $_.Service -ComputerName $_.Server -PipelineVariable svc} |
Select-Object MachineName, Name, Status, StartType,
@{n='OldStatus';e={$svc.Status}},
@{n='OldStartType';e={$svc.StartType}}
# Results
MachineName : SQL01
Name : Audiosrv
Status : Running
StartType : Automatic
OldStatus : Running
OldStartType : Automatic
MachineName : SP01
Name : Browser
Status : Stopped
StartType : Disabled
OldStatus : Stopped
OldStartType : Disabled
MachineName : SP01
Name : BITS
Status : Stopped
StartType : Manual
OldStatus : Stopped
OldStartType : Manual
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[/quote] Let's talk about SQL01 machine. Let's say the service was stopped, and set to manual start type. Keep your csv file as is please and run the script. Paste results here (the old status should be different from new status, but that's not what I saw in those results, so pipelinevariable isnt working

[quote quote=121431][/quote]
the output is not right.

in my csv, if the service status is stopped, but it is running on the server, what SHOULD be outputted is:

status: stopped

oldStatus: running

because the old status was running and because in csv file i defined it to stop running, the statuses would be different. that is my issue with -PipelineVariable svc. it should be getting the current status of the service BEFORE it gets set by the ensuing command.

this applied to the startuptype btw.

 

and sure, if i had the csv file say running and the service is already running, then cool, i would expect both to say the same thing. but the issue here is its NOT getting the current status before setting it.

By the way, ‘start’ isn’t valid for the ‘set-service -status’ parameter in the csv. It should be ‘running’.

[quote quote=121500]By the way, ‘start’ isn’t valid for the ‘set-service -status’ parameter in the csv. It should be ‘running’.

[/quote]
Edited my post.

As for your output,

the output is not right.

in my csv, if the service status is stopped, but it is running on the server, what SHOULD be outputted is:

status: stopped

oldStatus: running

because the old status was running and because in csv file i defined it to stop running, the statuses would be different. that is my issue with -PipelineVariable svc. it should be getting the current status of the service BEFORE it gets set by the ensuing command.

this applied to the startuptype btw.

 

and sure, if i had the csv file say running and the service is already running, then cool, i would expect both to say the same thing. but the issue here is its NOT getting the current status before setting it.

 

Here’s a way to do it. Note that tee saves as unicode like out-file.

Import-CSV services.csv |
ForEach {
  $a = Get-Service $_.service 
  $oldstatus = $a.status
  $oldstarttype = $a.starttype
  $a | Set-Service -Status $_.Task -StartupType $_.'Startup Type' -PassThru |
  Select Name, Status, StartType, @{n='OldStatus';e={$oldStatus}},
    @{n='OldStartType';e={$oldStartType}} 
} |
tee ChangeServices_LOG.txt


Name         : AdobeARMservice
Status       : Running
StartType    : Automatic
OldStatus    : Stopped
OldStartType : Manual

Name         : Apple Mobile Device Service
Status       : Running
StartType    : Automatic
OldStatus    : Stopped
OldStartType : Manual

Csv:

service,startup type,task
AdobeARMservice,automatic,running
Apple Mobile Device Service,automatic,running

[quote quote=121525][/quote]
yessss finally! THAT is what i have been looking for! OMG that took so many days and so many resources to ask. not even stackoverflow folks knew how lol

to summarize the problem for anyone in teh future having this issue:

PipelineVariable is DYNAMIC. what this means is if the variable’s properties is modified (i.e. set-service -status) then the status property will change and will ALSO change whatever the pipeline variable status was. this is unfortunate and it should not behave like this.

 

THANK YOU JS! after 3 days this issue can finally be put to rest!

It’s not that pipevariable is dynamic, but the StartType and Status properties in the ServiceController object are dynamic. I’ve never dealt with it before.