views:

47

answers:

2

In one of my programs I am using rundll32.exe url.dll,FileProtocolHandler c:\path\to\a.file to open files. I would like to handle errors in case this file could not be opened but I can't figure out how to find out if there was an error or not. That's my code:

QProcess::startDetached( QString( "rundll32.exe url.dll,FileProtocolHandler " + p_target_path ) );

startDetached() now always returns true, because it's always succesfull in opening a process containing rundll32.exe. So how do I know if my file could be found/opened or not?

I tried errorlevel-things in a *.bat file for testing.

rundll32.exe url.dll,FileProtocolHandler c:\not_existing.exe >nul || echo Could not open file.

But there is nothing being echoed. I also tried to read the %ERRORLEVEL%, but even if the file is not existing the errorlevel remains 0.

Does anyone know a way to find out how to deal with this?

A: 

It seems to me that rundll32.exe is really not return an erorlevel. It you look at http://support.microsoft.com/kb/164787 you can see, that Rundll32 Interface has no defined way to return error.

VOID CALLBACK FileProtocolHandler (
  __in  HWND hwnd,
  __in  HINSTANCE ModuleHandle,
  __in  PCTSTR pszCmdLineBuffer,
  __in  INT nCmdShow
);

By the way you can call the function FileProtocolHandler exported by url.dll directly without starting rundll32.exe. As pszCmdLineBuffer you can give p_target_path. Nevertheless you will receive no error information.

UPDATED: By the way if you use rundll32.exe url.dll,FileProtocolHandler to open files only and not URLs than you can use ShellExecute or ShellExecuteEx instead with the verb "open" or NULL (see http://msdn.microsoft.com/en-us/library/bb776886.aspx). In the simplest case the code could looks like following

HINSTANCE hInst = ShellExecute (NULL, TEXT("open"), TEXT("c:\path\to\a.file"), NULL, NULL, 0);

You can test hInst for the errors (see Return Value in http://msdn.microsoft.com/en-us/library/bb762153.aspx)

Oleg
Thx for your help, this looks just as if it could be the solution... But how can I use ShellExecute and the hInst value together with a startDetached()? And how to give a var to the third parameter in ShellExecute? TEXT(p_target_path) won't work 'cause the macro will add an L at the beginning...
Exa
I debugged a little bit and tested the code you posted. When giving c:\windows\system32\cmd.exe to the ShellExecute, hInst is "0x0000002a"... But cmd is not being opened...
Exa
I tested other programs and they did work well, but hInst still is 0x0000002a...
Exa
I'm getting crazy... it DID start cmd.exe but in the background without showing a window.... Same for an *.sln (VS2005) file... It started devenv.exe and loaded everything into the RAM but there is no VS2005 window.... Strange isn't it...?
Exa
Sorry, but you should read documentation of `ShellExecute` and `ShellExecuteEx`. For example, "If the function succeeds, it returns a value greater than 32". So hInst=0x0000002a means NO error. The last parameter of `ShellExecute` (`nShowCmd`) defines how the started application should show the main window. You can use for example `SW_SHOW`. To start program asynchronously you should use `ShellExecuteEx` together with the flag `SEE_MASK_NOCLOSEPROCESS`. Just look in MSDN or serch in google for examples.
Oleg
The problem with macro `TEXT` you hopefully already solved. It makes `L` at the beginning (UNICODE string) depend on preprocessor directives of your compiler. If you not yet use UNICODE string you can just remove `TEXT` macro and better explicitly use `ShellExecuteA` or `ShellExecuteExA` (ANSI verion of this functions) instead of `ShellExecute` or `ShellExecuteEx` which can be translated to `ShellExecuteW` or `ShellExecuteExW` if you wrong preprocessor directives for the compiler.
Oleg
Wir hätten uns auch auf deutsch unterhalten können, fällt mir grade auf... :) Nochmal danke für die Hilfe!
Exa
A: 

Yep, even before you wrote your comment, I started to read the documentation properly and in less then 2 minutes I had the solution:

void main_window::open_test( QString p_target_path )
{
    p_target_path = p_target_path.remove( "\"" );

    HINSTANCE res = ShellExecute( NULL, TEXT("open"), (LPCWSTR) p_target_path.utf16(), NULL, NULL, SW_SHOWNORMAL );

    QString err_str = "";

    int res_code = (int) res;

    switch( res_code )
    {
    case 0:
        err_str = "Your operating system is out of memory or resources.";
        break;
    case ERROR_FILE_NOT_FOUND:
        err_str = "The specified file was not found.";
        break;
    case ERROR_PATH_NOT_FOUND:
        err_str = "The specified path was not found.";
        break;
    case ERROR_BAD_FORMAT:
        err_str = "The .exe file is invalid (non-Win32 .exe or error in .exe image).";
        break;
    case SE_ERR_ACCESSDENIED:
        err_str = "Your operating system denied access to the specified file.";
        break;
    case SE_ERR_ASSOCINCOMPLETE:
        err_str = "The file name association is incomplete or invalid.";
        break;
    case SE_ERR_DDEBUSY:
        err_str = "The DDE transaction could not be completed because other DDE transactions were being processed.";
        break;
    case SE_ERR_DDEFAIL:
        err_str = "The DDE transaction failed.";
        break;
    case SE_ERR_DDETIMEOUT:
        err_str = "The DDE transaction could not be completed because the request timed out.";
        break;
    case SE_ERR_DLLNOTFOUND:
        err_str = "The specified DLL was not found.";
        break;
    case SE_ERR_NOASSOC:
        err_str = "There is no application associated with the given file name extension.\nThis error will also be returned if you attempt to print a file that is not printable.";
        break;
    case SE_ERR_OOM:
        err_str = "There was not enough memory to complete the operation.";
        break;
    case SE_ERR_SHARE:
        err_str = "A sharing violation occurred.";
        break;
    default:
        return;
    }

    QMessageBox::warning( this, "Error", err_str );
}
Exa