Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.31;
Скачать: CL | DM;

Вниз

Ошибка в функции, содержащей 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 вся ветка

Текущий архив: 2004.10.31;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.024 c
1-1097831601
tria
2004-10-15 13:13
2004.10.31
Как картику из ImageList скопировать в Icon формы?


3-1096897477
sloug
2004-10-04 17:44
2004.10.31
TDBRichEdit ошибка


1-1098018449
denis24
2004-10-17 17:07
2004.10.31
множественный выбор из одного listbox в другой


4-1096106992
Alexander K.
2004-09-25 14:09
2004.10.31
Работа с корзиной


1-1098181125
__Strelok__
2004-10-19 14:18
2004.10.31
DateTimePicker - Дата и время