Ver Mensaje Individual
  #11  
Antiguo 14-11-2006
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Reputación: 24
seoane Va por buen camino
Vamos a destripar esta pieza de relojería
Código Delphi [-]
// Esta funcion nos indica si sobre un archivo hay alguna operacion pendiente
// de realizarse en el siguiente reinicio
function Pendiente(Archivo: string): Boolean;
var
  Buffer: PChar;
  Size: Integer;
  i: integer;
begin
  Result := FALSE;
  with TRegistry.Create do
  try
    Access := KEY_READ;
    RootKey := HKEY_LOCAL_MACHINE;
    if OpenKey('\SYSTEM\CurrentControlSet\Control\Session Manager', FALSE) then
    begin
      if ValueExists('PendingFileRenameOperations') then
      begin
        Size := GetDataSize('PendingFileRenameOperations');
        if Size > 0 then
        try
          GetMem(Buffer, Size);
          try
            Fillchar(Buffer^, Size, #0);
            ReadBinaryData('PendingFileRenameOperations', Buffer^, Size);
            for i := 0 to Size - 2 do
              if Buffer[i] = #0 then
                Buffer[i] := #13
              else
                Buffer[i] := upcase(Buffer[i]);
            if StrPos(Buffer, PChar(Uppercase(Archivo))) <> nil then
              Result := TRUE;
          finally
            FreeMem(Buffer);
          end;
        except
        end;
      end;
      CloseKey;
    end;
  finally
    Free;
  end;
end;

procedure Reemplazar(Viejo, Nuevo: string);
begin
  // Comprobamos si hay alguna operacion pendiente sobre los archivos
  if Pendiente(Viejo) or Pendiente(Nuevo) then
    Exit;
  // Si no hay archivo nuevo es que lo queremos borrar
  if Nuevo = '' then
  begin
    // Para borrarlo primero tiene que existir
    if FileExists(Viejo) then
      // Lo intentamos borrar por las buenas
      if not DeleteFile(Viejo) then
        // Si no podemos lo dejamos pendiente hasta reiniciar el equipo
        MoveFileEx(PChar(Viejo), nil, MOVEFILE_DELAY_UNTIL_REBOOT or
          MOVEFILE_REPLACE_EXISTING);
  end
  else
  begin
    // Intentamos reemplazar un archivo por otro, por las buenas
    if MoveFileEx(PChar(Nuevo), PChar(Viejo), MOVEFILE_REPLACE_EXISTING) then
    begin
      // Si lo conseguimos y el archivo se llama autorun.exe lo ejecutamos
      if Uppercase(ExtractFileName(Viejo)) = 'AUTORUN.EXE' then
        ShellExecute(0, nil, PChar(Viejo), nil, nil, SW_SHOW);
    end
    else
    begin
      // Si no conseguimos hacerlo por las buenas lo retrasamos hasta el siguiente reinicio
      MoveFileEx(PChar(Nuevo), PChar(Viejo), MOVEFILE_DELAY_UNTIL_REBOOT or
        MOVEFILE_REPLACE_EXISTING)
    end;
  end;
end;

En ningún momento intento cerrar la aplicación. Si es eso lo que quieres puedes intentar mostrar un aviso y esperar a que el usuario la cierre, cerrarla por las malas o si estas intentando actualizar tu propia aplicación hacer algo como esto (que ya puse en otro hilo):
Código Delphi [-]
procedure Actualizate(Nuevo: string);
var
  Actual: String;
  Buffer: array[0..MAX_PATH] of Char;
begin
  if GetShortPathName(PChar(ParamStr(0)),@Buffer, Sizeof(Buffer) -1) = 0 then
    Exit;
  Actual:= String(PChar(@Buffer));
  if GetShortPathName(PChar(Nuevo),@Buffer, Sizeof(Buffer) -1) = 0 then
    Exit;
  Nuevo:= String(PChar(@Buffer));
  with TStringList.Create do
  try
    Add(':BUCLE');
    Add('Del ' + Actual);
    Add('if %ERRORLEVEL% NEQ 0 goto BUCLE');
    Add('Copy ' + Nuevo + ' ' + Actual);
    Add('Start ' + Actual);
    SaveToFile(ChangeFileExt(ParamStr(0),'.bat'));    
    ShellExecute(0,nil,PChar(ChangeFileExt(ParamStr(0),'.bat')),nil,nil,SW_SHOW);
  finally
    Free;
  end;
end;

// Ejemplo de uso
Actualizate('c:\Windows\Temp\nuevo.exe');
Halt; // Lo apropiado seria usar close, o algo similar
Responder Con Cita