Link to home
Start Free TrialLog in
Avatar of kishoresr
kishoresr

asked on

Having Problems Executing Command Using Shell Function

Hi,
I am trying to Execute a Command from VB using Shell Function.

Its like
'Sorts the data in the file.
FName = "D:\Rpsort102\Rpsort.com /+1:11 /D H:\X.txt H:\X_sort.txt"

Shell(FName,3)

This Code works if I create Project with only this piece of code .


But When i use the same code in my project is doesn't work.

I have tried using ShellExecute, ShellExecuteEx,ShellExecuteInfo API but none of them run a Command from VB(In the Sense they don't Execute commands)

Please suggest me a way to solve my problem.


Thanks,
Sriram
Avatar of jjmartin
jjmartin

Can you show us the section of code in your project where this fails?  If this works in a stand alone project, and not in another, it stands to reason that it's not this piece of code that isn't working, but something else within your project.
Avatar of Guy Hengel [angelIII / a3]
FYI, if you will not realize what the problem is, then you may try to use the WshIShell.Run or .Execute(References:Windows Scripting Host)
command
If you are accessing the sorted file after the call to shell, you need to wait for the shelled app to finish before continuing your code.

"Q129796 - HOWTO: 32-Bit App Can Determine When a Shelled Process Ends"
http://support.microsoft.com/support/kb/articles/Q129/7/96.asp

And:
"Q161303 - HOWTO: Close a Shelled Process When Finished Under Windows"
http://support.microsoft.com/support/kb/articles/Q161/3/03.ASP
Avatar of kishoresr

ASKER

Let me explain what is happening.
When I use a Stand Alone Project with only this piece of code.
~~~~~~~~~~~~~
Private sub cmdSort_Click()
Shell(FName,3)
End sub
~~~~~~~~~~~~
Opens the MS-Dos window and stays there till the command is executed.
Since I can't control the Shell command once it is invoked ..the command Executes even after the project is closed.

But in my second case when I use the same code..it opens the MS-DOS window and Quickly closes the MS-Dos window(Starts and Ends Immediately)..I am not able to figure it out what is causing it...

My main problem is I need to run this Command from VB.
The sort file is a ".com" file.
Please let me know any other way to do this thing.

Thanks
Try calling:

h = Shell(Environ("COMSPEC") & " " & fName, 3)

Or try redirecting the output to read the error messages:

h = Shell(fName & " >c:\redir.log", 3)  
What you need is a Shell and Wait. The VB Shell command when you execute it, runs the program and then immediately continues along its way.. A Shell and Wait will execute the other program.. and then stop and wait until it is done.. <smile>.

As AngelIII comments, there is a Shell and Wait Function in the Windows Scripting Host.. to use it.. add a reference to your project (VB Menu.. Project.. References) and click on the Windows Scripting Runtime (SCRRUN.DLL). Having done that.. add the following code..

<----- Code Begin ----->

Option Explicit

Private Const SW_HIDE = 0
Private Const SW_SHOWNORMAL = 1
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_SHOWNOACTIVE = 4
Private Const SW_SHOW = 5
Private Const SW_MINIMIZE = 6
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_RESTORE = 9

Private Sub Form_Load()

    Dim strCommand as String
    strCommand = "c:\Windows\Calc.Exe"

    MsgBox ("About to run " & strCommand)

    Call xShellAndWait (strCommand, True)  
    MsgBox (strCommand & " COMPLETED!!!")

End Sub


Private Sub xShellAndWait _
(Byval strCommand as String, _
ByVal booWaitToComplete as Boolean)

    Dim oShl As New IWshShell_Class
    Call oShl.Run(strCommand, SW_SHOWNORMAL, booWaitToComplete)
   
End Sub

ASKER CERTIFIED SOLUTION
Avatar of Argonaut
Argonaut

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Argonaut Writes: "Shell is not a very reliable method of launching another program."

HUH?.. Argonaut, which version of VB are you using.. the dart board set?.. PLEASE DOCUMENT YOUR STATEMENT.. <sheesh>.

Frankly.. the ANSWER(?) you provide only does exactly what the questioner is doing.. it launchs the external program.. and then goes merrily upon its way. As I interpret the question, the questioner needs to Shell to the program and then WAIT for it to complete.. before processing continues. With that in mind, you should have added a WaitForObject API to your example.

Argonaut.. As you are obviously new here, I won't blast you for locking down this question. Unless your answewr is absolutely the best and only approach.. please hit the comment button rather than the answer.. give the questioner the benefit of other experts opinions too.. and let the questioner choose which answer best satisfies his/her means.. <smile>.
Ditto.
The link I provided earlier
"Q129796 - HOWTO: 32-Bit App Can Determine When a Shelled Process Ends"
http://support.microsoft.com/support/kb/articles/Q129/7/96.asp 
uses CreateProcess.
Agree with wsh2, only put it as an answer if you are 99+ % sure it is the complete answer. (LOL agreeing with wsh2 ;) ) Eric did provide a correct answer with his link.
Hi All,
Thanks a lot for your suggestions one more quick question.
I was reading the Suggestion by Erick37
~~~~~~
"Q129796 - HOWTO: 32-Bit App Can Determine When a Shelled Process Ends"
http://support.microsoft.com/support/kb/articles/Q129/7/96.asp 

~~~~~~
This works ...and has all the things (APIs) but this Invokes the application and the MS-DOS window comes up.
Is there any way to hide the DOS-window.
I saw the Parameters  and couldn't find any thing which hides the application.

Please let me know you valuable suggestions.

Thanks,
In the declare add in :

Private Const SW_SHOWMINIMIZED = 2
Private Const STARTF_USESHOWWINDOW = &H1

Then right after start.cb = Len(start)
add:

start.dwFlags = STARTF_USESHOWWINDOW
start.wShowWindow = SW_SHOWMINIMIZED
Hi All,
Hes suggestion was Great ..I had to make only one change(i.e)
Private Const SW_SHOWMINIMIZED = 2 (0)which hides the DOS-window and it works..
I will try to implement it in the Orginal Project and see how it works..
Let you know..

Thanks
Hi Eric37 & Hes
I am still getting the same problem..it working on the test project and not working on the working project.
I am getting a return code of 51 which is a system error and the Desc for this
is
51
The remote computer is not available.  ERROR_REM_NOT_LIST
I am not connecting to any remote computer..I have no idea why it is giving me that error.

Please give me some Input.

Thanks
Try running another program other than rpsort on d:\ and see if the same problem exists.

This will narrow down the problem.

What version of Windows?
Hi,
I am running both my projects on Windows NT Service Pack 5.0
I tested my Application in another PC's it works fine .
I don't know its making me Frustrate.
I works on other PC's not on mine.
it works on Test Project of mine but Not the Working project.

Please suggest something.
This is horrible.

Thanks,
If you don't want to use APIs to Shell and Wait.. see my comment above.. (paid for by the Campaign to reerect the looney-bin resident)

As to the Dos Window problem.. place your program in a BAT file.. and pass the parameters you need for the program to it. Using Windows Explorer.. change the BAT file properties to display however you like.. <smile>
Use the example I suggested above then in a while loop call the GetObject api to see when your App is finished.

While GetObject(YourApp.hWnd) <> 0
   DoEvents
Loop
Argonaut:
Your solution will still leave the application open for processing. IF the program requires the completion of this Shell to continue, the last comment you proferred may not be the best solution. Keeping in line with your viable solution, you may want to add a comment about using a WaitForSingleObject API to make the VB program pause until his DOS program is finished.. <smile>.


Public Sub ExecuteAndWait(cmdline As String)
    Dim NameOfProc As PROCESS_INFORMATION
    Dim NameStart As STARTUPINFO
    Dim X As Long
    NameStart.cb = Len(NameStart)
    X = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, NameStart, NameOfProc)
    X = WaitForSingleObject(NameOfProc.hProcess, INFINITE)
    X = CloseHandle(NameOfProc.hProcess)
End Sub

Hi All,
I am back..my Shell thing..I finally figured out what my problem is..as I mentioned to you I am getting a Exit Code 51(Which means that Remote Computer Not Found)..I know what's causing that but don't know Why and How to fix it..
here are the Steps I am doing in this method..
I wrote a method which reads a text file from a CD .
Then splits the Text file into two ".txt" files.
Once it splits into two files I take one of the files and with the Help of Shell Command I Execute a command to sort my file.
I already have ".txt file " to be sorted
But if I directly execute my command without reading from the CD-Rom using (Common dialog Control) it works fine but if I use the Common Dialog Control..Intialise the Dir,Filter and Open it ..it fails...

Please give me your input on this.
Is there any limitations to Common dialog..what is the connection between Common Dialog and Shell.
~~~~~~~~
Code
~~~~~~~~
'Initiates the Directory and the Drive
    cDialog.InitDir = CDFileDir
   'Allows to View only the text files
    cDialog.Filter = "Text Files(*.txt)"
   'Opens the Dialog Box
    cDialog.ShowOpen
    ~~~~Failing right here..I mean if I comment it out it works fine
    '
    'Calls the Procedure to wait for 5 Min
      LngPTime = 30
    '
      Call Wait(LngPTime)
'
   '
   'strGFileName = cDialog.FileName
   'Checks for the FileName selected
   'BolFileName = CheckFile(strGFileName)
   '
   'If BolFileName Then
           '
           '
           BolSplitFile = True
           'Calls the Process to do the split the file into Patient and NDC
           'BolSplitFile = DataLoad.Load(strGFileName)
           '
           If BolSplitFile Then
               'Set the Value for the BolSplit file
                BolSplitFile = False
               'Calls the Procedure to Sort the NDC File
               'Dblret = ExecCmd(RPSortDir)
               Dblret = ExecCmd(RPSortDir)
               '
              MsgBox "Process Finished, Exit Code " & Dblret