Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.10.31;
Скачать: [xml.tar.bz2];

Вниз

Ошибка в функции, содержащей WinAPI (CreateProcess и др.)   Найти похожие ветки 

 
Unknown Mystic ©   (2004-08-31 16:05) [0]

Помогите, пожалуйста, написать функцию, чтобы можно было заменить выделенный фрагмент


// Данный фрагмент кода работает.
procedure TMainForm.btnUpdateClick(Sender: PObj);
var
 ...

 iExitCode: integer;
 sArch, sArchParam, sReceiveDir: string;

 TSI: TStartupInfo;
 TPI: TProcessInformation;
 cExitCode: Cardinal;
 Msg: TMSG;
begin
 ...

/////////////////////////////////////////////////////////////////
 // Устанавливаем видимость окна в SW_HIDE
 if false then TSI.wShowWindow := SW_SHOWDEFAULT
 else TSI.wShowWindow := SW_HIDE;
 TSI.dwFlags := STARTF_USESHOWWINDOW;

 // Выполняем команду для распаковки
 CreateProcess(nil, PChar(sArch + " " + sArchParam), nil, nil, false, NORMAL_PRIORITY_CLASS,
               nil, PChar(sReceiveDir), TSI, TPI);
 // Ждем завершения выполнения
 While true do
   case MsgWaitForMultipleObjects(1, TPI.hProcess, false, INFINITE,
                                   QS_PAINT or QS_MOUSE) of
     WAIT_OBJECT_0: Break;
     WAIT_OBJECT_0 + 1 .. WAIT_OBJECT_0 + 2:
       while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
       begin
         TranslateMessage(Msg);
         DispatchMessage(Msg);
       end;
   end;
 // Получаем код возврата
 GetExitCodeProcess(TPI.hProcess, cExitCode);

 iExitCode := cExitCode;
/////////////////////////////////////////////////////////////////

 ...
end;


на что-то вроде
 iExitCode := RunApp(sArch + " " + sArchParam, sReceiveDir, false); // false - окно не видимо
или наверно лучше на
 iExitCode := RunApp(PChar(sArch + " " + sArchParam), PChar(sReceiveDir), false);

Если просто перенести этот код в функцию, то при запуске любой программы вылазит ошибка инициализации и она (программа) завершается. iExitCode равен 128...

Может я не верно с PChar обращаюсь? - больше идей нету.

Заранее благодарен.


 
Digitman ©   (2004-08-31 16:19) [1]

TSI.cb := sizeof(TSI);

if false then TSI.wShowWindow := SW_SHOWDEFAULT
else TSI.wShowWindow := SW_HIDE;
TSI.dwFlags := STARTF_USESHOWWINDOW;

// Выполняем команду для распаковки
if CreateProcess(nil, PChar(sArch + " " + sArchParam), nil, nil, false, NORMAL_PRIORITY_CLASS,
              nil, PChar(sReceiveDir), TSI, TPI) then
 begin
// Ждем завершения выполнения
While true do
  case MsgWaitForMultipleObjects(1, TPI.hProcess, false, INFINITE,
                                  QS_PAINT or QS_MOUSE) of
    WAIT_OBJECT_0: Break;
    WAIT_OBJECT_0 + 1:
      while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
  end;
// Получаем код возврата
GetExitCodeProcess(TPI.hProcess, cExitCode);
CloseHandle(TPI.hThread);
CloseHandle(TPI.hProcess);

end;


 
GrayFace ©   (2004-08-31 18:16) [2]

Digitman ©   (31.08.04 16:19) [1]
if false then TSI.wShowWindow := SW_SHOWDEFAULT
else TSI.wShowWindow := SW_HIDE

:)


 
Digitman ©   (2004-09-01 09:08) [3]


> GrayFace ©   (31.08.04 18:16) [2]


я даже и не посмотрел на эту чушь, скопировал один-в-один, добавив совершенно необходимый код


 
Unknown Mystic ©   (2004-09-01 10:29) [4]

>> Digitman ©   (31.08.04 16:19) [1]

Не помогло...
Если в самой функции делать преобразование string -> pchar, тогда вызов
 iExitCode := RunApp(sArch + " " + sArchParam, sReceiveDir, false);
то ничего не изменилось (в смысле ошибок), а если сразу передавать pchar, т.е.
 iExitCode := RunApp(PChar(sArch + " " + sArchParam), PChar(sReceiveDir), false);
то первый вызов функции проходит нормально, а дальше та же ошибка и выход.

>> GrayFace ©   (31.08.04 18:16) [2]

Это код функции, с минимальными изменениями.


 
Digitman ©   (2004-09-01 10:52) [5]

приведи свой вариант объявления и реализации ф-ции RunApp()


 
Unknown Mystic ©   (2004-09-01 13:06) [6]

Объявления нету - просто код в разделе implementation сразу после раздела var.

function RunApp(pCmdLine, pWorkDir: PChar; bShow: boolean): Integer;
var
 TSI: TStartupInfo;
 TPI: TProcessInformation;
 cExitCode: Cardinal;
 Msg: TMSG;
begin
 TSI.cb := sizeof(TSI);

 if bShow then TSI.wShowWindow := SW_SHOWDEFAULT
 else TSI.wShowWindow := SW_HIDE;
 TSI.dwFlags := STARTF_USESHOWWINDOW;

 CreateProcess(nil, pCmdLine, nil, nil, false, NORMAL_PRIORITY_CLASS,
               nil, pWorkDir, TSI, TPI);
 // Ждем завершения выполнения
 While true do
   case MsgWaitForMultipleObjects(1, TPI.hProcess, false, INFINITE,
                                   QS_PAINT or QS_MOUSE) of
     WAIT_OBJECT_0: Break;
     WAIT_OBJECT_0 + 1 .. WAIT_OBJECT_0 + 2:
       while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
       begin
         TranslateMessage(Msg);
         DispatchMessage(Msg);
       end;
   end;
 // Получаем код возврата
 GetExitCodeProcess(TPI.hProcess, cExitCode);

 CloseHandle(TPI.hThread);
 CloseHandle(TPI.hProcess);

 Result := cExitCode;
end;


 
Digitman ©   (2004-09-01 13:13) [7]

опять двадцать пять ...

ну ты хоть в код-то в [1] вникал ?

CreateProcess - функция !! а не процедура ... почему не анализируешь результат ее выполнения ?

WAIT_OBJECT_0 + 2 - а это откуда здесь взялось ? у тебя всего один объект синхронизации ... максимум что можно ожидать - WAIT_OBJECT_0 + 1


 
Unknown Mystic ©   (2004-09-01 13:58) [8]

>> Digitman ©   (01.09.04 13:13) [7]

Виноват :( Увидел выделенные фрагменты, а остальное не посмотрел...

CreateProcess - поправлю и посмотрю что он выдает...

Я думал, что
QS_PAINT  -  WAIT_OBJECT_0 + 1
QS_MOUSE  -  WAIT_OBJECT_0 + 2

И еще вопрос попутно возник:
Имеет ли значение последовательность выполнения?

CloseHandle(TPI.hThread);
CloseHandle(TPI.hProcess);

А то в примере MSDNа наоборт.


 
Digitman ©   (2004-09-01 14:08) [9]


> поправлю и посмотрю что он выдает


да... и это важно


> думал, что
> QS_PAINT  -  WAIT_OBJECT_0 + 1
> QS_MOUSE  -  WAIT_OBJECT_0 + 2


нет.

WAIT_OBJECT_0 - стартованный тобой процесс завершился
WAIT_OBJECT_0 + 1 - в очереди сообщений окна, созданного текущим трэдом, есть сообщения. которые необходимо обработать, что собственно ты и делаешь в цикле while PeekMessage() do..


> Имеет ли значение последовательность выполнения?
>
> CloseHandle(TPI.hThread);
> CloseHandle(TPI.hProcess);


думаю что в принципе не имеет , хэндлы так или иначе должны быть закрыты, коль они созданы системой в ходе вызова Createprocess() и возвращены тебе


 
Unknown Mystic ©   (2004-09-01 14:21) [10]

Спасибо. К сожалению Delphi есть только дома. Завтра скажу, что получилось.

А такой вызов функции верен? (Я в преобразовании сомневаюсь.)
iExitCode := RunApp(PChar(sArch + " " + sArchParam), PChar(sReceiveDir), false);


 
Digitman ©   (2004-09-01 14:28) [11]


> Unknown Mystic ©   (01.09.04 14:21) [10]


> А такой вызов функции верен?


при приведенной тобой конкретной декларации ф-ции RunApp() почему же не верен ? я не вижу тут никаких подводных камней ..


> в преобразовании сомневаюсь


поделился бы сомнениями, коль имеются ..


 
GrayFace ©   (2004-09-01 17:44) [12]

Зачем нужен cExitCode? Просто подавай Cardinal(Result).


 
Unknown Mystic ©   (2004-09-02 12:21) [13]

Поправил. CreateProcess() false возващает и программа вылетает.


 
Digitman ©   (2004-09-02 12:24) [14]

Return Values

If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.


 
Unknown Mystic ©   (2004-09-20 13:19) [15]

// Прошу прощения за такой перерыв...

На текущий момент функция:

function RunApp(pCmdLine, pWorkDir: PChar; bShow: boolean): Integer;
var
 TSI: TStartupInfo;
 TPI: TProcessInformation;
 cExitCode: Cardinal;
 Msg: TMSG;
 RunOK: string;
 dw: DWord;
 lpMsgBuf: string;
begin
 MainForm.reLog.Add(#13#10 + pCmdLine + #13#10);
 MainForm.reLog.Add(pWorkDir + #13#10);
 Result := -1;
 TSI.cb := SizeOf(TSI);

 if bShow then TSI.wShowWindow := SW_SHOWDEFAULT
 else TSI.wShowWindow := SW_HIDE;
 TSI.dwFlags := STARTF_USESHOWWINDOW;

 RunOK := "CreateProcess return false";
 if CreateProcess(nil, pCmdLine, nil, nil, false, NORMAL_PRIORITY_CLASS,
                  nil, pWorkDir, TSI, TPI) then
 begin
   RunOK := "CreateProcess return true";
   // Ждем завершения выполнения
   While true do
     case MsgWaitForMultipleObjects(1, TPI.hProcess, false, INFINITE,
                                     QS_PAINT or QS_MOUSE) of
       WAIT_OBJECT_0: Break;
       WAIT_OBJECT_0 + 1:
         while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
         begin
           TranslateMessage(Msg);
           DispatchMessage(Msg);
         end;
     end;
   // Получаем код возврата
   GetExitCodeProcess(TPI.hProcess, Cardinal(Result));

   CloseHandle(TPI.hThread);
   CloseHandle(TPI.hProcess);
 end
 else begin
   dw := GetLastError();
   MainForm.reLog.Add("Error " + Int2Str(dw) + " - "+ SysErrorMessage(dw) + #13#10);
{    FormatMessage(
       FORMAT_MESSAGE_ALLOCATE_BUFFER OR
       FORMAT_MESSAGE_FROM_SYSTEM,
       nil,
       dw,
       LANG_RUSSIAN,//MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       PChar(lpMsgBuf),
       0, nil );
   MainForm.reLog.Add("CreateProcess() failed with error " + Int2Str(dw) + ": " + lpMsgBuf + #13#10);}
 end;
 MainForm.reLog.Add(RunOK + #13#10 + #13#10);
end;


вызывается:

iExitCode := RunApp(PChar(sArch + " " + sArchParam), PChar(sReceiveDir), false);

В результате выполнения в MainForm.reLog попадает строкаи (кроме верных pCmdLine и pWorkDir):
Error 998 - Не верная попытка доступа к адресу памяти.
CreateProcess return false

После чего вылазит сообщение об ошибке:
Инструкция по адресу "0x77f8c15c" обратилась к памяти по адресу 0x00000003.
Память не может быть "read".

// С что-то не вышло поэтому и закомментировал.


 
Digitman ©   (2004-09-22 09:30) [16]

для начала почисть структуру TSI

FillChar(TSI, SizeOf(TSI), 0);
TSI.cb := SizeOf(TSI);


 
Unknown Mystic ©   (2004-09-23 12:03) [17]

Почистил и все заработало. Уже на 3-ем ПК все нормально работает. Большое спасибо!

Может есть еще замечания по поводу моего кода?



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.10.31;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.037 c
1-1097591583
hooky-mars
2004-10-12 18:33
2004.10.31
Добавление строк в Excel


10-1049790727
vovan_i
2003-04-08 12:32
2004.10.31
Использование IStringsPtr в DCOM


1-1097824953
Dionnis
2004-10-15 11:22
2004.10.31
Закрыть все формы приложения


1-1097592193
Expl
2004-10-12 18:43
2004.10.31
вызов hlp файла при нажатии на клавишу


4-1096379974
Гость
2004-09-28 17:59
2004.10.31
Языки операционных систем





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский