7

I am starting a small console application from within my IIS web application. The code is started from within an app pool using code like this,

Process process = new Process();
ProcessStartInfo processStartInfo = new ProcessStartInfo();

processStartInfo.CreateNoWindow = true;
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

// ..

process.Start();

I used to intermittently get an error,

Win32Exception exception has occured  Message: No such interface supported
ErrorCode: 80004005  NativeErrorCode: 80004002

I proved that when this happened the console application wouldn't start at all.

I added to the code above this,

processStartInfo.UseShellExecute = false;

And the problem has gone away (so far, fingers crossed). I understand that by making this change it doesn't require a valid desktop context to run, but what exactly does that mean. If that means we cannot run the above code if there is no desktop (which applies to an IIS app pool running with a system user), then why did it used to run sometimes in the past rather than fail every time?

Does anybody have any idea why this would make a difference? What does no interface supported mean in this context?

UPDATE:

I have taken on board everything people have said, and done more research myself. So to summarise if you have UseShellExecute = true (which is the default) then it will call ShellExecuteEX in shell32.dll to execute the process. It will do this actually (copied from the System.dll using ILSpy),

public bool ShellExecuteOnSTAThread()
{
    if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
    {
        ThreadStart start = new ThreadStart(this.ShellExecuteFunction);
        Thread thread = new Thread(start);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        thread.Join();
    }
    else
    {
        this.ShellExecuteFunction();
    }
    return this._succeeded;
}

If you have UseShellExecute = false then it will call CreateProcess in kernel32.dll to start the process.

I was wondering if there is a problem with the fact the the code ShellExecuteOnSTAThread above is creating a new thread? Could the app pool reach some limit on the threading which could indirectly cause a Win32Exception?

peter
  • 13,009
  • 22
  • 82
  • 142
  • I've seen this specific failure mode mentioned several times in the last couple of months. Nothing close to an explanation, but using UseShellExecute = false will certain fix it. – Hans Passant Apr 20 '12 at 00:07
  • Thanks. Where else have you seen it? I can't really find it anywhere? Sorry if I am asking a question you can't answer, but I would be curious if you can find them. – peter Apr 20 '12 at 00:22
  • 1
    This doesn't answer what Hans is getting at but this SO question has some interesting detail: http://stackoverflow.com/questions/5255086/when-do-we-need-to-set-useshellexecute-to-true – Russ Clarke Apr 20 '12 at 00:48

1 Answers1

8

This error can occur when certain COM objects aren't registered, although it's a bit of a mystery to me why it's intermittent.

In fairness though, Spawning a local executable from within IIS is a pretty rare thing to do and it may actually cause a security problem, or at the least cause an issue with IIS if the command fails for some reason and doesn't give control back to the system.

In reality the best practice for something like that is to record the action that you need to happen inside the registry,database or some kind of setting file and have your local application run as a scheduled task or a windows service.

For reference, the UseShellExec states whether or not the Kernel should launch the exe directly, or whether it should ask Explorer to launch the file.

You might be getting this problem when there's no-one logged in so there isn't necessarily a shell loaded to launch the exe.

Ultimately though, what you're currently trying to do is a bad thing in production - you cannot guarantee the state of IIS when it tries to launch this exe and rightly so, IIS is not a Shell.

Russ Clarke
  • 17,511
  • 4
  • 41
  • 45
  • To qualify the security concern, IIS typically runs with high privileges and launching a process in the manner you're attempting will launch it with the same set of privileges. IMHO this is rarely a good thing. – Russ Clarke Apr 19 '12 at 23:58
  • 1
    OK, thanks. I am not worried about security, I don't have time to explain the full story on that. I agree, you say we might be getting the problem when there is no one logged into the server. Sounds correct, but it doesn't seem to be the case. It must relate to some other problem that 'loading the shell' causes. – peter Apr 20 '12 at 00:43
  • Security aside, it's still a question of having a valid state on the server. what happens if something stalls the exe and the IIS worker process restarts or spins down because of an activity timeout ? I guess knowing what this exe is intended to do is going to help; even if you can only provide the mile-high view. – Russ Clarke Apr 20 '12 at 00:51
  • Sure. It is taking a document such as a pdf file (as a byte[]) and generating an image which is a 'preview' image. This means a PNG image which is an image of the first page. This is done in a separate process because it is using the GhostScript library which is a C library, and is not thread safe. – peter Apr 20 '12 at 01:36
  • By the way I point out that this process creates just a 'preview'. If the preview process fails then it doesn't cause data loss of a serious issue in the software. It just means that when the user loads up their page next time the preview will be blank when they click on the documents in a list. They will have to click a button to download and view their attachment before they can be sure which one is which. – peter Apr 20 '12 at 02:07