(view source code of which.vbs as plain text)
Option ExplicitDim arrFound, arrInt, arrPath, arrPathExt, arrTempDim blnAll, blnClipboard, blnExtOnly, blnHasExt, blnQuiet, blnShort, blnVerDim i, intArgs, jDim objFile, objFSO, objIE, wshShellDim strComSpec, strExt, strIntAll, strIntCmd, strIntCom, strPath, strPathExt, strResult, strTime, strVer' Initialize variablesintArgs = 0
strResult = ""
With WScript.Arguments
' Check the command line for exactly 1 argument (the file ' name), which should NOT contain wildcard charactersIf .Unnamed.Count <> 1 Then Syntax
If InStr( .Unnamed(0), "*" ) Then Syntax
If InStr( .Unnamed(0), "?" ) Then Syntax
' Check the command line switchesIf .Named.Exists( "A" ) Then
blnAll = True
intArgs = intArgs + 1
ElseblnAll = False
End If
If .Named.Exists( "C" ) Then
blnClipboard = True
intArgs = intArgs + 1
ElseblnClipboard = False
End If
If .Named.Exists( "Q" ) Then
' /Q can only be used with /CIf blnClipboard Then
blnQuiet = True
intArgs = intArgs + 1
ElseSyntax
End If
ElseblnQuiet = False
End If
If .Named.Exists( "S" ) Then
blnShort = True
intArgs = intArgs + 1
ElseblnShort = False
End If
If .Named.Exists( "V" ) Then
blnVer = True
intArgs = intArgs + 1
ElseblnVer = False
End If
If .Named.Exists( "X" ) Then
blnExtOnly = True
intArgs = intArgs + 1
ElseblnExtOnly = False
End If
' Check for remaining invalid command line switchesIf intArgs <> .Named.Count Then Syntax
End With
' Create the required objectsSet objFSO = CreateObject( "Scripting.FileSystemObject" )
Set wshShell = CreateObject( "Wscript.Shell" )
' Define internal command listsstrIntAll = "BREAK CALL CD CHCP CHDIR CLS COPY DATE DEL DIR ECHO ERASE " _
& "EXIT FOR GOTO IF MD MKDIR MOVE PATH PAUSE PROMPT RD REM " _
& "REN RENAME RMDIR SET SHIFT TIME TYPE VER VERIFY VOL "
strIntCmd = "ASSOC COLOR ENDLOCAL FTYPE POPD PUSHD SETLOCAL START TITLE"
strIntCom = "CTTY LFNFOR LH LOADHIGH LOCK TRUENAME UNLOCK"
' Determine the type of command processor' used: COMMAND.COM or CMD.EXEstrComSpec = UCase( wshShell.ExpandEnvironmentStrings( "%COMSPEC%" ) )
If Right( strComSpec, 12 ) = "\COMMAND.COM" Then
arrInt = Split( strIntAll & strIntCom )
End If
If Right( strComSpec, 8 ) = "\CMD.EXE" Then
arrInt = Split( strIntAll & strIntCmd )
End If
' Read the PATH and PATHEXT variables, and store their values in' arrays; the current directory is prepended to the PATH firststrPath = wshShell.CurrentDirectory & ";" _
& wshShell.ExpandEnvironmentStrings( "%PATH%" )
strPathExt = wshShell.ExpandEnvironmentStrings( "%PATHEXT%" )
arrPath = Split( strPath, ";" )
arrPathExt = Split( strPathExt, ";" )
' Check if the command line argument contains a dot' which would mean we wouldn't have to use PATHEXTblnHasExt = CBool( InStr( WScript.Arguments.Unnamed(0), "." ) > 0 )
If blnHasExt Then
' If an extension WAS specified, just search the PATHstrExt = Mid( WScript.Arguments.Unnamed(0), InStrRev( WScript.Arguments.Unnamed(0), "." ) )
arrPathExt = Array( strExt )
strResult = FindWhich( WScript.Arguments.Unnamed(0) )
ElseIf IsArray( arrInt ) And Not blnExtOnly Then
' Let's check for INTERNAL commands first, unless of course, the /X switch was usedFor i = 0 To UBound( arrInt )
If UCase( WScript.Arguments.Unnamed(0) ) = arrInt(i) Then
strResult = "[" & wshShell.ExpandEnvironmentStrings( "%COMSPEC%" ) & "]::" & arrInt(i)
Exit For
End If
NextEnd If
If strResult = "" Then
strResult = FindWhich( WScript.Arguments.Unnamed(0) )
End If
End If
' Copy the result to clipboard if the /C command line switch was usedIf blnClipboard Then
Set objIE = CreateObject( "InternetExplorer.Application" )
objIE.Navigate( "about:blank" )
objIE.Document.ParentWindow.ClipboardData.SetData "text", strResult
objIE.Quit
Set objIE = Nothing
End If
' Display the result, unless the /Q command line switch was usedIf Not blnQuiet Then
WScript.Echo strResult
End If
' Return code 1 if not foundWScript.Quit -( strResult = "" )
Function FindWhich( myFile )
' This function searches the directories in the PATH array for the ' specified file name, adding extensions from PATHEXT if required Dim i, j, objFound, strFound, strFullPath, strTestPathstrFound = ""
For i = 0 To UBound( arrPath )
' Skip empty directory values, caused by the PATH ' variable being terminated with a semicolonIf Trim( arrPath(i) ) <> "" Then
' Iterate through the array with extensions (if an extension was specified, ' the array will only contain the specified extension, otherwise it will ' contain all extensions in PATHEXT)For j = 0 To UBound( arrPathExt )
' Build a fully qualified path of the file to test forstrTestPath = objFSO.BuildPath( arrPath(i), objFSO.GetBaseName( myFile ) & arrPathExt(j) )
' Check if that file existsIf objFSO.FileExists( strTestPath ) Then
Set objFound = objFSO.GetFile( strTestPath )
If blnVer Then
strVer = objFSO.GetFileVersion( strTestPath )
If strVer = "" Then
strVer = objFound.DateLastModified
End If
End If
If blnShort Then
' Get the capitalization rightstrTestPath = objFSO.GetAbsolutePathName( strTestPath )
' Return the short full pathstrFullPath = objFound.ShortPath
Else ' Return the full path with proper capitalizationstrFullPath = objFSO.GetAbsolutePathName( strTestPath )
End If
If blnAll Then
' Append the path of the file foundstrFound = strFound & strFullPath
If blnVer Then strFound = strFound & vbTab & strVer
strFound = strFound & ";"
Else ' Abort when the first file is found strFound = strFullPathIf blnVer Then strFound = strFound & vbTab & strVer
Exit For
End If
Set objFound = Nothing
' Unless the /A (All) command line switch was used, abort inner loop after the first file is foundIf strFound <> "" And Not blnAll Then Exit For
End If
NextEnd If
' Unless the /A (All) command line switch was used, abort outer loop after the first file is foundIf strFound <> "" And Not blnAll Then Exit For
NextIf strFound <> "" Then
arrFound = Split( strFound, ";" )
strFound = Join( arrFound, vbCrLf )
End If
FindWhich = strFoundEnd Function
Sub Syntax( )
Dim strMsg strMsg = vbCrLf _& "Which.vbs, Version 1.20" & vbCrLf _
& "Find out which file or internal command is actually executed when you type" _
& vbCrLf _& "a command without its fully qualified path (like UNIX command, but extended)" _
& vbCrLf & vbCrLf _
& "Usage: WHICH.VBS filename[.ext] [ /A ] [ /C [ /Q ] ] [/S] [/V] [/X]" _
& vbCrLf & vbCrLf _
& "Where: filename[.ext] file name (with optional extension) or internal command" _
& vbCrLf _& " to search for; wildcards (""*"" and ""?"") are not allowed;" _
& vbCrLf _& " use the extension to search for .dll, .ocx, .ps1, etc." _
& vbCrLf _& " /A list All matches, not just the first match" _
& vbCrLf _& " /C copy result to the Clipboard" _
& vbCrLf _& " /Q Quiet mode, no screen output (only valid with /C)" _
& vbCrLf _& " /S return Short path(s) (8.3 notation)" _
& vbCrLf _& " /V show Version number" _
& vbCrLf _& " /X eXternal commands only, ignore internal commands" _
& vbCrLf & vbCrLf _
& "Notes: /A and /V switches will be ignored for internal commands" _
& vbCrLf _& " /V will display file timestamp for non-executables" _
& vbCrLf & vbCrLf _
& "Written by Rob van der Woude" & vbCrLf _
& "http://www.robvanderwoude.com" & vbCrLf
WScript.Echo strMsg
WScript.Quit 1
End Sub
page last modified: 2025-10-11; loaded in 0.0077 seconds