怎么不行呢?我们的系统一直用这个方法(3years),检测到新版本后(ftp下载ver文件),ftp下载程序,如果是自己的运行程序(exe/dll),就直接试图renmae覆盖,覆盖不成功,如果是主程序模块就用另外一个程序来更名,如果是别人的东西,可以用下面的函数,可能需要重启动才能更新: T_WindowsVerType = (wv31Win32,wvWin9x,wvWinNT,wvWinNT351,wvUnidentified); T_WinRunType = (wrRun, wrRunOnce, wrRunService, wrRunServiceOnce {Only in Win9x} );function RegisterWinRun (eRun: T_WinRunType; sIdent: string; const sValue: string; bIdentUnique: Boolean): Boolean; var cReg: TRegistry; I: LongInt; sSuffix: string; begin Result := FALSE; case eRun of wrRun: sSuffix := SKEY_RUN; wrRunOnce: sSuffix := SKEY_RUN_ONCE; wrRunService: sSuffix := SKEY_RUN_SERVICE; wrRunServiceOnce: sSuffix := SKEY_RUN_SERVICE_ONCE; else Exit; end; cReg := TRegistry.Create; with cReg do try RootKey := HKEY_LOCAL_MACHINE; if (OpenKey(KEY_WIN_CURVER+'\'+sSuffix, TRUE)) then begin // Create a unique ident if necessary by attaching a numeric suffix sSuffix := ''; I := 0; while bIdentUnique and ValueExists(sIdent+sSuffix) do begin Inc(I); sSuffix := IntToStr(I); end; try WriteString(sIdent+sSuffix,sValue); except Exit; end; LazyWrite := False; CloseKey; Result := True; end; finally Free; end; end;function GetWindowsVerType(psVer: PString): T_WindowsVerType; var rVI: TOSVersionInfo; sVer: string; begin Result := wvUnidentified; rVI.dwOSVersionInfoSize := sizeof(TOSVersionInfo); if (not GetVersionEx (rVI)) then Exit; sVer := IntToStr (rVI.dwMajorVersion)+'.'+IntToStr(rVI.dwMinorVersion); if psVer<>nil then psVer^ := sVer; case rVI.dwPlatformId of VER_PLATFORM_WIN32s: Result := wv31Win32; VER_PLATFORM_WIN32_WINDOWS: Result := wvWin9x; VER_PLATFORM_WIN32_NT: begin if (Pos ('3.5', sVer) = 1) then Result := wvWinNT351 else Result := wvWinNT; end; else Result := wvUnidentified; end; end;function ExtraRen (sFrom, sTo: string): Integer; const WIN_INIT_INI = 'wininit.ini'; REN_SEC = 'rename'; NULL_FILE = 'nul'; var yFrom, yTo: array[0..MAX_PATH] of Char; T: System.Text; sBatFile: string; begin Result := -1; sFrom := ExtractShortPathName (sFrom); sTo := ExtractShortPathName (sTo); StrPCopy(yTo, sTo); StrPCopy(yFrom, sFrom); case GetWindowsVerType of wvWin9x: begin // !!!!! only in Win9x // Update wininit.ini here // Rename new WritePrivateProfileString(REN_SEC,yTo,yFrom,WIN_INIT_INI); Result := 1; end; else // Try to move it again (in NT may work) if (not MoveFileEx(yFrom,yTo,MOVEFILE_DELAY_UNTIL_REBOOT)) then begin // OK, let me try a bat file as a "runonce service" if (GenTempFileName('','UPD',0,sBatFile,TRUE)<=0) then Exit; sBatFile := ExtractShortPathName (sBatFile); sBatFile := ChangeFileExt (sBatFile,'.bat'); { cBatLines := TStringList.Create; with cBatLines do try Add('attrib -r -s -h '+sTo); Add('erase '+sTo); Add('move '+sFrom+' '+sTo); Add('ren '+sFrom+' '+sTo); SaveToFile(sBatFile); finally Free; end;} System.AssignFile(T, sBatFile); {$I-} System.Rewrite(T); Writeln(T, 'attrib -r -s -h '+sTo); Writeln(T, 'erase '+sTo); Writeln(T, 'move '+sFrom+' '+sTo); Writeln(T, 'ren '+sFrom+' '+sTo); CloseFile(T); {$I+} if (IOResult=0) then if (RegisterWinRun(wrRunOnce, 'EDUPD', sBatFile, True)) then Result := 1; end else Result := 0; end; end;
T_WinRunType = (wrRun, wrRunOnce,
wrRunService, wrRunServiceOnce {Only in Win9x}
);function RegisterWinRun (eRun: T_WinRunType; sIdent: string;
const sValue: string; bIdentUnique: Boolean): Boolean;
var
cReg: TRegistry;
I: LongInt;
sSuffix: string;
begin
Result := FALSE;
case eRun of
wrRun: sSuffix := SKEY_RUN;
wrRunOnce: sSuffix := SKEY_RUN_ONCE;
wrRunService: sSuffix := SKEY_RUN_SERVICE;
wrRunServiceOnce: sSuffix := SKEY_RUN_SERVICE_ONCE;
else Exit;
end; cReg := TRegistry.Create;
with cReg do
try
RootKey := HKEY_LOCAL_MACHINE; if (OpenKey(KEY_WIN_CURVER+'\'+sSuffix, TRUE)) then
begin
// Create a unique ident if necessary by attaching a numeric suffix
sSuffix := '';
I := 0;
while bIdentUnique and ValueExists(sIdent+sSuffix) do
begin
Inc(I);
sSuffix := IntToStr(I);
end;
try
WriteString(sIdent+sSuffix,sValue);
except
Exit;
end;
LazyWrite := False;
CloseKey;
Result := True;
end;
finally
Free;
end;
end;function GetWindowsVerType(psVer: PString): T_WindowsVerType;
var
rVI: TOSVersionInfo;
sVer: string;
begin
Result := wvUnidentified;
rVI.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
if (not GetVersionEx (rVI)) then Exit;
sVer := IntToStr (rVI.dwMajorVersion)+'.'+IntToStr(rVI.dwMinorVersion);
if psVer<>nil then psVer^ := sVer;
case rVI.dwPlatformId of
VER_PLATFORM_WIN32s: Result := wv31Win32;
VER_PLATFORM_WIN32_WINDOWS: Result := wvWin9x;
VER_PLATFORM_WIN32_NT:
begin
if (Pos ('3.5', sVer) = 1) then
Result := wvWinNT351
else
Result := wvWinNT;
end;
else
Result := wvUnidentified;
end;
end;function ExtraRen (sFrom, sTo: string): Integer;
const
WIN_INIT_INI = 'wininit.ini';
REN_SEC = 'rename';
NULL_FILE = 'nul';
var
yFrom, yTo: array[0..MAX_PATH] of Char;
T: System.Text;
sBatFile: string;
begin
Result := -1;
sFrom := ExtractShortPathName (sFrom);
sTo := ExtractShortPathName (sTo);
StrPCopy(yTo, sTo);
StrPCopy(yFrom, sFrom);
case GetWindowsVerType of
wvWin9x:
begin
// !!!!! only in Win9x
// Update wininit.ini here
// Rename new
WritePrivateProfileString(REN_SEC,yTo,yFrom,WIN_INIT_INI);
Result := 1;
end;
else
// Try to move it again (in NT may work)
if (not MoveFileEx(yFrom,yTo,MOVEFILE_DELAY_UNTIL_REBOOT)) then
begin
// OK, let me try a bat file as a "runonce service"
if (GenTempFileName('','UPD',0,sBatFile,TRUE)<=0) then Exit;
sBatFile := ExtractShortPathName (sBatFile);
sBatFile := ChangeFileExt (sBatFile,'.bat');
{ cBatLines := TStringList.Create;
with cBatLines do
try
Add('attrib -r -s -h '+sTo);
Add('erase '+sTo);
Add('move '+sFrom+' '+sTo);
Add('ren '+sFrom+' '+sTo);
SaveToFile(sBatFile);
finally
Free;
end;} System.AssignFile(T, sBatFile);
{$I-}
System.Rewrite(T);
Writeln(T, 'attrib -r -s -h '+sTo);
Writeln(T, 'erase '+sTo);
Writeln(T, 'move '+sFrom+' '+sTo);
Writeln(T, 'ren '+sFrom+' '+sTo);
CloseFile(T);
{$I+}
if (IOResult=0) then
if (RegisterWinRun(wrRunOnce, 'EDUPD', sBatFile, True)) then
Result := 1;
end else Result := 0;
end;
end;