Powershell IF Statement not Executing

by Typeo at 2013-01-25 08:23:44

I setup a somewhat simple Powershell script to install and setup the SNMP service on Server 2008. I had the script working fine, but wanted to add a bit of error checking in with some IF Else statements. I seem to have ran into a road block, and can’t get the second IF statement in the script to run on the first passthrough.


#This Script will install the SNMP Windows Features (SNMP-Service and SNMP WMI Provider) and make changes so it up to be able to talk to Krang (Solarwinds).

# Setting up variables
$ComPath = ‘HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SNMP\Parameters\ValidCommunities’
$HostPath = ‘HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SNMP\Parameters\PermittedManagers’
$FWPath = ‘HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SharedAccess\Parameters\FirewallPolicy\FirewallRules’

#Importing ServerManager Module
Import-Module ServerManager

$SNMPCheck = Get-WindowsFeature | Where-Object {$.Name -eq ‘SNMP-Service’}

#Checks to see if SNMP Service is installed or not.. If not, it will install the service
If ($SNMPCheck.Installed -ne ‘True’)
{
#Installing windows SNMP Service Feature and its subfeature
Add-WindowsFeature -Name SNMP-Service -IncludeAllSubFeature
}

#Checks to see if SNMP service is installed or not.. If so, it will make nessesary regestry changes for Krang
If ($SNMPCheck.Installed -eq ‘True’)
{
#Directory Change to make edits to the Registry
CD HKLM:

#Registry change to add SNMP community string
New-ItemProperty -Path $ComPath -Name ‘CommString’ -Type DWORD -Value 4 -Force

#Registry change to add accpeted hosts (This will overide any
New-ItemProperty -Path $HostPath -Name 2 -Type String -Value 111.11.11.1 -Force

#Registry change to edit the inbound filewall rule
New-ItemProperty -Path $FWPath -Name SNMP-In-UDP -Type String -Value ‘v2.10|Action=Allow|Active=TRUE|Dir=In|Protocol=17|Profile=Private|Profile=Public|LPort=161|RA4=111.11.11.1|App=%SystemRoot%\system32\snmp.exe|Svc=SNMP|Name=@snmp.exe,-8|Desc=@snmp.exe,-10|EmbedCtxt=@snmp.exe,-3|’ -Force

#Registry change to edit the outbound firewall rule
New-ItemProperty -Path $FWPath -Name SNMP-Out-UDP -Type String -Value ‘v2.10|Action=Allow|Active=TRUE|Dir=Out|Protocol=17|Profile=Private|Profile=Public|RPort=161|RA4=111.11.11.1|App=%SystemRoot%\system32\snmp.exe|Svc=SNMP|Name=@snmp.exe,-9|Desc=@snmp.exe,-11|EmbedCtxt=@snmp.exe,-3|’ -Force

#Directory change back to C:<br> CD C:<br>
#Restarting SNMP service to accept changes
Restart-Service -Name SNMP -force

#Keeps the powershell window from closing automaticly
Read-Host ‘Powershell has been installed and setup properly, press Enter to continue...’
}

#Runs if it runs into issues with installing SNMP service
Else {Read-Host ‘Error: SNMP Services could not install correctly! Press Enter to exit...’}


Basicly, when I run the script the first time, it sees that SNMP is not installed, so it installs it. It should then jump to the second if statement and check to see if it has been installed or not… If it was properly installed, the second if statement should then run to make all the nessessary changes.

However, what actually happens is… I run the script, and it sees SNMP is not installed. The first IF statement runs and installes SNMP. It completly skips the second IF statement and goes directly to the ending ELSE statement. If I were to run the script a second time it would skip the first IF statement (Since SNMP is already installed) and correctly execute the second if statement since SNMP has indeed been installed…

Why do I have to run the script twice to get the desired effect? The second IF statement seems to get getting skipped on the first run through of the script. Any ideas why this might be happening?

Thanks for the help,
Typeo
by nohandle at 2013-01-25 09:39:54
Strange, I kept the formatting and it seems to work for me.
are you sure the $SNMPCheck.Installed is true before the second if? Have you stepped the code to see how exactly it is executed? Try placing write-host $SNMPCheck.Installed right before the second if to see the state.

if the result is boolean, doing -eq ‘true’ is totally unnecassary and sooner or later you will mistype the ‘true’ string and then wonder why your logical tests doe not work. Do simply if (-not $SNMPCheck.Installed) {‘this is output when the installed was false’}or ($SNMPCheck.Installed) {‘this is output when the installed was true’} to take the action if the variable is false or true.’ :slight_smile:
by Typeo at 2013-01-25 10:08:30
Hi Nohandle,

I am fairly new at Powershell (started a couple weeks ago), How would you go about stepping through the code? I will put the write-host $SNMPCheck.Installed right before the second if statement to see what it comes back with and will update the post so you know.

I kind of lost you on the second paragraph.Are you saying that instead of trying to do the -eq ‘True’, it would be safer to do:

if (-not $SNMPCheck.Installed) {‘this is output when the installed was true’} for true

and

if ($SNMPCheck.Installed) {‘this is output when the installed was true’} for false

If I am understanding correctly, the first one is stating that if $SNMPCheck is not installed run {x} and the second statement is just if $SNMPCheck is installed run {x}?

UPDATE:

After adding in the write-host $SNMPCheck.Installed right before the second if statement, and running the script, it actually came back as False… What would cause it to do this?

If I run the script again right after the first time, it returns as true… For some reason on the first pass through, right after SNMP has been installed it comes back with a false, but then running it again, it returns true.
by sunnyc7 at 2013-01-25 15:18:40
try replacing the second IF statement with

ElseIf ($SNMPCheck.Installed -eq ‘True’)
by Typeo at 2013-01-25 17:58:18
Only issue with that is whether the send IF statement (or ELSE IF if I changed it) it would still rely on SNMPCheck.Installed to equal true to be able to execute… However, as stated in a bit more detail in the last post, the SNMPCheck.Installed is still registering as false when it gets to the second IF statement. So sadly, whether it was IF or ELSE IF, I don’t think would make a difference.
by nohandle at 2013-01-26 03:26:03
[quote="Typeo"]I am fairly new at Powershell (started a couple weeks ago), How would you go about stepping through the code?[/quote]
Get yourself a PowerGui then use F11 to step through the code.
Or you can use Poweshell ISE that is probably availible on you station, but in it you need to save the script first, set break point (F9) run the script, wait until it runs to the brakpoint and then you can step it using the F11
[quote="Typeo"]I kind of lost you on the second paragraph.Are you saying that instead of trying to do the -eq ‘True’, it would be safer to do:
if (-not $SNMPCheck.Installed) {‘this is output when the installed was true’} for true
and
if ($SNMPCheck.Installed) {‘this is output when the installed was true’} for false[/quote]
Sorry, I was trying to compress to much info into one paragraph. You got it the other way around. You basically do three things that make the test more error prone:
1) you are testing the equality against string ‘true’ instead of the variable $true that contains the logical true
2) you first test $something -ne $true and then $something -eq $true spotting the difference is easier when you test $something -eq $false and $something -eq $true
3) testing against the $true brings chance of mistyping to $treu (for example), than your test stops working.
this ($something) is the same as ($something -eq $true)
this (-not $somtehing) is the same as ($somtehing -eq $false)

[quote="sunnyc7"]try replacing the second IF statement with

ElseIf ($SNMPCheck.Installed -eq ‘True’)
[/quote]
This would change the logic. The OP needs to test if the service is running and if it is not then it is started. Then the state is tested again. Else would skip the second part. [quote="Typeo"]the SNMPCheck.Installed is still registering as false when it gets to the second IF statement.[/quote]
You probably need to load the state before the second if, the info in the variable is not live.
$SNMPCheck = Get-WindowsFeature | Where-Object {$
.Name -eq ‘SNMP-Service’}
by Typeo at 2013-01-28 07:19:46
[quote="nohandle"][quote="Typeo"]the SNMPCheck.Installed is still registering as false when it gets to the second IF statement.[/quote]
You probably need to load the state before the second if, the info in the variable is not live.
$SNMPCheck = Get-WindowsFeature | Where-Object {$.Name -eq ‘SNMP-Service’}[/quote]

This seemed to resolve the issue for me, thank you very much for the help!

One last question if you don’t mind. Doesn’t the $SNMPCheck = Get-WindowsFeature | Where-Object {$
.Name -eq ‘SNMP-Service’} command just grab the SNMP-Service name? I then thought that the SNMPCheck.installed is what determined whether or not it was installed.

If that is the case, why would grabbing the SNMP feature again make the variable true on whether it was installed or not?

Either way, doing that fixed the problem… Thanks a bunch to everybody that helped out!

Typeo
by nohandle at 2013-01-28 07:53:26
Great. Now to your question: Imagine the data you get back from the get-windowsFeature cmdlet as a table. For simplicity the table has just two columns one called name and the other installed. There are two rows in the table, for the snmp-service (i will refer it simply as snmp) and one for RSAT. The table looks like this:
Name Installed
Snmp True
Rsat True

Now what the ‘where’ does is it enables you to filter the rows based on the value in certain column(s). You specify header ‘name’ and value ‘snmp’ and get back the whole row. But you dont get live link to the row you get just ‘dead’ copy. (Usually, but lets focus on this case)

So if you test the data first the installed says the feature is not installed. You install it in the first if but the data in your dead copy still say it is not installed. So you issue the query againg and get new updated copy before doing the second ‘if’. Your updated copy states the snmp feature is installed and you mat process the body of the second if.

Going back to the table metaphor you could select certain column for all of the rows using ‘select-object’.