how would i launch a batch file from within visual basic?
the batch file is called kill.bat i have used the following code
but does not work. the bat file is stored in the root where the application would be launched from.Code:shell "/kill.bat"
Printable View
how would i launch a batch file from within visual basic?
the batch file is called kill.bat i have used the following code
but does not work. the bat file is stored in the root where the application would be launched from.Code:shell "/kill.bat"
Not tested - from the top of my head :)Code:Dim x As String
x = App.Path
If Right$(x, 1) <> "\" Then x = x & "\"
x = x & "kill.bat"
Shell x, vbNormalFocus
Wouldn't the following work fine?Quote:
Originally Posted by gavio
I don't disagree with your method, because it should work fine, but is all the code around necessary?Code:Shell App.Path & "\kill.bat"
I mean I've never used it that way ;)
@TheBigB: what if EXE is in drive root? "c:\"? Then you have:... which of course, fails. You must think ahead ;)Code:Shell "c:\\kill.bat"
My code is still not good enough. He should also check if "kill.bat" actually exists :)
Never thought of that :bigyello:Quote:
Originally Posted by gavio
Thanks for pointing that out.
an alternative to that problem would be to use ShellExecute and specify a working directory of the App.Path it wont matter the root path or not (note the double backslash just as a working example).Quote:
Originally Posted by gavio
Code:Option Explicit
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Private Const SW_HIDE As Long = 0
Private Const SW_SHOWNORMAL As Long = 1
Private Const SW_SHOWMAXIMIZED As Long = 3
Private Const SW_SHOWMINIMIZED As Long = 2
Private Sub Command1_Click()
ShellExecute Me.hwnd, "open", "\deleteme.txt", vbNullString, "C:\", SW_SHOWNORMAL
End Sub
I would rather recommend this code. Its much more simple and will do all that is required. And without APIs too.
Code:Dim path As String
path = App.Path
If Right(path,1) <> "\" Then path = path & "\"
path = path & "kill.bat"
If LCase(Dir(path)) <> "kill.bat" Then
'file does not exist
MsgBox "The required file does not exist"
Else
'file exists
Shell path
End If
No need to shy away from APIs as they are on your system from the OS anyways. Its just up to you to decide to call it or not and yes your code is good too. :).
This API is just as good too as it adds the backslash if needed.
PathAddBackslash
You flatter me saying my code is good, LOL.
I don't shy from APIs, its just that they always tend to loosen the programmer's grip over the way things work. They also add the factor of uncertainty to the program and the chances of getting a program crash rise (well for me at least, maybe others don't agree with me). Thats why I always try to do without them.
There is less chance of them failing but if they did it would be because of ones coded usage of them but with the non-api approach you are taking more chances and uncertanity as your code didnt go through the rigors of unit testing that MS put the APIs through.
I'm not bringing in anything really new with the following code, just bringing some stuff to think about:As for ShellExecute, you don't need to do checking beforehand, you can just go ahead and make the function call. However instead you can get an error message out of it as a return value: http://msdn.microsoft.com/en-us/library/bb762153.aspx - although it is of the weirder ones, the return value is an error if it is from 0 to 32, otherwise the return value means success. That is even weirder than most other API functions, where 0 can mean success and any other value is an error; but there are also API functions where 0 means error and you have to use GetLastError API to get the error number, because any other value is a wanted result. But there are also APIs where -1 (or &HFFFFFFFF) is the failing condition. And then we have these functions like ShellExecute that are truly unique with their return values...Code:Dim strPath As String
' use string and byte version of Right
If RightB$(App.Path, 2) <> "\" Then
strPath = App.Path & "\kill.bat"
Else
strPath = App.Path & "kill.bat"
End If
' another point: because we are finding out where a file (or folder) exists
' and Dir returns a null string if it was not found, we only need to check
' length of the returned string
If LenB(Dir$(strPath)) Then
Shell strPath
Else
MsgBox "The file """ & strPath & """ was not found!"
End If
My full example I usually post but I usually I try to keep it simple :)
Code:Option Explicit
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Const SW_SHOWNORMAL As Long = 1
Private Const SW_SHOWMINIMIZED As Long = 2
Private Const SW_SHOWMAXIMIZED As Long = 3
Private Const ERROR_FILE_NOT_FOUND As Long = 2&
Private Const ERROR_PATH_NOT_FOUND As Long = 3&
Private Const ERROR_BAD_FORMAT As Long = 11&
Private Const SE_ERR_ACCESSDENIED As Long = 5
Private Const SE_ERR_ASSOCINCOMPLETE As Long = 27
Private Const SE_ERR_DDEBUSY As Long = 30
Private Const SE_ERR_DDEFAIL As Long = 29
Private Const SE_ERR_DDETIMEOUT As Long = 28
Private Const SE_ERR_DLLNOTFOUND As Long = 32
Private Const SE_ERR_FNF As Long = 2
Private Const SE_ERR_NOASSOC As Long = 31
Private Const SE_ERR_OOM As Long = 8
Private Const SE_ERR_PNF As Long = 3
Private Const SE_ERR_SHARE As Long = 26
Private Sub Command1_Click()
On Error GoTo MyError
Dim lRet As Long
lRet = ShellExecute(Me.hwnd, "Open", "CMD.exe", " /C ipconfig.exe /all > C:\ip.txt", "C:\", SW_SHOWNORMAL)
If lRet <= 32 Then
Select Case lRet
Case 0
MsgBox "The operating system is out of memory or resources."
Case ERROR_FILE_NOT_FOUND
MsgBox "The specified file was not found."
Case ERROR_PATH_NOT_FOUND
MsgBox "The specified path was not found."
Case ERROR_BAD_FORMAT
MsgBox "The .EXE file is invalid (non-Win32 .EXE or error in .EXE image)."
Case SE_ERR_ACCESSDENIED
MsgBox "The operating system denied access to the specified file."
Case SE_ERR_ASSOCINCOMPLETE
MsgBox "The filename association is incomplete or invalid."
Case SE_ERR_DDEBUSY
MsgBox "The DDE transaction could not be completed because other DDE transactions were being processed."
Case SE_ERR_DDEFAIL
MsgBox "The DDE transaction failed."
Case SE_ERR_DDETIMEOUT
MsgBox "The DDE transaction could not be completed because the request timed out."
Case SE_ERR_DLLNOTFOUND
MsgBox "The specified dynamic-link library was not found."
Case SE_ERR_FNF
MsgBox "The specified file was not found."
Case SE_ERR_NOASSOC
MsgBox "There is no application associated with the given filename extension."
Case SE_ERR_OOM
MsgBox "There was not enough memory to complete the operation."
Case SE_ERR_PNF
MsgBox "The specified path was not found."
Case SE_ERR_SHARE
MsgBox "A sharing violation occurred."
End Select
End If
Exit Sub
MyError:
MsgBox Err.Number & " - " & Err.Description
End Sub
Nice :eek:
That's some fool-proof code over there :D
You're right in a way, but you have to face that ShellExecute provides more functionality than Shell. In addition, API calls speed up your code, because it's a direct link from the code, rather than a redirection from the VB runtime.Quote:
Originally Posted by lone_REBEL
Perhaps ShellExecute is better way nowadays as some systems may block Shell command.
This is a revived version of lone_REBEL's code in post#7, it also looks similar to Merri's code in post#11.
Code:Sub KillIt()
Dim sPath As String
sPath = Replace(App.Path & "\kill.bat", "\\", "\") '-- cheating an If (I am lazy)
If Len(Dir(sPath)) Then '-- the file exists
Shell sPath
Else
MsgBox "File Not Found: " & sPath
End If
End Sub
What if the application is ran on a network location :rolleyes:Quote:
Originally Posted by anhn
\\server\
You know how to fix it.:pQuote:
Originally Posted by TheBigB
You don't really need to clean up the \ character though:You can even put \\\\\\\\\\\\\\\\\\\\\ in and it still says the file exists...Code:Option Explicit
Private Sub Form_Load()
Dim strPath As String
strPath = "C:\Windows\\Win.ini"
If LenB(Dir$(strPath)) Then Debug.Print "File exists"
End Sub
Success! (Also showing how to make Unicode call since all the others prefer ANSI... using Dir$ spoils this one though)Code:Option Explicit
Private Declare Function ShellExecuteW Lib "shell32.dll" (ByVal hWnd As Long, ByVal lpOperation As Long, ByVal lpFile As Long, ByVal lpParameters As Long, ByVal lpDirectory As Long, ByVal nShowCmd As Long) As Long
Private Sub Form_Load()
Dim strPath As String
strPath = "C:\\\\\\\\\\\\\\\\\\Windows\\\\\\\\\\\\\\\\Win.ini"
If LenB(Dir$(strPath)) Then
If ShellExecuteW(Me.hWnd, StrPtr("Open"), StrPtr(strPath), 0, 0, 1) > 32 Then
Debug.Print "Success!"
End If
End If
End Sub
Good info, Merri. That's modern technology! :)Quote:
Originally Posted by Merri
The bat file may exist but if it cannot be run then the Shell() function will return 0. How about this:
(Don't hate "On Error Resume Next". It's a good statement if we use it properly.)Code:Sub RunBatFile(sBatFileName As String, Optional ByVal sPath As String)
Dim ID As Double
If sPath = "" Then sPath = App.Path
On Error Resume Next
ID = Shell(sPath & "\" & sBatFileName)
If ID = 0 Then MsgBox "Cannot run bat file: " & sBatFileName
End Sub