Jump to content

Powershell: I feel like my code is kludgy, but can't figure out how to smoothen it.


Recommended Posts

Posted

$splitvar = "(0)", "(1)", "(2)", "(3)" 									# Junk entries for splitvar. Required for the while-loop (cannot reference null variable)
Write-Host 'ComputerName E:(Y/N) [R:(Y/N) P:(K/S)], or /? for help' 	# Instruction and command format
while (($splitvar[1] -inotmatch "^e:(y|n)$") -or ($splitvar[2] -inotmatch "^r:(y|n)$") -or ($splitvar[3] -inotmatch "^p:(s|k)$")) {		# Whilst splitvar1 is not E:(Y/N), splitvar2 is not R:(Y/N) or splitvar3 is not P:(S/K)
$splitvar = "(0)", "(1)", "(2)", "(3)" 		# Junk entries for splitvar to ensure no previous command entries are remembered
$command = Read-Host "	" 					# Requests command, assigns to $command var
if ($command -match "\/\?") { 																# if /? is entered
	clear																					# clear window
	Write-Host "Commands are as follows. All are case-insensitive"							# Information
	Write-Host "ComputerName	The name of the target machine, e.g. SCILT3-017"			# about each 
	Write-Host "E:(Y/N)		Email the results to an internal email address. e.g. E:Y"		# acceptable 
	Write-Host "F:(Y/N)		Has the damage been repaired? Affects e-mail body. e.g. F:N"	# command and
	Write-Host "P:(K/S)		Specify the damaged part, Screen or Keyboard, e.g. P:K"			# its indended
	Write-Host "		(F and P are not required if E:N)"									# usage
	Write-Host @() 																			# Blank line
	Write-Host 'ComputerName E:(Y/N) R:(Y/N) P:(K/S)' 										# Repeated command
} else { 														# if /? is not entered
	$splitvar = [regex]::split($command, " ") 					# split the command at spaces
	if ($splitvar[1] -imatch "^e:n$") { 						# if splitvar1 (E:?) matches [beginning]e:n[end] (case insensitve match) - i.e do not email results
		$splitvar = $splitvar[0], $splitvar[1], "r:y", "p:k" 	# set splitvar as ComputerName, E:N, R:Y, P:K (R and P entries not important and are never referenced, but required to break out of while loop)
	} elseif (($splitvar[1] -inotmatch "^e:(y|n)$") -or ($splitvar[2] -inotmatch "^r:(y|n)$") -or ($splitvar[3] -inotmatch "^p:(s|k)$")) { 	# if splitvar1 is not E:(Y/N), splitvar2 is not R:(Y/N) or splitvar3 is not P:(S/K)
		Write-Host "Please ensure correct command formatting." 																				# throw error message
	}
}
}
$fqdn = ($splitvar[0] + ".domain.local") 				# Append domain to splitvar0 to create FQDN
Write-Host ("Testing connectivity to " + $fqdn) 	# Status message
$ErrorActionPreference = "Stop" 					# Stop if an error is encountered - Required for try/catch.
try {
Test-Connection -ComputerName $fqdn -Count 2 | Out-Null		# Ping $fqdn, output to null as ip/response time isn't of importance - only that it does respond.
} catch {														# If ping fails
Write-Host "Error: Could not connect to $fqdn"				# Throw error message
Write-Host "Check name, power and connectivity status." 	# Advise
Start-Sleep -Seconds 5 										# Wait 5 seconds
exit 														# Exit script
}
while ($me -eq $null) { 					# If $me has no value..
try { 
	if ($splitvar[3] -imatch "^p:k$") {						# If splitvar3 is P:K (case insensitive)
		[int]$me = Read-Host "MaxEvents? (Default: 4)" 		# Prompt user for the MaxEvents value (as multiple users may be required to see who caused the damage)
		if ($me -eq "") { 									# If no value is given,
			$me = [int]4 									#default to 4
		}
	} elseif ($splitvar[3] -imatch "^p:s$") {	# If splitvar2 is P:S (case insensitive)
		$me = [int]1							# set MaxEvents as 1 (nobody would logon to a broken screen laptop, so only the last user is required)
	}
} catch {															# If $me cannot be convered to an 32bit integer
	Write-Host "Error: MaxEvents may only be a numerical value." 	# display error message.
}
} 
$ErrorActionPreference = "Inquire" 		# Prompt user if any further error is encountered.
$logFile = "M:\" + $cn + "Log.txt" 		# Set log file name using $cn
[int]$count = 0 #						 Set counter to 0
foreach ($event in Get-WinEvent -ComputerName "$fqdn" -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents $me) { # Query eventlog of $fqdn, return $me instances of Microsoft Windows Security Auditing logs with ID of 4624 (Logon) containing the phrase C:\...\winlogon.exe
$newtime = [regex]::split($event.timecreated, "/") 					# Split date at /'s
$newtime = ($newtime[1] + "/" + $newtime[0] + "/" + $newtime[2]) 	# Rearrange date from MM/DD/YYYY to DD/MM/YYYY
$count ++ 															# +1 to count
if ($splitvar[1] -imatch "^e:y$") { 				# if splitvar1 is e:y (so an email is being sent)
	if ($splitvar[3] -imatch "^p:k$") {				# if splitvar3 is p:k (the damaged part is a keyboard)
		$part = "keyboard"							# set $part as 'keyboard' (for use in email body)
	} elseif ($splitvar[3] -imatch "^p:s$") {		# if splitvar3 is not p:k but is p:s (the damaged part is a screen)
		$part = "screen"							# set $part as 'screen'
	}
	$fulllogs += $newtime + ([regex]::split($event.message, "`r`n") | Where {$_ -match '	Account Name:		'+ "[^-\$]*$"}) + "`r`n" # add DD/MM/YY HH:MM:SS Account Name: USERNAME (as defined by the event log) to fulllogs array
	$body = "This is an automated e-mail. Replies will be sent to [email protected]`r`n`r`nIt has been brought to our attention that " + $splitvar[0] + " has had its " + $part + " damaged. In accordance with regular procedures, the previous $me logon(s) to that machine are as follows:`r`n`r`n$fulllogs`r`n" # construct first half of email body with logon information and computername
	if ($splitvar[2] -imatch "^r:y$") { 																			# if splitvar2 is r:y (case insensitive)
		$body += "The $part has been fully restored and the laptop will be returned to its appropriate set." 		# Append 'fixed and returned' to email body
	} elseif ($splitvar[2] -imatch "^r:n$") { 																								# if splitvar2 is r:n (case insensitive)
		$body += "Unfortunately we lack the required parts to repair the damage and will keep the laptop as spares for your department" 	# append 'cannot be fixed' to email body
		if ($part -imatch "keyboard") {																					# If the damaged part is a keyboard
			$body += ", unless you wish to purchase a replacement keyboard. Please let me know if this is the case." 	# append query about purchasing replacement
		} elseif ($part -imatch "screen") {		# if damaged part is a screen
			$body += '.'						# end message
		}
	}
} elseif ($splitvar[1] -imatch "^e:n$") { # if splitvar1 is not e:y and is e:n (case insensitive)
		$fulllogs += ([string]"Log $count`r`n----------" + $newtime + "----------`r`n" + $event.message + "`r`n" -replace [string]"(?s)Detailed.*key was requested.", "---------- Event message end ----------`r`n`r`n") # Take the newtime and message values, strip out junk data and add to $fulllogs
}
}
if ($splitvar[1] -imatch "^e:y$") { # if splitvar1 is e:y (case insensitive)
$recip = Read-Host "Email Recipient (Username)" # ask for the username of the email recipient
$to = ('"' + $recip + ' <' + $recip + '@domain.location.sch.uk>"') # Append details to create full email address
Send-MailMessage -smtpserver 'email-server' -To $to -Cc "Me " -From "Me " -Subject $splitvar[0] -Body $body # send email to user and me, from me
Start-Sleep -Seconds 3 # 3-second wait (send-mailmessage fails if it is the final command)
} elseif ($splitvar[1] -imatch "^e:n$") { # if splitvar1 is not e:y but is e:n
"Previous $count/$me logon events for $fqdn `r`n`r`n$fulllogs" > $logFile # Write $fulllogs to $logfile
Start-Process $logFile -wait # Open $logfile. Wait for file to close before proceeding.
Remove-Item $logFile # Delete $logfile.
}

I'd colour it all for easier reading.. but that's way too much and I have work to do.

 

Long-Story short, give it a PC name and some info about what you want to do (email and details of vandalism), ping machine, if it responds, get maxevents value (manual input or, if screen, automatic), get-winevent, e-mail (and cc to me) or display as text document... But I can't help but look at it and think it's rather kludgy.. It could likely be much more streamlined, but after combing through it and reducing where I can, I'm not sure what other modifications would help.

 

Would anybody be able to nudge me in the direction of another avenue to explore?

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...