# Because SCCM's built in detection method for checking powershell.exe's version number just doesn't work.
# This script file is just a backup copy for the code that's stored in the app package's detection method.
# It can also be run directly, and if called by a TS, will pass TS variables back to the TS if -CalledFromTS is specified.

# https://david-obrien.net/2013/12/configmgr-powershell-application-detection-methods/
# https://docs.microsoft.com/en-us/previous-versions/system-center/system-center-2012-r2/gg682159(v%3dtechnet.10)?ranMID=43674&ranEAID=je6NUbpObpQ&ranSiteID=je6NUbpObpQ-R6D01_EdS2oeCG4mS3F8nw&epi=je6NUbpObpQ-R6D01_EdS2oeCG4mS3F8nw&irgwc=1&OCID=AID681541_aff_7795_1243925&tduid=(ir__agti36kioskfrizr0c1gdjgco32xhodi2hz9uihf00)(7795)(1243925)(je6NUbpObpQ-R6D01_EdS2oeCG4mS3F8nw)()&irclickid=_agti36kioskfrizr0c1gdjgco32xhodi2hz9uihf00#to-use-a-custom-script-to-determine-the-presence-of-a-deployment-type
#

# Parameters
param(
	# If specified, will run read and set TS variables
	[switch]$CalledFromTS
)

# https://stackoverflow.com/questions/24992681/powershell-check-if-a-file-is-locked
function Test-FileLock {
  param (
    [parameter(Mandatory=$true)][string]$Path
  )
  $oFile = New-Object System.IO.FileInfo $Path
  if ((Test-Path -Path $Path) -eq $false) {
    return $false
  }
  try {
    $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
    if ($oStream) {
      $oStream.Close()
    }
    $false
  }
  catch {
    # file is locked by a process.
    return $true
  }
}

# https://stackoverflow.com/questions/5648931/test-if-registry-value-exists
function Test-RegistryValue {
    param(
        [Alias("PSPath")]
        [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [String]$Path
        ,
        [Parameter(Position = 1, Mandatory = $true)]
        [String]$Name
        ,
        [Switch]$PassThru
    ) 

    process {
        if (Test-Path $Path) {
            $Key = Get-Item -LiteralPath $Path
            if ($Key.GetValue($Name, $null) -ne $null) {
                if ($PassThru) {
                    Get-ItemProperty $Path $Name
                }
				else {
                    $true
                }
            }
			else {
                $false
            }
        }
		else {
            $false
        }
    }
}

$logDir = "c:\engrit\logs"
$logFile = $logDir + "\powershell-detection-method.log"
if(!(test-path -path $logDir)) {
	New-Item -ItemType "directory" -Path $logDir
}
echo "Creating logfile..." | Out-File $logFile
function log($string) {
	echo $string | Out-File $logFile -Append
}

$major = $psversiontable.psversion.major
$minor = $psversiontable.psversion.minor
$build = $psversiontable.psversion.build
$revision = $psversiontable.psversion.revision
$full = "$major.$minor.$build.$revision"

log("PowerShell version: $full")

$exitCode = -1
$result = '$result not set'

if($major -ge "5") {
	# Major version is at least 5
	log("Major version is at least 5.")
	
	if($major -eq "5") {
		# Major version is exactly 5
		log("Major version is exactly 5.")
		
		# Check for minor version
		if($minor -ge "1") {
			# Minor version is at least 1
			log("Minor version is at least 1.")
			
			# Report success
			$result = "Success 1"
			$exitCode = 0
		}
		else {
			# Minor version is less than 1
			log("Minor version is less than 1.")
			
			# Do not report success
			$result = "Fail 1"
			$exitCode = 1
		}
	}
	else {
		# Major version is greater than 5
		log("Major version is greater than 5.")
		
		# Report success
		$result = "Success 2"
		$exitCode = 0
	}
}
else {
	# Not installed
	log("Major version is less than 5.")
	
	# Do not report success
	$result = "Fail 2"
	$exitCode = 2
}

log("Completed version checking logic.")

$succeeded = "False"
$slackMsgStart = '$slackMsgStart not set'
if($exitCode -eq 0) {
	$succeeded = "True"
	Write-Host $resultMsg
	$slackMsgStart = ":heavy_check_mark: WMF/PowerShell 5.1 succeeded!"
}
else {
	# Don't output anything if failed. See links above.
	#Write-Host $resultMsg
	$slackMsgStart = ":no_entry_sign: WMF/PowerShell 5.1 failed to install!"
}

log("succeeded = $succeeded")
log("slackMsg = $slackMsg")

# To double check, read registry variable that should only exist if installation was successful
$regPath = "HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine"
$regValue = "PowerShellVersion"
$regExists = Test-RegistryValue -Path $regPath -Name $regValue
$regData = "unknown"

if($regExists) {
	if($regLocked) {
		$regData = "locked"
	}
	else {
		$regData = (Get-ItemProperty -Path $regPath -name $regValue | select-object $regValue).$regValue
	}
}
else {
	$regData = "doesn't exist"
}

log("regData = $regData")

# To triple check, read file version of powershell.exe
$exePath = "c:\windows\system32\windowspowershell\v1.0\powershell.exe"
$exeCopyPath = "c:\engrit\logs\powershell.exe"

$exeExists = Test-Path -Path $exePath
$exeLocked = Test-FileLock -Path $exePath
$exeVersion = "unknown"
if($exeExists) {
	copy-item $exePath -destination $exeCopyPath
	if($exeLocked) {
		$exeVersion = "locked"
	}
	else {
		$exeVersion = (Get-ItemProperty -Path $exePath).versioninfo.fileversion
	}
}
else {
	$exeVersion = "doesn't exist"
}

log("exeVerstion = $exeVersion")

$exeCopyExists = Test-Path -Path $exeCopyPath
$exeCopyLocked = Test-FileLock -Path $exeCopyPath
$exeCopyVersion = "unknown"
if($exeCopyExists) {
	if($exeCopyLocked) {
		$exeCopyVersion = "locked"
	}
	else {
		$exeCopyVersion = (Get-ItemProperty -Path $exeCopyPath).versioninfo.fileversion
		remove-item $exeCopyPath
	}
}
else {
	$exeCopyVersion = "doesn't exist"
}

log("exeCopyVerstion = $exeCopyVersion")

if(!$CalledFromTS) {
	$detected = "not run from TS"
}
else {
	# Access to TS variables
	$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
	$detected = $tsenv.Value('EngrIT_WMFDetected')	
}

$logMsg = "$slackMsgStart Result: $result, Succeeded: $succeeded, Exit code: $exitCode, Version (ps): $full, Version (reg): $regData, Version (exe): $exeVersion, Version (exe copy): $exeCopyVersion, Detected by detection method: $detected"

log($logMsg)

if($CalledFromTS) {
	$tsenv.Value('EngrIT_PowershellSucceeded') = $succeeded
	$tsenv.Value('EngrIT_PowershellDetectionMsg') = $logMsg
}
	
Exit $exitCode