用另外一个程序来做,下载新程序后(须做校验)启动它,等待并通信传递参数(包括新程序路径、当前程序路径参数、event handle等),退出,
更新进程等主程序退出(等待),删除、改名,重启动主程序。

解决方案 »

  1.   

    怎么不行呢?我们的系统一直用这个方法(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;