Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > ShellExecute, REGSVR32.EXE


Автор: lv151 27.1.2010, 17:35
Привет.
Запускаю
int res = (int)ShellExecute(NULL, NULL, "REGSVR32.EXE", path, NULL, SW_SHOWNORMAL);

Допустим что DLL-ки нет по такому пути. Выскакивает ShowMessage о том, что невозможно загрузить библиотеку, 
но res = 42, как будто ShellExecute отработал нормально.

Как обработатать эту ошибку?

Автор: artsb 27.1.2010, 18:06
Цитата(lv151 @  27.1.2010,  17:35 Найти цитируемый пост)
Как обработатать эту ошибку?

ИМХО никак. Функция то ведь действительно отработала нормально. Всё запустила что нужно. А вот REGSVR32.EXE не нашла dll'ку указанную в параметрах, а следовательно она и генерирует ошибку.
Единственное, может попробовать создавать процесс через http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx. А после его отработки получать код завершения:
Код

int res;
GetExitCodeProcess(ProcessHandle, &res);

обычно, при успешном завершении возвращается 0. Если вернулось STILL_ACTIVE - процесс ещё работает. Подробности - http://msdn.microsoft.com/en-us/library/ms683189%28VS.85%29.aspx.

Автор: GoldFinch 27.1.2010, 18:35
Цитата(artsb @  27.1.2010,  18:06 Найти цитируемый пост)
Если вернулось STILL_ACTIVE - процесс ещё работает.

надо сразу вызывать
WaitForSingleObject(processInformation.hProcess,-1);
чтобы подождать его завершения

Автор: artsb 27.1.2010, 18:42
Цитата(GoldFinch @  27.1.2010,  18:35 Найти цитируемый пост)
WaitForSingleObject(processInformation.hProcess,-1)

А если он повиснет по каким-нибудь причинам, то прога тоже повиснет. Поэтому лучше в цикле ждать небольшой промежуток времени раз пять:
Код

for(int i=0; i<5; i++) {
 WaitForSingleObject(processInformation.hProcess, 1000); // ждём секунду
 if(i == 4) {
  // что-то долго процесс не завершается...
  // предпринимаем меры
 }
}

Что типа этого. Только время нужно своё подобрать.

Автор: GoldFinch 27.1.2010, 18:48
artsb, так запускай ожидание в отдельном потоке, и пусть себе виснет.
полюбому такие вещи должны быть развязаны с пользовательским интрефейсом

если запускаемый процесс повис - юзер это заметит, и например убьет повисший процесс, тогда ожидание закончится
или можно предусмотреть в нашей программе кнопку [убить процесс]

Добавлено через 1 минуту и 25 секунд
а ждать четыре раза по 1 сек в цикле - это бред)

Автор: artsb 27.1.2010, 19:08
Цитата(GoldFinch @  27.1.2010,  18:48 Найти цитируемый пост)
юзер это заметит, и например убьет повисший процесс

не все такие умные smile

Цитата(GoldFinch @  27.1.2010,  18:48 Найти цитируемый пост)
а ждать четыре раза по 1 сек в цикле - это бред) 

а вот и нет. Зависит от задачи. Это я просто пример привёл. А устраивать ожидание до бесконечности (даже в отдельном потоке) нужно лишь в том случае, если есть 100-процентная уверенность, что процесс рано или поздно завершится.

Автор: GremlinProg 27.1.2010, 20:01
чтобы особенно ничего не менять, можно использовать ShellExecuteEx
дескриптор процесса тут: SHELLEXECUTEINFO::hProcess

если надо скрыть окна запускаемого процесса, можно попробовать передать в ShellExecute дескриптор какого-нить своего скрытого окна или вообще поиграться с SHELLEXECUTEINFO::DUMMYUNIONNAME::hMonitor

Автор: lv151 28.1.2010, 11:14
thx all.

Автор: lv151 28.1.2010, 12:41
Как сделать так, чтобы выскакивал ShowMessage об успешной регистрации dll-ки,
ползаю по описание функции, но не нахожу параметра.
Код

SHELLEXECUTEINFO info;
memset(&info, 0, sizeof(SHELLEXECUTEINFO));

info.cbSize = sizeof(SHELLEXECUTEINFO);
info.fMask = SEE_MASK_FLAG_NO_UI;
info.lpVerb = _T ("open");
info.lpFile = szDllPath;
info.nShow = SW_SHOW;



    

Автор: artsb 28.1.2010, 13:04
Цитата(lv151 @  28.1.2010,  12:41 Найти цитируемый пост)
но не нахожу параметра.

его и нет smile

Цитата(lv151 @  28.1.2010,  12:41 Найти цитируемый пост)
Как сделать так, чтобы выскакивал ShowMessage

Схематически:
Код

SHELLEXECUTEINFO info;
// ...
if(ShellExecuteEx(info)) {
 // используя WaitForSingleObject дожидаемся завершения процесса
 // первым параметром будет info.hProcess
 int res;
 GetExitCodeProcess(info.hProcess, &res);
 if(res == 0)
  ShowMessage("Success!");
}


Добавлено через 2 минуты и 43 секунды
Но повторюсь, что обычно при успехе возвращается 0, но не всегда так бывает.

Автор: xvr 28.1.2010, 14:40
Цитата(lv151 @ 27.1.2010,  17:35)
Запускаю
int res = (int)ShellExecute(NULL, NULL, "REGSVR32.EXE", path, NULL, SW_SHOWNORMAL);

Если нужен ИМЕННО regsvr32, то проще его не запускать, а выполнить его работу самому. Он делает тривиальную вещь - грузит указанный dll, извлекает из него адрес функции DllRegisterServer (кажется так) и запускает ее. 5 строчек кода  smile 

Автор: jonie 29.1.2010, 12:40
а нахрена самому вызывать regsvr32, если тоже что он делает можно сделать руками самому, вызвав экспортируемые функции?

Автор: lv151 8.2.2010, 11:39
У меня почему то info.hProcess = 0 ?

Автор: artsb 8.2.2010, 12:22
Что-то мой хрустальный шар барахлит.  smile  Можешь дать кусочек кода?

Автор: lv151 8.2.2010, 13:16
Код

   SHELLEXECUTEINFO info;
    memset(&info, 0, sizeof(SHELLEXECUTEINFO));

    info.cbSize = sizeof(SHELLEXECUTEINFO);
    info.fMask = SEE_MASK_FLAG_NO_UI;
    info.lpVerb = _T ("open");
    info.lpFile = "REGSVR32.EXE";
    info.lpParameters = szDll;
    info.nShow = SW_SHOW;

    BOOL res = ShellExecuteEx(&info);
    WaitForSingleObject(info.hProcess, INFINITE);
    
    DWORD resProc = 0;    
    GetExitCodeProcess(info.hProcess, &resProc);

    if (res == FALSE || resProc != 0)
   {
    LPVOID lpMsgBuf;        

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                                  FORMAT_MESSAGE_FROM_SYSTEM | 
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL,
                                  GetLastError(),
                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
                                  (LPTSTR) &lpMsgBuf,
                  0,
                  NULL);
        
    MessageBox(NULL, (LPCSTR)lpMsgBuf, "Error", MB_OK|MB_ICONSTOP);

    LocalFree(lpMsgBuf);
    
        return result;
    }


Отрабатывает всё нормально.

Автор: xvr 8.2.2010, 13:24
Код

info.fMask = SEE_MASK_FLAG_NO_UI|SEE_MASK_NOCLOSEPROCESS;

Автор: artsb 8.2.2010, 13:36
А на каком этапе info.hProcess становится = 0? Может она изначально равна 0...

Автор: xvr 8.2.2010, 13:48
Цитата(artsb @ 8.2.2010,  13:36)
А на каком этапе info.hProcess становится = 0? Может она изначально равна 0...

Видимо изначально - ТС не поставил необходимый флажок в fMask 

Автор: artsb 8.2.2010, 13:51
Цитата(xvr @  8.2.2010,  13:48 Найти цитируемый пост)
Видимо изначально - ТС не поставил необходимый флажок в fMask 

скорее после выполнения ShellExecuteEx. Флаг должен помочь  smile

Добавлено через 1 минуту и 10 секунд
Цитата

SEE_MASK_NOCLOSEPROCESS
    0x00000040. Use to indicate that the hProcess member receives the process handle. This handle is typically used to allow an application to find out when a process created with ShellExecuteEx terminates. In some cases, such as when execution is satisfied through a Dynamic Data Exchange (DDE) conversation, no handle will be returned. The calling application is responsible for closing the handle when it is no longer needed.

Автор: lv151 8.2.2010, 17:31
Всё дело в маске.
Спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)