Link to home
Start Free TrialLog in
Avatar of Joe
JoeFlag for United States of America

asked on

Powershell Question

I am working on a powershell script to take this command.

Get-WmiObject -Class Win32Reg_AddRemovePrograms | Select-String -Pattern "exchange"

and if it equals this:

\\A01344\root\cimv2:Win32Reg_AddRemovePrograms.ProdID="Microsoft Exchange v14"

Then do nothing.

But if it does not equal that then run a reg file.

I am new at this please assist. Thank you in advance.
Avatar of Brandon Mac
Brandon Mac

are you trying to check to see if Microsoft exchange and specific version is installed ? If so it would probably be best to do this by a reg key as add/remove programs doesn't always contain all the information.
Avatar of Joe

ASKER

No I am running a reg file to fix some SSL/TLS vulnerabilities but we don't want to run it on Exchange yet.  The powershell script just lets us know if exchange is installed.
ASKER CERTIFIED SOLUTION
Avatar of Ben Personick (Previously QCubed)
Ben Personick (Previously QCubed)
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Joe

ASKER

Here is what I went with.

$findexchange = Get-Service | where {$_.Name -like "*exchange*"}
$findSQL = Get-Service | where {$_.Name -like "*SQL*"}

if (($findexchange -or $findSQL) -eq "") 
    {
    #echo "I did not find SQL or Exchange procede"


    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\DES 128/128”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\DES 56/56”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\NULL”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 64/128”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\Triple DES 168”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Server”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client”)
    $Key.SetValue(“DisabledByDefault”, “1”, [Microsoft.Win32.RegistryValueKind]::DWORD)
    $Writable = $True
    $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $Writable).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server”)
    $Key.SetValue(“Enabled”, “0”, [Microsoft.Win32.RegistryValueKind]::DWORD)

Open in new window

Avatar of Joe

ASKER

These aren't the actual answers but they both tried to help. Hopefully my solution will help someone. If you all have any suggestions then please feel free to keep commenting.

Thank you!!
You took a different route for checking for specific software. That's ok.

But are aware that your original question asked for installed Exchange (which also includes Exchange Management Shell on a client), but you now check for services of Exchange and SQL? The latter might even be wrong, any service with SQL in it will stop.
I'm not clear whether you want to check for both services (only if both are installed, stop changing registry), or as soon as one of them is found.
The line
if (($findexchange -or $findSQL) -eq "")

Open in new window

is probably not what you are after. -or is a logical operator, combining boolean expressions, and resulting in a boolean expression, so the check for -eq "" is formally wrong. In fact, what that expression checks is:
   ($findexchange -or ...)      => $findexchange not empty
   (... -or $findSQL)                => $findSQL not empty
   => any of the services found
   ((... -or ...) -eq "")                => NOT any of the services found  => NO service found
It would be much better to just say
if (!$findexchange -and !$findSQL)

Open in new window


Further, Get-Service supports wildcard search, and you should use that, as it is much faster. And if you ever will use it remotely, it means a real difference.
$findexchange = Get-Service "*exchange*"
$findSQL = Get-Service "*SQL*"

Open in new window

or even better (making the vars real booleans)
$findexchange = @(Get-Service "*exchange*").Count -gt 0
$findSQL = @(Get-Service "*SQL*").Count -gt 0

Open in new window


The registry change has not been part of the question (you said you already have that ready for use). The way you do that could be simplified without changing the way it works, by using a helper function:
function write-SCHANNEL($subkey, $name, $value, $type)
{
  $Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $true <# Writable #>).CreateSubKey(“CurrentControlSet\Control\SecurityProviders\SCHANNEL\$subkey")
  $Key.SetValue($name, $value, [Microsoft.Win32.RegistryValueKind]::DWORD)
}

  write-SCHANNEL "Ciphers\DES 128/128”      Enabled 0
  write-SCHANNEL "Ciphers\DES 56/56”"       Enabled 0
  write-SCHANNEL "Ciphers\NULL”             Enabled 0
  write-SCHANNEL "Ciphers\RC4 64/128”       Enabled 0
  write-SCHANNEL "Ciphers\Triple DES 168”   Enabled 0
  write-SCHANNEL "Protocols\PCT 1.0”        Enabled 0
  write-SCHANNEL "Protocols\PCT 1.0\Server" Enabled 0
  write-SCHANNEL "Protocols\TLS 1.0\Server" Enabled 0

  write-SCHANNEL "Protocols\TLS 1.0\Client” DisabledyDefault 1

Open in new window

On another note, you should not provide points just because Experts tried to help. There has to be real value for you (or at least for other members seeing the question). Ben's code would have worked.
Since I only provided a small improvement of Ben's code, getting half the points for that is unfair to him. I know it is the default in the closing wizard, and changing the point split requires additional steps, but there are times you should go that extra mile ;-).
@Josef Al-Chacar,

  What?

  The code offered in our posts does work, Qlemo is just pointing out the extra parens aren't really necessary.

  In your question, you did not describe wishing to check for two different values although that is easily done in the original portion by collecting the entry for both and still checking a single variable, or as you have done it using two checks and two variables.

But, you should change -eq "" to be -not to negate the contents of your -or.

  While using -eq ""  is serving the same purpose as using -not it's bad coding practice as -eq "" is not the intended method for negating a value so it may not behave as expected in all scenarios even though it is working here.  Since there is an easier more direct method which was specifically designed to do this, it isn;t worth using -eq "" for the purpose that -not already carries out.

  Much like Qlemo I see you're using some practices here you could do away with to make your life easier

 I also agree with him that you did not want the code for writing the values in the original request, nor did you even hint this was an issue once working answers were provided.

  In addition, just as Qlemo stated, you have changed from looking to see if any exchange products are installed to checking to see if the services are there, which changes the nature of your question, maybe that was a better description of your needs, but it would be better to simply tell the experts that you realised you didn;t want to check for any exchange tools or SQL tools, just see if the services were present, and we'd have simply changed over to the same cmdlet.

-- Edit: updated comment because I started writing before Qlemo had posted and needed to run down to get food and posted a half comment so I wanted to fix the formatting and finish my thoughts.
I like Qlemo's Idea to use a 'helper function' when you need to call a piece of code several times it's of big use.

 But whether you use a helper function or not I think there is a lot of benefit for using a for-loop here, when I need to make a lot of repetitive changes I much prefer having a single place to change values in variables and then looping through the values.

  Here is your code which I have rewritten to be faster and more efficient.

  You could easily change the body of the for-loop to call his function if preferred.


$DebugPreference="Continue"
$ServiceExists = $( Get-Service "*exchange*"; Get-service "*SQL*" )
$RootKey = "CurrentControlSet\Control\SecurityProviders\SCHANNEL"
$KeysValues =@(
	@("Ciphers\DES 128/128","Enabled",0),
	@("Ciphers\DES 56/56","Enabled",0),
	@("Ciphers\NULL","Enabled",0),
	@("Ciphers\RC4 64/128","Enabled",0),
	@("Ciphers\Triple DES 168","Enabled",0),
	@("Protocols\PCT 1.0","Enabled",0),
	@("Protocols\PCT 1.0\Server","Enabled",0),
	@("Protocols\TLS 1.0\Server","Enabled",0),
	@("Protocols\TLS 1.0\Client","DisabledyDefault",1)
)
IF (-not $ServiceExists) {
	write-Debug "I did not find SQL or Exchange.  Okay to proceed.`r"
	Foreach ($KeyValue in $KeyValues) {
		$KeyObject = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $True).CreateSubKey("$RootKey\$KeyValue[0]")
		$KeyObject.SetValue($KeyValue[1], $KeyValue[2], [Microsoft.Win32.RegistryValueKind]::DWORD)
	}
}

Open in new window

That loop idea came into my mind too, of course. I decided that it would be better (i.e. more clear) to use the helper function. But technical, it's no difference, just a matter of taste. One change I would make to that script is to properly align the array content (as in my code snippet), because I'm obsessive about that :D.
Well, to be fair, none of those Ideas are really mutually exclusive from one another anyway so you can have your cake and eat it too.

Here's both together for the heck of it.

function write-SCHANNEL($subkey, $name, $value ) {
	$Key = (Get-Item HKLM:\).OpenSubKey(“SYSTEM”, $true <# Writable #>).CreateSubKey(“$RootKey\$subkey")
	$Key.SetValue($name, $value, [Microsoft.Win32.RegistryValueKind]::DWORD)
}

$DebugPreference="Continue"
$ServiceExists = $( Get-Service "*exchange*"; Get-service "*SQL*" )
$RootKey = "CurrentControlSet\Control\SecurityProviders\SCHANNEL"

$KeyValues =@(
	"Ciphers\DES 128/128          Enabled              0",
	"Ciphers\DES 56/56            Enabled              0",
	"Ciphers\NULL                 Enabled              0",
	"Ciphers\RC4 64/128           Enabled              0",
	"Ciphers\Triple DES 168       Enabled              0",
	"Protocols\PCT 1.0            Enabled              0",
	"Protocols\PCT 1.0\Server     Enabled              0",
	"Protocols\TLS 1.0\Server     Enabled              0",
	"Protocols\TLS 1.0\Client     DisabledyDefault     1"
)

IF (-not $ServiceExists) {
	Foreach ($KeyValue in $KeyValues) {
		$Tmp_KVA += $KeyValue -split "     +"
		write-SCHANNEL $($Tmp_KVA[0]) $($Tmp_KVA[1]) $($Tmp_KVA[2])
	}
}

Open in new window

Edit, Re-pasted the non-function code yesterday, today I posted the code that should have been there.

Combines the function (hey, who knows when you might need to use it again), with the loop (because simpler/neater), with the Formatting to keep values in the same spacing (Because, hey, why not, easy enough to do either way depending on which you like :))

Edit: Although, in looking at it today I noticed I had a += instead of = for the split value, whoops, that would only have allowed it to set the 1st value.  Here is that + sign removed:

# Script: EnableSChannel.ps1
# Version: 1.1
function write-SCHANNEL($subkey, $name, $value )
{
	$Key = (Get-Item HKLM:\).OpenSubKey("SYSTEM", $true <# Writable #>).CreateSubKey("$RootKey\$subkey")
	$Key.SetValue($name, $value, [Microsoft.Win32.RegistryValueKind]::DWORD)
}


$DebugPreference="Continue"
$ServiceExists = $( Get-Service "*exchange*"; Get-service "*SQL*" )
$RootKey = "CurrentControlSet\Control\SecurityProviders\SCHANNEL"
$KeyValues =@(
"Ciphers\DES 128/128          Enabled              0",
"Ciphers\DES 56/56            Enabled              0",
"Ciphers\NULL                 Enabled              0",
"Ciphers\RC4 64/128           Enabled              0",
"Ciphers\Triple DES 168       Enabled              0",
"Protocols\PCT 1.0            Enabled              0",
"Protocols\PCT 1.0\Server     Enabled              0",
"Protocols\TLS 1.0\Server     Enabled              0",
"Protocols\TLS 1.0\Client     DisabledyDefault     1"
)
IF (-not $ServiceExists) {
	Foreach ($KeyValue in $KeyValues) {
		$Tmp_KVA = $KeyValue -split "     +"
		write-SCHANNEL $($Tmp_KVA[0]) $($Tmp_KVA[1]) $($Tmp_KVA[2])
	}
}

Open in new window