Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for which.vbs

(view source code of which.vbs as plain text)

  1. Option Explicit
  2.  
  3. Dim arrFound, arrInt, arrPath, arrPathExt, arrTemp
  4. Dim blnAll, blnClipboard, blnExtOnly, blnHasExt, blnQuiet, blnShort, blnVer
  5. Dim i, intArgs, j
  6. Dim objFile, objFSO, objIE, wshShell
  7. Dim strComSpec, strExt, strIntAll, strIntCmd, strIntCom, strPath, strPathExt, strResult, strTime, strVer
  8.  
  9. ' Initialize variables
  10. intArgs   = 0
  11. strResult = ""
  12.  
  13. With WScript.Arguments
  14. 	' Check the command line for exactly 1 argument (the file
  15. 	' name), which should NOT contain wildcard characters
  16. 	If .Unnamed.Count   <>   1   Then Syntax
  17. 	If InStr( .Unnamed(0), "*" ) Then Syntax
  18. 	If InStr( .Unnamed(0), "?" ) Then Syntax
  19. 	' Check the command line switches
  20. 	If .Named.Exists( "A" ) Then
  21. 		blnAll  = True
  22. 		intArgs = intArgs + 1
  23. 	Else
  24. 		blnAll  = False
  25. 	End If
  26. 	If .Named.Exists( "C" ) Then
  27. 		blnClipboard = True
  28. 		intArgs      = intArgs + 1
  29. 	Else
  30. 		blnClipboard = False
  31. 	End If
  32. 	If .Named.Exists( "Q" ) Then
  33. 		' /Q can only be used with /C
  34. 		If blnClipboard Then
  35. 			blnQuiet = True
  36. 			intArgs  = intArgs + 1
  37. 		Else
  38. 			Syntax
  39. 		End If
  40. 	Else
  41. 		blnQuiet = False
  42. 	End If
  43. 	If .Named.Exists( "S" ) Then
  44. 		blnShort = True
  45. 		intArgs  = intArgs + 1
  46. 	Else
  47. 		blnShort = False
  48. 	End If
  49. 	If .Named.Exists( "V" ) Then
  50. 		blnVer  = True
  51. 		intArgs = intArgs + 1
  52. 	Else
  53. 		blnVer  = False
  54. 	End If
  55. 	If .Named.Exists( "X" ) Then
  56. 		blnExtOnly = True
  57. 		intArgs    = intArgs + 1
  58. 	Else
  59. 		blnExtOnly = False
  60. 	End If
  61. 	' Check for remaining invalid command line switches
  62. 	If intArgs <> .Named.Count Then Syntax
  63. End With
  64.  
  65. ' Create the required objects
  66. Set objFSO   = CreateObject( "Scripting.FileSystemObject" )
  67. Set wshShell = CreateObject( "Wscript.Shell" )
  68.  
  69. ' Define internal command lists
  70. strIntAll = "BREAK CALL CD CHCP CHDIR CLS COPY DATE DEL DIR ECHO ERASE " _
  71.           & "EXIT FOR GOTO IF MD MKDIR MOVE PATH PAUSE PROMPT RD REM " _
  72.           & "REN RENAME RMDIR SET SHIFT TIME TYPE VER VERIFY VOL "
  73. strIntCmd = "ASSOC COLOR ENDLOCAL FTYPE POPD PUSHD SETLOCAL START TITLE"
  74. strIntCom = "CTTY LFNFOR LH LOADHIGH LOCK TRUENAME UNLOCK"
  75.  
  76. ' Determine the type of command processor
  77. ' used: COMMAND.COM or CMD.EXE
  78. strComSpec = UCase( wshShell.ExpandEnvironmentStrings( "%COMSPEC%" ) )
  79. If Right( strComSpec, 12 ) = "\COMMAND.COM" Then
  80. 	arrInt = Split( strIntAll & strIntCom )
  81. End If
  82. If Right( strComSpec, 8 ) = "\CMD.EXE" Then
  83. 	arrInt = Split( strIntAll & strIntCmd )
  84. End If
  85.  
  86. ' Read the PATH and PATHEXT variables, and store their values in
  87. ' arrays; the current directory is prepended to the PATH first
  88. strPath    = wshShell.CurrentDirectory & ";" _
  89.            & wshShell.ExpandEnvironmentStrings( "%PATH%" )
  90. strPathExt = wshShell.ExpandEnvironmentStrings( "%PATHEXT%" )
  91. arrPath    = Split( strPath, ";" )
  92. arrPathExt = Split( strPathExt, ";" )
  93.  
  94. ' Check if the command line argument contains a dot
  95. ' which would mean we wouldn't have to use PATHEXT
  96. blnHasExt = CBool( InStr( WScript.Arguments.Unnamed(0), "." ) > 0 )
  97.  
  98. If blnHasExt Then
  99. 	' If an extension WAS specified, just search the PATH
  100. 	strExt     = Mid( WScript.Arguments.Unnamed(0), InStrRev( WScript.Arguments.Unnamed(0), "." ) )
  101. 	arrPathExt = Array( strExt )
  102. 	strResult  = FindWhich( WScript.Arguments.Unnamed(0) )
  103. Else
  104. 	If IsArray( arrInt ) And Not blnExtOnly Then
  105. 		' Let's check for INTERNAL commands first, unless of course, the /X switch was used
  106. 		For i = 0 To UBound( arrInt )
  107. 			If UCase( WScript.Arguments.Unnamed(0) ) = arrInt(i) Then
  108. 				strResult = "[" & wshShell.ExpandEnvironmentStrings( "%COMSPEC%" ) & "]::" & arrInt(i)
  109. 				Exit For
  110. 			End If
  111. 		Next
  112. 	End If
  113. 	If strResult = "" Then
  114. 		strResult = FindWhich( WScript.Arguments.Unnamed(0) )
  115. 	End If
  116. End If
  117.  
  118. ' Copy the result to clipboard if the /C command line switch was used
  119. If blnClipboard Then
  120. 	Set objIE = CreateObject( "InternetExplorer.Application" )
  121. 	objIE.Navigate( "about:blank" )
  122. 	objIE.Document.ParentWindow.ClipboardData.SetData "text", strResult
  123. 	objIE.Quit
  124. 	Set objIE = Nothing
  125. End If
  126.  
  127. ' Display the result, unless the /Q command line switch was used
  128. If Not blnQuiet Then
  129. 	WScript.Echo strResult
  130. End If
  131.  
  132. ' Return code 1 if not found
  133. WScript.Quit -( strResult = "" )
  134.  
  135.  
  136. Function FindWhich( myFile )
  137. 	' This function searches the directories in the PATH array for the
  138. 	' specified file name, adding extensions from PATHEXT if required
  139. 	Dim i, j, objFound, strFound, strFullPath, strTestPath
  140. 	strFound = ""
  141. 	For i = 0 To UBound( arrPath )
  142. 		' Skip empty directory values, caused by the PATH
  143. 		' variable being terminated with a semicolon
  144. 		If Trim( arrPath(i) ) <> "" Then
  145. 			' Iterate through the array with extensions (if an extension was specified,
  146. 			' the array will only contain the specified extension, otherwise it will
  147. 			' contain all extensions in PATHEXT)
  148. 			For j = 0 To UBound( arrPathExt )
  149. 				' Build a fully qualified path of the file to test for
  150. 				strTestPath = objFSO.BuildPath( arrPath(i), objFSO.GetBaseName( myFile ) & arrPathExt(j) )
  151. 				' Check if that file exists
  152. 				If objFSO.FileExists( strTestPath ) Then
  153. 					Set objFound = objFSO.GetFile( strTestPath )
  154. 					If blnVer Then
  155. 						strVer = objFSO.GetFileVersion( strTestPath )
  156. 						If strVer = "" Then
  157. 							strVer = objFound.DateLastModified
  158. 						End If
  159. 					End If
  160. 					If blnShort Then
  161. 						' Get the capitalization right
  162. 						strTestPath  = objFSO.GetAbsolutePathName( strTestPath )
  163. 						' Return the short full path
  164. 						strFullPath  = objFound.ShortPath
  165. 					Else
  166. 						' Return the full path with proper capitalization
  167. 						strFullPath = objFSO.GetAbsolutePathName( strTestPath )
  168. 					End If
  169. 					If blnAll Then
  170. 						' Append the path of the file found
  171. 						strFound = strFound & strFullPath
  172. 						If blnVer Then strFound = strFound & vbTab & strVer
  173. 						strFound = strFound & ";"
  174. 					Else
  175. 						' Abort when the first file is found
  176. 						strFound = strFullPath
  177. 						If blnVer Then strFound = strFound & vbTab & strVer
  178. 						Exit For
  179. 					End If
  180. 					Set objFound = Nothing
  181. 					' Unless the /A (All) command line switch was used, abort inner loop after the first file is found
  182. 					If strFound <> "" And Not blnAll Then Exit For
  183. 				End If
  184. 			Next
  185. 		End If
  186. 		' Unless the /A (All) command line switch was used, abort outer loop after the first file is found
  187. 		If strFound <> "" And Not blnAll Then Exit For
  188. 	Next
  189. 	If strFound <> "" Then
  190. 		arrFound = Split( strFound, ";" )
  191. 		strFound = Join( arrFound, vbCrLf )
  192. 	End If
  193. 	FindWhich = strFound
  194. End Function
  195.  
  196.  
  197. Sub Syntax( )
  198. 	Dim strMsg
  199. 	strMsg = vbCrLf _
  200. 	       & "Which.vbs,  Version 1.20" & vbCrLf _
  201. 	       & "Find out which file or internal command is actually executed when you type" _
  202. 	       & vbCrLf _
  203. 	       & "a command without its fully qualified path (like UNIX command, but extended)" _
  204. 	       & vbCrLf & vbCrLf _
  205. 	       & "Usage:  WHICH.VBS  filename[.ext]  [ /A ]  [ /C [ /Q ] ]  [/S]  [/V]  [/X]" _
  206. 	       & vbCrLf & vbCrLf _
  207. 	       & "Where:  filename[.ext]  file name (with optional extension) or internal command" _
  208. 	       & vbCrLf _
  209. 	       & "                        to search for; wildcards (""*"" and ""?"") are not allowed;" _
  210. 	       & vbCrLf _
  211. 	       & "                        use the extension to search for .dll, .ocx, .ps1, etc." _
  212. 	       & vbCrLf _
  213. 	       & "        /A              list All matches, not just the first match" _
  214. 	       & vbCrLf _
  215. 	       & "        /C              copy result to the Clipboard" _
  216. 	       & vbCrLf _
  217. 	       & "        /Q              Quiet mode, no screen output (only valid with /C)" _
  218. 	       & vbCrLf _
  219. 	       & "        /S              return Short path(s) (8.3 notation)" _
  220. 	       & vbCrLf _
  221. 	       & "        /V              show Version number" _
  222. 	       & vbCrLf _
  223. 	       & "        /X              eXternal commands only, ignore internal commands" _
  224. 	       & vbCrLf & vbCrLf _
  225. 	       & "Notes:  /A and /V switches will be ignored for internal commands" _
  226. 	       & vbCrLf _
  227. 	       & "        /V will display file timestamp for non-executables" _
  228. 	       & vbCrLf & vbCrLf _
  229. 	       & "Written by Rob van der Woude" & vbCrLf _
  230. 	       & "http://www.robvanderwoude.com" & vbCrLf
  231. 	WScript.Echo strMsg
  232. 	WScript.Quit 1
  233. End Sub
  234.  

page last modified: 2024-04-16; loaded in 0.0072 seconds