Simulating Where.exe functionality using PowerShell


Yesterday, Laerte Junior(Blog|twitter) re-tweeted an interesting blog post by Microsoft MVP Jeffery Hicks (twitter) which shows how to quickly find the file you are looking for by using the cmdlet ‘Get-FileItem’. Here is a link to Jeff’s blog post: Where Is The File? Part 2: Using Get-FileItem. What Jeff has written is much better than ‘where.exe’, in my opinion. I would advise you to read his blog post before moving on.

The script below depends on Get-RemoteRegistryKeyProperty. In Windows PowerShell Cookbook (O’Reilly) by Lee Holmes, there is a script that provided a good way to read properties from a remote machine’s registry. The script is available in poshcode: Get-RemoteRegistryKeyProperty.

So, what we have in this blog post is a bare bones implementation of what ‘where.exe’ does. I had written this script couple of months ago as part of automating the SQL*Server pre-install validation process (this script will probably be blogged at a later date). The basic idea was to quickly check if certain executables where available in the path and try to check their versions.

Function Find-CommonExecutables
{
	<#
		.SYNOPSIS
			For use to find executables in current path.

		.DESCRIPTION
			The script takes a computername and searches all directories in the path to
			find if we can find the commonly used executables there.

		.PARAMETER ComputerName
			Name of the Computer for which we need to collect the information.

			Required                                         true
			Position                                         named
			Default value
			Accept pipeline input                            false
			Accept wildcard characters                       false

		.EXAMPLE
		This is how it works on a local machine.
		 PS C:\> Find-CommonExecutables
		 Executbale 'where.exe' not found in any path
		 Executable sc.exe found at path: C:\WINDOWS\system32
		 Executable dsquery.exe found at path: C:\WINDOWS\system32
		 Executable msiexec.exe found at path: C:\WINDOWS\system32

		 FileName                                ProductVersion                          FileVersion
		 --------                                --------------                          -----------
		 \\SqlChow-DI-234\C$\Perl\bin\perl.exe   Build 827 [291969]                      5,8,9,827
		 \\SqlChow-DI-234\C$\WINDOWS\system32... 4.5.6001.22159                          4.5.6001.22159 (vistasp1...

		.NOTES
			- We have no need to search recursively as the paths in enviroment should have the
				executable in the base path itself, we need not recurse.
	#>
	param(
		[ValidateNotNullOrEmpty()]
		[String]
		$ComputerName = $env:COMPUTERNAME
	)
	$exeToBeChecked = @('where.exe','sc.exe','dsquery.exe', 'msiexec.exe')
	$regPath = 'HKLM:\System\CurrentControlSet\Control\Session manager\Environment'

	try
	{

		$pathVar = (Get-RemoteRegistryKeyProperty -ComputerName $ComputerName -Path $regPath -Property 'Path').Path
		$pathArry = $pathVar.Split(';')
		$fileVer = @()
		foreach($exe in $exeToBeChecked)
		{
			$foundExe = $false
            foreach($exPath in $pathArry)
            {

				#WMI way is a lot slower compared to Get-ChildItem
				#no need for recursive checking as the executable should be found in the base path.
				$pathToSearch = "\\"+$ComputerName+"\"+$($exPath.Replace(':','$'))
				Write-Debug "Searching in path $pathToSearch for $exe..."

				if((Get-ChildItem -Path $pathToSearch -Filter $exe -Force -ErrorAction SilentlyContinue))
				{
					$foundExe = $True;
					Write-Host "Executable $exe found at path: $exPath" -Fore Green
					#Write-Host "Checking version info for $exe" -Fore Yellow
					$fileVer += @((Get-ChildItem -Path $pathToSearch -Filter $exe -Force -ErrorAction SilentlyContinue).VersionInfo |
											Select-Object FileName,ProductVersion, FileVersion)
					break;
				}
            }

            if(-not $foundExe)
			{
				Write-Host "Executbale '$exe' not found in any path" -ForegroundColor Red
			}

		}

		$fileVer | Format-Table -AutoSize -Wrap
	}
	catch
	{
		Write-Host "$_"
	}
}

So, why did I blog about this? Because of the nature of PowerShell it is very easy to implement one thing in many different ways. It is the varsitality of the language that I wanted to show case. Nothing more, nothing else. Can this be implemented in a better way? Sure, there should be scope for imporvement as I am not a very skilled coder.

Kindly leave a comment if there is anyway I can improve it.

Advertisements
About

By profession, I’m a SQL Server Database Administrator. I love to poke my nose into different corners and see how stuff looks in there. I keep looking for new things to do as my mind refuses to settle on one topic.

Tagged with: ,
Posted in PowerShell

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: