Need to transfer VB6 shell functions to .NET

c_law
c_law used Ask the Experts™
on
Here are two proecdures I used in VB6 to shell out a command, and wait for it to be terminated. Note that DoEvents was used to free the cpu to other processes. I desperately need to port these to a web based ASP.NET solution, and am unable to work out how this could possibly work in an asmx page. Any help greatly appreciated.

If at all possible I need to have the process that is created interacting with the desktop. I have also had trouble getting new processes to do this.


Sub ExecCmd(ByVal vstrCommand As String, Optional ByVal vlngWindowStyle As VbAppWinStyle = vbMinimizedNoFocus) '=vbHide
WaitForTermination Shell(vstrCommand, vlngWindowStyle)
End Sub

Private Sub WaitForTermination(ByVal vlngProcessId As Long)
Dim pHnd As Long

pHnd = OpenProcess(SYNCHRONIZE, 0&, vlngProcessId)
If pHnd <> 0& Then
Do Until WaitForSingleObject(pHnd, 1&) = 0&
DoEvents
Loop
CloseHandle pHnd
End If
End Sub
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
Basically you want to fire a shell command in an ASP.net environment. Does the client need to wait for the result?

Author

Commented:
The client is essentialy a front end for a build machine.

The client starts a command line compiler on the server, which needs to wait for the compiler to finish before carrying out the next step.

Another reason I need to wait is that by construction of the command to be passed out I can trap the ERRORLEVEL  parameter (old DOS environment variable) and create an error log if it fails (all from the command prompt). If I don't wait for the new process to finish I can't tell if it has failed or not.

Commented:
Quote:
The client starts a command line compiler on the server, which needs to wait for the compiler to finish before carrying out the next step.

What compiler may that be? The .Net compiler or an old compiler? It's pretty important to know this because compiling .Net applications can also be done on a different and better way!

Also I do not recommend waiting for a commandline through the internet. Last week I read an article on MSDN about queued components (also through ASP.Net) you might want to read through it if you want to continue with waiting for the commandline to be finished (it contains no information to transform your current bit of code though).

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet10222002.asp
Announcing the Winners!

The results are in for the 15th Annual Expert Awards! Congratulations to the winners, and thank you to everyone who participated in the nominations. We are so grateful for the valuable contributions experts make on a daily basis. Click to read more about this year’s recipients!

Author

Commented:
I need to compile (currently) using C++6 and VB6 compilers.

At some point in the future our projects will migrate, but there will always be legacy that must be done this way. Also, I use ss.exe to get (and label) the code from VSS. If I had a better code repository I may be able to use an API, but VSS does not have one.

Essentially, I am (re)writing an SCM tool. It is for internal use only, and .NET is being used partially so I can learn it. Very occasionally I might want to do this from off-site, but this is not an essential requirement of the project.

The client will ultimately have several web methods it calls, and will need to wait for one server process to finish before it does the next one (for example, one method to get the VSS code, one to compile the VB and C++ binaries, and one to compile the InstallShield project - these all require external processes to happen on the server, and all are dependant on the previous process finishing and returning a success flag).

I've just read the article you linked to, and I'm not sure if it would help in this particular situation. I could get the client to queue the request on the server, but as there will always be a 'next step' to perform from the client it would have to sit there and query the web service until it had found that the process had finished (so that it could proceed). Performance of the client is very unimportant here, I am looking for a simple solution, not to be able to scale this up or keep the client free.

I understand that this is not a typical implementation or a best practice one, and I appreciate any help you can give.

Commented:
I might have some time to look at the code changes. I understand that there is no other way for you to change the way of working... when I have time I'll see what I can do for you! Thank you for the additional explanation!

Author

Commented:
Thanks :)

Commented:
You can always left that code on vb6.  If you need to call that funcionality from a vb.net program, vb.net you can always use interops to call the vb6 subroutine.  It will run as unmanage code, but it will run.  I understand, (but can not give a code sample ) that you can always use interops to call WinApi that is the thing that you are doing.

Author

Commented:
DoEvents() is available in the system.windows.forms namespace, but this namespace is not accessable in an asmx page (according to the autocomplete). I have played with the System.Diagnostics.Process namespace, as well as the system.threading namespace, but am still unsure of their workings, and how they relate to my problem.

I don't understand how the web server would manage the new process, as the creation of it is within the web publisher service.

Shell() does work in .NET, (shell is an alias for system.tools.shell I think), and it returns a process ID, but how to wait for it to terminate without using up the cpu resources I'm not sure on...
It's different now...

Dim myProcess as New Process()
myProcess.StartInfo.FileName = "Notepad.exe"
' myProcess.StartInfo.UseShellExecute = True
' - use the shell when starting the process
' myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
' - hide window
myProcess.Start()
myProcess.WaitForExit()

 

Author

Commented:
I have tried this already, but does the WaitForExit method free up cpu cycles to other processes? i.e. Does this method do what DoEvents() used to do?

Also, even when WindowStyle is set to ProcessWindowStyle.Normal the new process is run with no UI. I must have a UI to monitor the progress for the process, and to shut down the process if it fails (a definite possibility in the coding stage, and a slight one in the released product).

At the moment, I can not kill the process in task manager if it fails (and can not tell if it is running or if it has failed and is waiting for user input), as I get an 'Access Denied' message. I believe that this process is running in the Web Publisher service, but allowing this sevice to interact with the desktop has not given me a UI. Also, adding administrator permissions to the IUSR and IWAM accounts (used by IIS) has had no impact. As a result, I get processes not terminating and I am unable to close tem, even manualy :(. I am getting frustrated with constant rebooting to free up memory...

Ultimately, I am no guru in .NET (I have only been playing with it for 2 weeks), and my disjointed understanding of the seperate components is frustrating as I have no overall understanding of what is going on. I'm sure what I am trying is easy if you know how - it's just that I don't!

Author

Commented:
I have extensively used the Process class to try and get my external processes running. Here is the code I have been using:

p.StartInfo.FileName = "cmd.exe"
p.StartInfo.Arguments = "/c """"" & sBatchFile & """"""
p.StartInfo.UseShellExecute = True
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal
p.StartInfo.CreateNoWindow = False
p.Start()
p.WaitForExit()

If sBatchFile contains the line:
echo hello > D:\Output.txt
It correctly creates a file called Output.txt with word 'hello' written in it, although there is no UI for the process.

If I try anything more complex such as:

"C:\Program Files\Microsoft Visual Studio\Common\VSS\win32\SS.exe" Get "*.*" -NL -GL"D:\SRC" -I-Y -R   -Y"Autobuild,AutobuildPwd" >> d:\batch\output.log > "D:\Output.txt"

It runs the file, but the command does not execute. The above command is a VSS GET command, and should recursively get the current project from visual sourcesafe to D:\SRC.

The batch file runs correctly when run independantly, but nothing happens at all when run from the web service. The
> "D:\Output.txt"
bit at the end of the line should redirect all output to the Output.txt file. This file is empty.

If I could only get a UI for the process I could see what was happening. I really need to do this or my whole project is dust :(

Author

Commented:
I read somewhere that it may have been a permissions problem stopping the UI, and I have now tried the following:

1 - setting the IIS ananymous user (one I have already created) to have Admin rights.
2 - setting the IUSR and IWAM users to have admin rights
3 - modifying machine.config USER attribute to be 'SYSTEM' instead of 'machine'
4 - playing with dcom general application launch and access settings (included 'everyone')

All of these things have yeilded no change to problem. Doing (3) now causes 'Access Denied' message when I try to end the process.

So, still can't see what is going on in the external process, and still can't get it to do anything useful...

Author

Commented:
Should I reopen this as another question and give the points for this to someone here?

Sorry for the newbie questions...
you should check permissions for ASPNET account and try don't use double " in the line
p.StartInfo.Arguments = "/c " & sBatchFile
or create cmd-file that contains all commands you want and run it

Author

Commented:
Please explain what 'permissions for ASPNET' are, as I do not understand. Note that in a comment above I specify what changes I have made to OS users and to the WWWPublisher service, all to no avail.

I will try removing some quotes, but you must have at least one set of quotes around the batch file name in case it has spaces in it. The format for this line was taken from my VB6 projet that used Shell(), maybe I can just pass the name of the file itself now as the new process class will run the .cmd file without the need for explicitly calling cmd.exe. I am not convinced however that this should be the issue as with a simple dos cammand (echo) the cmd file was executing.

Thanks for your help.

Author

Commented:
I have just tried several tests with the following batch file:
echo start > d:\output.log
"C:\Program Files\Microsoft Visual Studio\Common\VSS\win32\SS.exe" CP "$/SRC/Libs" -Y"User,Pwd" >> d:\output.log
echo finish  >> d:\output.log

When run from explorer or a command prompt, the output file looks like this:
   start
   Current project is $/SRC/Libs
   finish  

When I run this file directly using the process class
(p.StartInfo.Filename = "mybatch.cmd"), or indirectly (see comment above - uses cmd.exe as filename, batch file as parameter), or even with one less set of double quotes in the arguments (as per your suggestion above) then the output file looks like this:
   start
   finish
i.e. there is processing of the commands both before and after the ss.exe command, yet there is no output whatsoever from the ss.exe command itself. This is very confusing behaviour, and I can't begin to explain why it is happening.

I get the feeling that if I manage to sort out the permissions problem (whatever that is), then this would be alot easier (as I could see the UI).

Thanks again,

dan
Try log error output too
"C:\Program Files\Microsoft Visual Studio\Common\VSS\win32\SS.exe" CP "$/SRC/Libs" -Y"User,Pwd" 1>>d:\output.log 2>d:\error.log

About permission: user ASPNET must be able to run SS.exe application.

Author

Commented:
quote:
Try log error output too
"C:\Program Files\Microsoft Visual Studio\Common\VSS\win32\SS.exe" CP "$/SRC/Libs" -Y"User,Pwd" 1>>d:\output.log 2>d:\error.log

Please explain what you mean, I don't understand.

quote:
About permission: user ASPNET must be able to run SS.exe application.

I have given the ASPNET user admin rights (just to get this thing working), but no UI. Then tried adding ASPNET user directly to SS.exe permissions tab, still no UI.

To simplify things, I am now using calc.exe to run as a process, and have given rights to calc.exe for ASPNET user. Still no UI. :(

Could there be some setting in the IIS config I have missed?
Commented:
Success!!

I was playing around with every setting I could think of, in IIS, the OS user accounts, and anything else I could think of. I don't know why I tried it, but I set the IIS Admin Service to interact with the desktop. I had already set the WWWPub Service to interact with desktop. This fixed the problem!

Now I suppose the million dollar question is [I]why on earth should this setting stop a process controlled by a web service from interacting with the desktop?[/I]

I can't help but think that this implies that the IIS Admin Service is the one that 'owns' the external process I am running, but this is not in accordance with what others have told me (that it is the WWWPub service that owns it), and it does not match with the description of that service:
'Allows administration of Web and FTP services through the Internet Information Services snap-in.'
Running an external process is not exactly an admin function is it?

I wonder if there will be similar issues when I come to publish this website?

Anyway, big thanks for everyones help. I was on the verge of smashing my machine in to small pieces...
Most Valuable Expert 2012
Top Expert 2008

Commented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered by Yury_Delendik

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

TheLearnedOne
EE Cleanup Volunteer

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial