Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   API de Windows (https://www.clubdelphi.com/foros/forumdisplay.php?f=7)
-   -   Error utilizando GetModuleUsage en WinExecAndWait32 en Borland Delphi 7 (https://www.clubdelphi.com/foros/showthread.php?t=47248)

feidakila 22-08-2007 18:51:43

Error utilizando GetModuleUsage en WinExecAndWait32 en Borland Delphi 7
 
Hola, estoy usando Borland Delphi 7 y necesitaba un procedimiento para ejecutar un programa en consola (cmd) de manera síncrona (es decir hasta que no termina de ejecutarse el programa en la consola no se devuelve el control al programa Delphi que lo llamó) y he estado investigando en la red y el foro y me he topado con una funcion llamada WinExecAndWait32. He descargado 3 versiones diferentes de esta y sólo he conseguido hacer funcionar una de las 3 después de alguna leve modificación.

Pongo las 3 funciones, los problemas que he tenido y las modificaciones que les he hecho, además propongo una duda al final del post que me surge en una de las implementaciones y que no se resolver (por curiosidad)

1era implementacion: esta no me funciona, ya que se llama a WaitForSingleObject antes de que finalice el programa llamado por WinExec
Código Delphi [-]
function TForm1.WinExecAndWait(Path:PChar;Visibility:Word):Word;
var
  InstanceID:THandle;
begin
  InstanceID:=WinExec(Path, Visibility);
  WinExecAndWait:=WaitForSingleObject(InstanceID,INFINITE);
end;



2da implementacion: en esta me surgieron los siguientes errores, al principio cuando operamos con la variable Path, se intenta acceder mediante la funcion move a Path[0] con lo que da un error de compilación de valor inaccesible (supongo que se almacena el valor de la longitud de la cadena en esa celda); esto lo he solucionado cambiando el tipo de la variable Path a PChar para no tener que hacer ninguna transformación a Path (de todas maneras no se porque lo hace el autor). Como 2º error que no he conseguido solventar es la llamada a la funcion GetModuleUsage, la cual al compilar me dice que no existe dicho identificador y en la ayuda de Dephi no viene nada al respecto, como solución la he comentado pero evidentemente la función retoma el control antes de que el programa de consola termine (la condición es true)
Código Delphi [-]
Function TForm1.WinExecAndWait33(Path : PChar; Visibility : word) : word;
var
  InstanceID : THandle;
//  PathLen : integer;
begin
  { inplace conversion of a String to a PChar }
//  PathLen := Length(Path);
//  Move(Path[1],Path[0],PathLen);  {esta linea falla al acceder a path[0]}
//  Path[PathLen] := #0;
  { Try to run the application }
  InstanceID := WinExec(Path,Visibility); {hemos sustituido @Path por Path}
  if InstanceID < 32 then { a value less than 32 indicates an Exec error }
     WinExecAndWait33 := InstanceID
  else
  begin
    Repeat
      Application.ProcessMessages;
    until Application.Terminated;{or (GetModuleUsage(InstanceID)=0);}  {error! getmoduleusage -> identificador no declarado}
    WinExecAndWait33 := 32;
  end;
end;


3era implementacion: por último y la que me ha funcionado, salvo una ligera modificación. Y ha sido cambiar el tipo de la variable lpExitCode (antes entero) a tipo cardinal (según parece antes estaba definido como entero y ahora como cardinal)
Código Delphi [-]
function TForm1.WinExecAndWait32(Path: PChar; Visibility: Word): integer;
var
   Msg: TMsg;
   lpExitCode : cardinal;  {antes era integer}
   StartupInfo: TStartupInfo;
   ProcessInfo: TProcessInformation;
begin
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  with StartupInfo do
  begin
    cb := SizeOf(TStartupInfo);
    dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
    wShowWindow := visibility; 
  end;
  if CreateProcess(nil,path,nil, nil, False,
    NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin
    repeat
      while PeekMessage(Msg, 0, 0, 0, pm_Remove) do
        begin
          if Msg.Message = wm_Quit then Halt(Msg.WParam);
          TranslateMessage(Msg);
          DispatchMessage(Msg);
        end;  
    GetExitCodeProcess(ProcessInfo.hProcess,lpExitCode);    {producia error porque lpExitCode es de tipo entero y ha de ser cardinal}
    until lpExitCode<>Still_Active;
    with ProcessInfo do 
    begin
      CloseHandle(hThread);
      CloseHandle(hProcess);
    end;
    result := 0; {sucess}
  end
  else
    result:=GetLastError;
end;



Duda en la 2da implementación ¿porqué no me deja declarar la función GetModuleUsage?, ¿no viene implementada en la librería ShellApi de Borland? (he tratado a incluir la librería WinApi pero me da error, supongo que tampoco existe), ¿existe una función similar, se llama de otra manera?

Perdonad el rollo, pero es que llevaba un tiempo estancado con esto y lo mismo este post sirve por si alguien se topa con el mismo problema, muchas gracias y enhorabuena por el foro es de grandísima ayuda :)


La franja horaria es GMT +2. Ahora son las 23:55:18.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi