El objetivo es reemplazar un archivo por otro, si se puede en el momento, se reemplaza pero si no se puede la operacion se deja pendiente hasta el siguiente reinicio del equipo. Windows se encargara de realizar la operacion antes de cargar ningun otro programa.
Lo primero es hacer una funcion que compruebe si sobre alguno de los archivos existe ya alguna operacion pendiente ya que eso podria llevar a erroes. La funcion seria la siguiente:
Código Delphi
[-]
uses Registry;
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;
Una vez tomada esa precaucion podemos reemplzara un archivo por otro, o si el archivo de destino es una cadena vacia, borrar el original.
Código Delphi
[-]
procedure Reemplazar(Viejo, Nuevo: string);
begin
if Pendiente(Viejo) or Pendiente(Nuevo) then
Exit;
if Nuevo = '' then
begin
if FileExists(Viejo) then
if not DeleteFile(Viejo) then
MoveFileEx(PChar(Viejo), nil, MOVEFILE_DELAY_UNTIL_REBOOT or
MOVEFILE_REPLACE_EXISTING);
end
else
begin
if not MoveFileEx(PChar(Nuevo), PChar(Viejo), MOVEFILE_REPLACE_EXISTING) then
begin
MoveFileEx(PChar(Nuevo), PChar(Viejo), MOVEFILE_DELAY_UNTIL_REBOOT or
MOVEFILE_REPLACE_EXISTING)
end;
end;
end;
Ejemplos de uso:
Código Delphi
[-]
Reemplazar('Viejo.txt','Nuevo.txt');
Reemplazar(ParamStr(0),'');