Exit main script based off if else

This topic contains 0 replies, has 1 voice, and was last updated by  Forums Archives 5 years, 10 months ago.

  • Author
    Posts
  • #5442

    by sharpton at 2013-01-16 06:05:30

    Hello all,

    I have been searching for an answer and cannot seem to find it. I am a Powershell rookie, I have everything working as it should except for how my if/then is handled inside an invoke-command script. Earlier in my script I start a site on a remote server to add it to a load balancer pool. The site starts fine. My problem begins when I try to check that the site is actually started and if it is not, exit the script. The invoke command is exiting, I want the main script to stop when the site is not started and "else" is used.

    I know it is reaching the else part, because it will write my text, it just does not exit. This works outside of the invoke-command.

    Sample:

    #added to test a failure
    Write-Host "The site should now be started on $server2, stop it to create a fail condition, press any key to continue"
    $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

    Invoke-Command -ComputerName "$server2" -Credential $cred -ScriptBlock { import-module webadministration; if ((Get-WebsiteState -Name "CSS Monitoring").Value -eq "Started") {
    Write-Host "CSS Monitoring Started on $args" }
    ELSE
    { Write-Host "CSS Monitoring did not start on $args, script halted"
    exit }
    } -argumentlist $server2

    #added to see if the script exits or not above.
    Write-Host "The script continued"

    Your help is greatly appreciated.

    Sharpton

    by DonJ at 2013-01-17 06:53:14

    Ugh, Write-Host. Yuck.

    You're kind of doing the logic wrong. If the site exists, just allow the script to fall through to the end and complete naturally. Any code you want executed if the site does not exist, should be in the other part of the If construct, so that it doesn't execute if the site exists. In other words, you really shouldn't ever use exit to bail on a script.

    by sharpton at 2013-01-17 07:30:03

    [quote="DonJ"]Ugh, Write-Host. Yuck.

    You're kind of doing the logic wrong. If the site exists, just allow the script to fall through to the end and complete naturally. Any code you want executed if the site does not exist, should be in the other part of the If construct, so that it doesn't execute if the site exists. In other words, you really shouldn't ever use exit to bail on a script.[/quote]

    Not sure which logic is wrong here. I am not checking if the site exists. I am checking if the site is stopped/started. If the site did not stop/start, I do not want the script to continue as the site/server needs to be removed/added to/from the pool before I do maintenance on it. Write-Host yuck? What else can I do to have interactive messages passed to the user of the script?

    by DonJ at 2013-01-17 07:40:29

    LOL... sorry, the Write-Host is a thing of mine.

    So, let me pseudo-code this out to maybe illustrate the concept. I'm not saying you're doing anything wrong – just that you're maybe thinking about it wrong.


    if ($something -eq $else) {
    # do this
    } else {
    # do nothing
    }

    That should be the sum total of your script. If the site doesn't exist, do something about it. If it does exist, don't do anything – maybe log a status message, sure, but don't actually take any actions. My point is that there's no need to explicitly exit the script. Either way, it "falls through" to the end of the script file, and that's the end, and PowerShell will "exit" automatically. That's what you want it to do, rather than commanding it to exit somehow (because, as you've seen, it doesn't like being told to do that in some contexts). Looking at the code you provided, you've basically got that – you just don't need the exit.

    What you don't want to do, and what I don't think you are doing, is this:


    if ($something -eq $else) {
    # do something
    } else {
    # do nothing
    }
    # some other code that I only want to run
    # if $something -eq $else

    In that case, I *would* need an explicit exit in the "do nothing" block, because after the If construct I'm proceeding to run some other code. That's a bad logic setup, because my script can't naturally fall through to the end of the script.

    Does that make more sense? Again, the goal here is "don't explicitly exit the script" – it's just making sure your logic is structured so that you don't *have* to issue the exit statement. Just let the script end.

    As for Write-Host, it's main problem is that it draws pixels directly on the screen. There are other commands – Write-Verbose is one I'm thinking of – that are specifically intended to be used for that kind of interactive status message. At the top of your script, set $VerbosePreference='Continue' to enable the use of Write-Verbose. PowerShell deals with Verbose output as a specific pipeline, and can capture it independently of other output. For example, were you to run this script as a background job, your Write-Host wouldn't be captured, but verbose output could be.

    by sharpton at 2013-01-17 08:36:51

    Thanks for your reply. I see what you are saying, but I want to "do" something in either if or else. Basically if I hit else, that is bad. I want the entire main script to terminate. This works perfectly fine on the local machine not using the invoke command cmdlet.

    This script is used for failover of a web server farm. I need to stop a certain site on each server to remove it from a pool. Ihave done that already earlier in my script. I am now checking that the stopping of the site has worked on a remote server. If it has not worked, I wanted inform the person running the script of this, and halt the entire script. What is happening here is the invoke-command is exiting, and not the main script. I want to pass that up to the main script. Here is some more stuff you can laugh at that I created.

    Example of local calls which work perfectly whether "if" or "else" is encountered. All I want to do is this on a remote machine and exit the main script when "else" is encountered.

    # —-Stop website on the server that will host the maintenance page—-

    stop-website -Name "CSS Monitoring"
    set-Itemproperty "IIS:\Sites\css monitoring" serverautostart false

    if ((Get-WebsiteState -Name "CSS Monitoring").Value -eq "Stopped") {
    Write-Host "CSS Monitoring Stopped on $Server1" }
    ELSE
    { Write-Host "CSS Monitoring did not stop on $Server1, script halted, press any key to continue"
    $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
    exit
    }
    Write-Host "Success"

    In the above, when I run this, all works as it should. In the example above, if site did not stop, it will echo "CSS Monitoring did not stop" and the script will end.

    If I do this same thing remotely like this, the script always moves on whether I hit the "exit" or not.

    # —-Stop CSS Monitoring on all remote servers—-

    Write-Host "Stopping CSS Monitoring on remote servers"

    Invoke-Command -ComputerName "$server2" -Credential $cred -ScriptBlock { import-module webadministration; Stop-Website "CSS Monitoring" }

    Invoke-Command -ComputerName "$server2" -Credential $cred -ScriptBlock { import-module webadministration; if ((Get-WebsiteState -Name "CSS Monitoring").Value -eq "Stopped") {
    Write-Host "CSS Monitoring Stopped on $args" }
    ELSE
    { Write-Host "CSS Monitoring did not stop on $args, script halted, press any key to continue"
    $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
    exit }
    } -argumentlist $server2

    The "exit" in my "else" is not honored at the main script level, it must be honored inside the invoke command. Does this make sense? When doing this local to a machine, all is well. Remote, not so much. I am contemplating creating and passing my own exit codes, but this is clunky. Let me know if you know a better way. If not, I am confident that the command to stop/start sites will work. If it does not it will error, this should raise a flag with the person running it.

    by nohandle at 2013-01-17 09:22:43

    Hi, I agree with Don it is usually better to design the script in a way that does not require escaping from the code prematurely. But sometimes jumping out of the scope before it has run to completion is useful technique to minimize number of nested Ifs etc. I think what you are looking for are break or return keywords. Look them up to get description of the usage and what scope they jump out.
    Here is short example:
    Invoke-Command -ComputerName localhost -ScriptBlock {
    if ($true)
    {
    "Here I am."
    break
    }
    else
    {
    "This should not run."
    }
    }
    "This should run after the invoking is done."

    by DonJ at 2013-01-17 09:39:42

    Ah. Well, if it's bad, then how about throwing an error? Use Throw. That'll end the script. Break does, too.

    by nohandle at 2013-01-17 09:49:28

    Reading it again I stand corrected. Throwing an exception clearly indicates something really bad happened and hence is better solution.

    by sharpton at 2013-01-17 10:25:22

    I changed it to throw, and this throws an exception as I would expect, but the script continues just as it did when I had "exit" in the else command. The commands are doing what they should be, just not at the main script. I will try to find another way to do this, perhaps a remote PS session.

You must be logged in to reply to this topic.