Unoffical empeg BBS

Quick Links: Empeg FAQ | RioCar.Org | Hijack | BigDisk Builder | jEmplode | emphatic
Repairs: Repairs

Topic Options
#365253 - 10/11/2015 00:48 Gracefully stopping IIS Express from within my C# program?
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Okay, rubbing the EmpegBBS lamp once again, as Google is running me in circles.

I have a test where my C# code is running a test version of the company web site under IIS Express. I have a requirement that I need to, on demand, gracefully stop the web site to end the test. By gracefully, I mean, it cannot be TaskKill'ed or else that would ruin the test. (Specifically, if the task is not exited gracefully with a 0 exit code, the code coverage tool doesn't collect code coverage for the site, and the code coverage is the thing that I want.)

The site is launched from the IIS express command line tool like this:

Code:
iisexpress.exe /trace:info /path:C:\development\code\sites\websitename /port:5150


This works, and, if I were lucky enough to be on the same machine that is running the test and could get to the console window, simply pressing the Q key would stop the web site gracefully and do exactly what I want.

Problems:

- The site, and the test that controls the site, is running on servers without an active login. So finding the console window, focusing it, and doing a window-based "SendKeys" to that window is not an option.

- I don't actually need a window and a login to do console I/O redirection. That's worked for me before in the past. But in this case, though I can easily launch the iisexpress process myself from my C# code and control its console I/O, it does not respond to the following command:
Code:
IisExpressProcess.StandardInput.Write("q");  // WriteLine also does not work


I've successfully done that same thing to other processes (to other console apps in the same test group in fact), and I'm doing all of the same steps to make that happen. Normally other console programs respond to that just fine. IISExpress is behaving differently. As if it's not using a standard way of getting its keyboard input from stdin. Maybe it's doing some sort of keyscan code polling or something. Not sure.

Okay, so then I look at other ways to stop the site gracefully. 99 percent of the search results say to taskkill the site. The few that seem to start to be helpful say things like:
- There's a powershell script that does it: Stop-WebSite 'websitename'
- But you have to install/import the correct powershell website management module to get that work:
Add-PSSnapin WebAdministration
Import-Module WebAdministration
- But those don't work for me. So the internet says to install the module from the download of that module at the MSDN web site.
- It's here that I discover that it's a module for full IIS 7.0 and not for IIS express. It won't even let me install the thing.
- There are other places that say to go to Add/RemovePrograms and hit "Windows Features" and install the management module from there. But looking at those menus, that's also for full IIS and not for IIS express. And anyway it's not clear which tickybox to tick even.
- Okay, then other places say, oh, it's easy, there's a command line tool in the IIS express folder called "appcmd" and it'll let you do a STOP SITE command. Example:
appcmd stop site /site.name: Websitename
- That DOES NOT WORK. Appcmd responds that this is an invalid command, there is no such command as "STOP" for a "SITE". So somehow the version of appcmd I've got is nerfed somehow. Again, this might be an IIS Express versus Full IIS problem. Not sure.
- All the other options I'm seeing (vbscript and WMI methods) all hark back to that website management module. Which I can't figure out how to get installed or whether it even functions with IIS express at all.

Phew.

Any ideas anyone? Please help!
_________________________
Tony Fabris

Top
#365254 - 10/11/2015 00:58 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
I got slightly farther but it's still not working for me, and I think it's an IIS versus IIS Express problem.

What I did:

run appwiz.cpl
select Windows Features on the left hand side.
In the tree item: Internet Information Services
In the Tree item: Web Management Tools
Select the checkbox on this tree item: IIS Management Scripts and Tools


In a command prompt:
Powershell
Import-Module WebAdministration (this succeeded!)
Stop-WebSite "Websitename"

This gets an error message:

stop-webitem : Cannot find path 'IIS:\Sites\Websitename' because it does not exist.

Note that it says: IIS: there and not IISEXPRESS.
_________________________
Tony Fabris

Top
#365255 - 10/11/2015 01:15 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
drakino
carpal tunnel

Registered: 08/06/1999
Posts: 7868
Are you able to start and stop IIS Express as part of your test program? Or is it being started some other way?

http://stackoverflow.com/questions/4772092/starting-and-stopping-iis-express-programmatically might be worth looking at if you can control how IIS Express is being started.

Top
#365256 - 10/11/2015 01:21 Re: Gracefully stopping IIS Express from within my C# program? [Re: drakino]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
That is really interesting. I am investigating that right now. Thank you!
_________________________
Tony Fabris

Top
#365257 - 10/11/2015 01:49 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
After more testing, I think I have my answer.

Thanks, Tom, for giving me a kick with that other method you linked. The method cited there (just send WM_QUIT to IISExpress.exe) worked. But the funny thing is, it didn't work every time for me. This made me question my assumptions.

Rolling back my steps and retrying, I discovered that even TASKKILL /IM IISExpress.exe works, as long as I don't do /F to force kill. Both methods are a graceful stop of the process. But I was, in my experiments, getting different results depending on whether I pressed Q or whether I used an external force to close IISExpress.exe. Pressing Q got me the code coverage results, other methods did not.

Turns out it was a PEBKAC error: I was iterating so quickly on different methods trying to get this to work, that in some important situations I was missing an intermediate step in my experiments: Actually logging into the web site to make it generate some code coverage for me. Some of the cases where I wanted to get code coverage results, I had forgotten to take any actions which would have generated any code coverage. So I was messing up my assumed results by not actually doing all the necessary steps every time. This made me make a bunch of wrong assumptions about which methods worked and which did not.

Turns out that the simple solution: TASKKILL /IM IISExpress.exe, was right all along, and it was just my stupidity that prevented it from working.

At least I think that's the case for now, and I'm going to move forward with more experiments to make sure this is solid.

Thanks!
_________________________
Tony Fabris

Top
#365258 - 10/11/2015 08:19 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
Roger
carpal tunnel

Registered: 18/01/2000
Posts: 5680
Loc: London, UK
_________________________
-- roger

Top
#365259 - 10/11/2015 19:56 Re: Gracefully stopping IIS Express from within my C# program? [Re: Roger]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
So it would seem!

smile
_________________________
Tony Fabris

Top
#365260 - 10/11/2015 19:58 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Since you were using IIS Express with Team City, did you ever try to get DotCover code coverage on the sites you were running?

If you've successfully jumped through those hoops, I'd like any tips you might have. It's proving to be difficult for several reasons, only one of which is the stop-IIS-gracefully problem.
_________________________
Tony Fabris

Top
#365261 - 10/11/2015 20:03 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
New problem:

After all the tests get run on the Team City server, IE, in the full situation rather than in my little bench tests, the TASKKILL /IM iisexpress.exe command is not working, it's responding saying that the task cannot be killed and that I have to force it with the /F parameter.

I think it's probably because there are still things holding the web sites' ports open, like, the sites are still somehow active even though all the test are complete. The sites talk to each other so it's possible that this is the normal state for the sites, but now I have to figure out how to make them disconnect all their connections before I try to shut them down.

Any ideas on how to do *that* to a set of IIS express sites?
_________________________
Tony Fabris

Top
#365287 - 12/11/2015 22:34 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Yeah, wow, this one is a real stumper.

I can get this to work in a local bench test by doing the following:

- Launch the IIS Express executable in a separate window.
- Do my tests to exercise the site.
- When the tests are done, Find the IIS Express Process.MainWindowHandle, then send it a PostMessage of WM_KEYDOWN and WM_KEYUP for the keycode for "q", which is what IIS Express needs to close down gracefully. (StandardInput.Write("q") does NOT work for IIS Express.)
- I can also in many cases successfully send WM_QUIT to the window, or, do TASKKILL /IM Iisexpress.exe.

All of the above things work on my local machine in a brief bench test but then fail utterly once I run the full test suite up on the Team City server. When I try to close down IIS express with these methods, it's ignoring the keystroke and/or refusing to close from the WM_QUIT message.

For instance, doing TASKKILL /IM IISExpress.exe, which works in a local bench test, fails with the following log output on Team City:

ERROR: The process "iisexpress.exe" with PID 3212 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process "iisexpress.exe" with PID 6268 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process "iisexpress.exe" with PID 6084 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process "iisexpress.exe" with PID 3348 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process "iisexpress.exe" with PID 3976 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
_________________________
Tony Fabris

Top
#365294 - 13/11/2015 08:23 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
Roger
carpal tunnel

Registered: 18/01/2000
Posts: 5680
Loc: London, UK
And why can't you use the /F switch?
_________________________
-- roger

Top
#365295 - 13/11/2015 10:14 Re: Gracefully stopping IIS Express from within my C# program? [Re: Roger]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Good question.

Because the whole point of running these sites on the test machine is to run tests. And one thing that I want is the code coverage of those tests tracked. The DotCover code coverage tool only retrieves the code coverage when IIS Express closes down gracefully. If I use /F, I get no code coverage.

Put it another way: we were already using /F but getting no code coverage results. Now I want code coverage results.

I don't know what makes the sites close gracefully on my local machine, but refuse to do so when running the test suite on team city.
_________________________
Tony Fabris

Top
#365297 - 13/11/2015 19:19 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
drakino
carpal tunnel

Registered: 08/06/1999
Posts: 7868
Does Teamcity have an agent that runs as a Windows Service on the test box? Does iisexpress shut down when sent a taskkill with the option "Allow service to interact with desktop" turned on?

I had an automation task with a game patcher that required it to have a desktop session to fully function. Wondering if IISExpress is similar.

Top
#365298 - 13/11/2015 19:59 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
The agent runs as a specific user, not as a windows service. So the "Allow service to interact with desktop" option is not even available for the Team City Agent (it only gives you that checkbox if you're running as a service).
_________________________
Tony Fabris

Top
#365596 - 23/12/2015 21:02 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
More information.

I notice that when running as the Team City agent, on one of the Agent machines, IIS Express refuses to close gracefully with TASKKILL /IM IISExpress.exe in all cases, no matter what.

For instance, start up IIS on a site on the Team City Agent server (Running Windows server 2008 or sever 2012 I think), and the site runs, then, immediately try to shut it down without doing anything special to the site (IE, don't log into it, don't run any tests on it) and it still won't shut down gracefully.

Same steps on local machine (running windows 8) and IIS has no trouble closing down gracefully. Even if I'm logged into the local machine as the TeamCityAgent user with all the same permissions.

Something odd about these Team City Agent servers is why the sites won't shut down gracefully.
_________________________
Tony Fabris

Top
#365597 - 23/12/2015 21:17 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
But if I log into the remote desktop of the team city agent server and do all these things at the command prompt, then they all work without a problem and the sites shut down gracefully.

Something about the way Team City launches these commands in the build steps....
_________________________
Tony Fabris

Top
#365598 - 23/12/2015 21:58 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Working theory:

All methods which normally would gracefully close IISExpress.exe all depend upon there being an interactible window process that WM_CLOSE can be sent to.

Even though it's a console application, it can still receive a WM_CLOSE message as long as it was launched under circumstances which WM_CLOSE would work under, ie, an interactive desktop.

My theory is that the Team City Agents, when running their build steps, do not launch those steps under interactive desktops, so there is no window handle, and there is no way for it to process WM_CLOSE, so that's why TaskKill /IM does not work without the /F parameter.

Now, to figure out how to make it so that it *can* work. How to force an interactive desktop session.
_________________________
Tony Fabris

Top
#365599 - 24/12/2015 00:52 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Confirmed. Environment.UserInteractive=False for any build step launched from within Team City. That's the whole source of the problem. IISExpress.exe needs to be able to receive a WM_CLOSE message but it can't.
_________________________
Tony Fabris

Top
#365644 - 30/12/2015 20:01 Re: Gracefully stopping IIS Express from within my C# program? [Re: tfabris]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Solution!

Launch IIS Express via PSEXEC from Sysinternals. It has a /i command line parameter which forces the launched program to run under an interactive desktop, even if the outer shell program wasn't.

Later, when the testing is done, gracefully shut down IIS Express with a simple TaskKill command (without the /F parameter) to send IIS express the WM_CLOSE message. Taskkill must also be launched via PSEXEC with the /i parameter.


(Another working option is to change the Team City build agent so that it no longer runs as a service, set the Team City build agent server to auto-logon to the desktop and launch the Team City agent as a batch file. This gets the agent running under an interactive desktop. But the PSEXEC thing was much easier and didn't require reconfiguration of our agent servers.)
_________________________
Tony Fabris

Top
#365645 - 30/12/2015 20:04 Re: Gracefully stopping IIS Express from within my C# program? [Re: drakino]
tfabris
carpal tunnel

Registered: 20/12/1999
Posts: 31565
Loc: Seattle, WA
Originally Posted By: drakino
Does Teamcity have an agent that runs as a Windows Service on the test box? Does iisexpress shut down when sent a taskkill with the option "Allow service to interact with desktop" turned on?

I had an automation task with a game patcher that required it to have a desktop session to fully function. Wondering if IISExpress is similar.


So, Tom, you were right all along.
_________________________
Tony Fabris

Top