locked
Unexpected Token with service script RRS feed

  • Question

  • I wrote a script that manages services on the server and starts/stops etc...depending on the Task in the csv file, as well as changes the startuptype, again depending on the start up type in the csv file.

    CSV file:

    Server,Service,Startup Type,Task
    server1,SQL Server Analysis Services (MSSQLSERVER),automatic,start
    server2,"SQL Server Analysis Services (MSSQLSERVER), SQL Server Analysis Services (MSSQLSERVER) CEIP",Manual,stop

    Script

    $csvFile = Import-CSV .\SSAS_services.csv$ServiceState = Get-Service -Name$ServiceStartupType = Get-Service | select -property name,starttypeForEach ($row in $csvFile){       #checking if service in csv file exists on server    if (Get-Service $row.Service | Select-Object Name, StartType, Status -ComputerName $row.Server -ErrorAction SilentlyContinue)    {        "$row.Service not found on $row.Server!" | out-file .\SSAS_services.txt -Append    }    else     {        Get-Service $row.Service | Select-Object Name, StartType, Status -ComputerName $row.Server | select machinename,name | format-table -AutoSize    }    # Change the service on the server    if ($row.Task -eq "stop" -and $row.Server $ServiceState $row.Service -ne "stop")    {        Invoke-Command -ScriptBlock { Stop-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row        Start-Sleep 60    }    elseif ($row.Task -eq "start" -and $row.Server $ServiceState $row.Service -ne "start")    {        Invoke-Command -ScriptBlock { Start-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row        Start-Sleep 60    }    elseif ($row.Task -eq "pause" -and $row.Server $ServiceState $row.Service -ne "pause")    {        Invoke-Command -ScriptBlock { Suspend-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row        Start-Sleep 60    }    elseif ($row.Task -eq "Restart")    {        Invoke-Command -ScriptBlock { Restart-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row        Start-Sleep 60    }    #changing startup type if different    if ($row."Startup Type" -eq $ServiceStartupType -ComputerName    $row.Server)    {        "Changing Startup Type from '$ServiceStartupType' to $row.'Startup Type'"        Invoke-Command -ScriptBlock { Set-Service $using:row.Service -StartupType $using:row."Startup Type" } -ComputerName    $row.Server -ArgumentList $row    }} | Tee-object .\SSAS_services.txt -Append

    I am getting the following errors:

    • Unexpected token '$ServiceState' in expression or statement. + if ($row.Task -eq "stop" -and $row.Server $ServiceState $row.Serv ...
    • Unexpected token ')' in expression or statement. + ... elseif ($row.Task -eq "start" -and $row.Server $ServiceState $row.Se ...
      ~
    • Unexpected token '$ServiceState' in expression or statement. + elseif ($row.Task -eq "start" -and $row.Server $ServiceState $row ... +
    • Unexpected token '$row' in expression or statement. + ... -eq "start" -and $row.Server $ServiceState $row.Service -ne "start") + Unexpected token ')' in expression or statement. + ... elseif ($row.Task -eq "pause" -and $row.Server $ServiceState $row.Se ... 
    Thursday, November 1, 2018 11:50 PM

Answers

  • Here is an actual tested version of my code with some simple modifications.

    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, SrartType, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}


    \_(ツ)_/


    • Edited by jrv Friday, November 2, 2018 1:26 AM
    • Marked as answer by cataster Friday, November 2, 2018 1:41 AM
    Friday, November 2, 2018 1:25 AM

All replies

  • Please only post code that is formatted correctly and readable.


    \_(ツ)_/

    Thursday, November 1, 2018 11:59 PM
  • The code you posted is completely unusable as all line are concatenated into on long line.

    What I can see show that almost no line in the code is correct due to argument and syntax errors.

    The first line in your loop will always return the current systems service.

    There is no need for Invoke-Command in this code.


    \_(ツ)_/

    Friday, November 2, 2018 12:09 AM
  • I have edited the post but it counted it as spam... so frustrating

    anyways, here is a better version:

    $csvFile = Import-CSV .\SSAS_services.csv
    
    $ServiceState = Get-Service -Name
    $ServiceStartupType = Get-Service | select -property name,starttype
    
    ForEach ($row in $csvFile)
    {   
        #checking if service in csv file exists on server
        if (Get-Service $row.Service | Select-Object Name, StartType, Status -ComputerName $row.Server -ErrorAction SilentlyContinue)
        {
            "$row.Service not found on $row.Server!" | out-file .\SSAS_services.txt -Append
        }
        else 
        {
            Get-Service $row.Service | Select-Object Name, StartType, Status -ComputerName $row.Server | select machinename,name | format-table -AutoSize
        }
    
        # Change the service on the server
    
        if ($row.Task -eq "stop" -and $row.Server $ServiceState $row.Service -ne "stop")
        {
            Invoke-Command -ScriptBlock { Stop-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row
            Start-Sleep 60
        }
        elseif ($row.Task -eq "start" -and $row.Server $ServiceState $row.Service -ne "start")
        {
            Invoke-Command -ScriptBlock { Start-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row
            Start-Sleep 60
        }
        elseif ($row.Task -eq "pause" -and $row.Server $ServiceState $row.Service -ne "pause")
        {
            Invoke-Command -ScriptBlock { Suspend-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row
            Start-Sleep 60
        }
        elseif ($row.Task -eq "Restart")
        {
            Invoke-Command -ScriptBlock { Restart-Service $using:row.Service } -ComputerName    $row.Server -ArgumentList $row
            Start-Sleep 60
        }
    
        #changing startup type if different
    
        if ($row."Startup Type" -eq $ServiceStartupType -ComputerName    $row.Server)
        {
            "Changing Startup Type from '$ServiceStartupType' to $row.'Startup Type'"
    
            Invoke-Command -ScriptBlock { Set-Service $using:row.Service -StartupType $using:row."Startup Type" } -ComputerName    $row.Server -ArgumentList $row
        }
    
    } | Tee-object .\SSAS_services.txt -Append


    Friday, November 2, 2018 12:44 AM
  • The code you posted is completely unusable as all line are concatenated into on long line.

    What I can see show that almost no line in the code is correct due to argument and syntax errors.

    The first line in your loop will always return the current systems service.

    There is no need for Invoke-Command in this code.


    \_(ツ)_/

    see my reply
    Friday, November 2, 2018 12:46 AM
  • This is all it takes to set remote services to a startup and a state.

    $csvFile = Import-CSV .\SSAS_services.csv
    ForEach ($row in $csvFile){
        Get-Service $row.Service -ComputerName $row.Server |
            Set-Service -Status $row.Task -StartupType $row.'Startup Type' -PassThru
    }

    The rest of your code is totally incorrect and a very bad guess.  I recommend learning PowerShell before trying to modify code you don't understand.


    \_(ツ)_/

    Friday, November 2, 2018 12:48 AM
  • This is all it takes to set remote services to a startup and a state.

    $csvFile = Import-CSV .\SSAS_services.csv
    ForEach ($row in $csvFile){
        Get-Service $row.Service -ComputerName $row.Server |
            Set-Service -Status $row.Task -StartupType $row.'Startup Type' -PassThru
    }

    The rest of your code is totally incorrect and a very bad guess.  I recommend learning PowerShell before trying to modify code you don't understand.


    \_(ツ)_/

    I have actually been scripting with powershell for the past 2 months, i have written multiple complicated scripts. the reason for my if statements is i wanted to output whether the service in the csv file exists on the server, as well as the status of that service before and after the change, both to command pipeline as well as a file. 
    • Edited by cataster Friday, November 2, 2018 12:52 AM
    Friday, November 2, 2018 12:52 AM
  • You do not need most of the code to do that.  The code I posted can be easily modified to do what you want.  Just add a foreach-object in th pipeline and output the info you need. Invoke-Command is not needed and that overly long "if" is totally unnecessary for what you are trying to do.

    The issue reported in the errors are obvious and are because you do not know hoe to use PowerShell CmdLets The error says you have bad elements in the command.

    Without a real foundation in basic PowerShell you will make this kind of mistake and never understand what the error is telling you

    Look at his line  and try to see what you did wrong.  I guarantee mthat you cannot detect your obvious errors;

      if (Get-Service$row.Service | Select-Object Name, StartType, Status -ComputerName $row.Server -ErrorAction SilentlyContinue)

    There are at least three obvious errors that any beginner in PowerShell should be able to see.


    \_(ツ)_/


    • Edited by jrv Friday, November 2, 2018 12:58 AM
    Friday, November 2, 2018 12:58 AM
  • This is all it takes to set remote services to a startup and a state.

    $csvFile = Import-CSV .\SSAS_services.csv
    ForEach ($row in $csvFile){
        Get-Service $row.Service -ComputerName $row.Server |
            Set-Service -Status $row.Task -StartupType $row.'Startup Type' -PassThru
    }

    The rest of your code is totally incorrect and a very bad guess.  I recommend learning PowerShell before trying to modify code you don't understand.


    \_(ツ)_/

    also how would this accomodate for two services or more in a row?
    Friday, November 2, 2018 12:58 AM
  • You do not need most of the code to do that.  The code I posted can be easily modified to do what you want.  Just add a foreach-object in th pipeline and output the info you need. Invoke-Command is not needed and that overly long "if" is totally unnecessary for what you are trying to do.

    The issue reported in the errors are obvious and are because you do not know hoe to use PowerShell CmdLets The error says you have bad elements in the command.

    Without a real foundation in basic PowerShell you will make this kind of mistake and never understand what the error is telling you

    Look at his line  and try to see what you did wrong.  I guarantee mthat you cannot detect your obvious errors;

      if (Get-Service$row.Service | Select-Object Name, StartType, Status -ComputerName$row.Server -ErrorAction SilentlyContinue)

    There are at least three obvious errors that any beginner in PowerShell should be able to see.


    \_(ツ)_/

    i understand, thanks. i have actually received help from some expert on another website that recommended such long script-blocks and the use of $using variable. in that case, as begineers, we cant really know what is the best course to steer our code. I would think that person who answered me knows a lot and what hes doing, but clearly your version is a lot simpler and does almost what i need (beside the output/preliminary checks)

    with that said, can you edit your answer to include the foreach you mentioned in order to output what i want? I know tee-object outputs to command line and file, but if what i have done is incorrect, then i am not sure how to implement what you suggested. it would be much helpful if you can edit that as afinalized answer

    Friday, November 2, 2018 1:03 AM
  • Some "experts" know very little about PowerShell or programming.

    Consider the following:

    Import-CSV .\SSAS_services.csv |
        ForEach-Object{
            Get-Service $_.Service -ComputerName $_.Server -PipelineVariable svc|
                Set-Service -Status $_.Task -StartupType $_.'Startup Type' -PassThru |
                Select-Object PsComputerName, Name, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}
        }

    Before you can do anything effectively you need to start over and relearn the bad concepts you seen to have learned.

    Microsoft Virtual Academy - Getting Started with Microsoft PowerShell


    \_(ツ)_/


    • Edited by jrv Friday, November 2, 2018 1:17 AM
    Friday, November 2, 2018 1:10 AM
  • Some "experts" know very little about PowerShell or programming.

    Consider the following:

    Import-CSV .\SSAS_services.csv
        ForEach-Object{
            Get-Service $row.Service -ComputerName $row.Server -PipelineVariable svc|
                Set-Service -Status $row.Task -StartupType $row.'Startup Type' -PassThru |
                Select-Object PsComputerName, Name, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}
        }

    Before you can do anything effectively you need to start over and relearn the bad concepts you seen to have learned.


    \_(ツ)_/

    thanks for the link. btw, not sure if you had seen my other response, but can you tell me where in this code does it take into account multiple services in a row listed in csv file? in other words, shouldn't there be a
    foreach $row.Service.split(,)
    there so that if there is a case where i want to manipulate multiple services on a server, like server2 example i have in the csv file, it can take care of that as well? 
    Friday, November 2, 2018 1:16 AM
  • Here is an actual tested version of my code with some simple modifications.

    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, SrartType, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}


    \_(ツ)_/


    • Edited by jrv Friday, November 2, 2018 1:26 AM
    • Marked as answer by cataster Friday, November 2, 2018 1:41 AM
    Friday, November 2, 2018 1:25 AM
  • Some "experts" know very little about PowerShell or programming.

    Consider the following:

    Import-CSV .\SSAS_services.csv
        ForEach-Object{
            Get-Service $row.Service -ComputerName $row.Server -PipelineVariable svc|
                Set-Service -Status $row.Task -StartupType $row.'Startup Type' -PassThru |
                Select-Object PsComputerName, Name, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}
        }

    Before you can do anything effectively you need to start over and relearn the bad concepts you seen to have learned.


    \_(ツ)_/

    thanks for the link. btw, not sure if you had seen my other response, but can you tell me where in this code does it take into account multiple services in a row listed in csv file? in other words, shouldn't there be a
    foreach $row.Service.split(,)
    there so that if there is a case where i want to manipulate multiple services on a server, like server2 example i have in the csv file, it can take care of that as well? 

    There is no such row in you script.  Fis the script you have and use it to learn PowerShell before adding new issues.


    \_(ツ)_/

    Friday, November 2, 2018 1:28 AM
  • Here is an actual tested version of my code with some simple modifications.

    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, SrartType, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}


    \_(ツ)_/


    what does 
    @{n and e) mean?
    Friday, November 2, 2018 1:29 AM
  • Some "experts" know very little about PowerShell or programming.

    Consider the following:

    Import-CSV .\SSAS_services.csv
        ForEach-Object{
            Get-Service $row.Service -ComputerName $row.Server -PipelineVariable svc|
                Set-Service -Status $row.Task -StartupType $row.'Startup Type' -PassThru |
                Select-Object PsComputerName, Name, @{n='OldStatus';e={$svc.Status}}, @{n='OldStartType';e={$svc.StartType}}
        }

    Before you can do anything effectively you need to start over and relearn the bad concepts you seen to have learned.


    \_(ツ)_/

    thanks for the link. btw, not sure if you had seen my other response, but can you tell me where in this code does it take into account multiple services in a row listed in csv file? in other words, shouldn't there be a
    foreach $row.Service.split(,)
    there so that if there is a case where i want to manipulate multiple services on a server, like server2 example i have in the csv file, it can take care of that as well? 

    There is no such row in you script.  Fis the script you have and use it to learn PowerShell before adding new issues.


    \_(ツ)_/

    from what i understood from the person who recommended $using, i thought that took care of any number of services in that row. 

    yes i also read the documentation regarding this variable $using, but i didnt really understand its purpose but trusted his expertise that it takes care of getting all services on the row...

    $using:row.Service 
    Friday, November 2, 2018 1:35 AM

  • what does 
    @{n and e) mean?

    Use the link to learn PowerShell and you will understand all of what I have posted. Forums are not good places to learn basic PowerShell.


    \_(ツ)_/

    Friday, November 2, 2018 1:37 AM
  • from what i understood from the person who recommended $using, i thought that took care of any number of services in that row. 

    yes i also read the documentation regarding this variable $using, but i didnt really understand its purpose but trusted his expertise that it takes care of getting all services on the row...

    $using:row.Service 

    From all of your posts it is clear that you are completely lost about how programming and code work.  You must stop and take the time to learn these things.  "$using:varname" does not do what you think.  Without basics you will not be able to understand any of this and your guesses will be forever bad.

    "using" tells a scriptblock in a remote command to reference the variable in the calling scope.


    \_(ツ)_/

    Friday, November 2, 2018 1:44 AM

  • what does 
    @{n and e) mean?

    Use the link to learn PowerShell and you will understand all of what I have posted. Forums are not good places to learn basic PowerShell.


    \_(ツ)_/

    I have learned that @ is an initiator for hashing, n is short for Name, and e is short for expression. the expression outputs to the name. 

    When i ran the script, this is whats printed

    MachineName  : serverhostname
    Name         : MSSQLServerOLAPService
    Status       : Stopped
    SrartType    :
    OldStatus    : Stopped
    OldStartType : Manual

    how come StartType is not populating?

    also, OldStatus and OldStartType are not accurate at all. the service was running before i stopped it, so how is the oldstatus "stopped"? same for oldStartType, it was automatic before not manual as it says....there seems to be a bug here...

    ------------

    btw, i have found out that i can only use IP address for server name. I cannot use CName for server. not even targeting the same server i am logged on. apparently the script prints exception:  Cannot open Service Control Manager on computer ''. This operation might require other privileges.

    its too bad it only works with IP :/


    • Edited by cataster Friday, November 2, 2018 6:00 AM
    Friday, November 2, 2018 6:00 AM