• Delphi工程版本号修改工具


    自动修改某目录下符合条件的Delphi工程(dproj)版本号, 支持命令行调用
    支持通配符忽略文件

    -p [Path] 在[Path]路径下查询所有dproj文件(可以为空, 默认路径为程序当前路径)
    -v [Version] 将查询到的dproj文件中Base节点版本改为[Version]并删除其他节点版本信息(可以为空, 进入程序后输入)
    -i [File1,File2...]要忽略的文件, 支持? *的通配符, 忽略大小写, 包含路径, 不要包含扩展名, 如: workproject?
    -b 修改时备份原文件到文件所在路径的dproj_bak目录下(默认不备份)
    -ac 工作结束自动关闭程序(默认不关闭)

    已经编译完的程序放CSDN了, 不过有点坑, 提交的资源不能修改内容, 也不能修改下载积分(当初没看, 直接选了5分...呵呵)

    http://download.csdn.net/download/hskill/10120236

    下面直接给出源码, 是个控制台程序

    PS: 里面用到了QXML, 但是QXML会吧单引号转义, 不过不影响IDE的读取保存

    program dproj_Version;
    
    //  ***************************************************************************
    //
    //  版本: 1.0
    //  作者: 刘志林
    //  修改日期: 2017-11-15
    //  QQ: 17948876
    //  E-mail: lzl_17948876@hotmail.com
    //  博客: http://www.cnblogs.com/lzl_17948876/
    //
    //  !!! 若有修改,请通知作者,谢谢合作 !!!
    //
    //  ***************************************************************************
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils, System.Classes, System.IOUtils, System.Types, System.Masks,
      QXML, QString;
    
    function _GetXNode(AXNParent: TQXMLNode; AName: string; out AValue: string): TQXMLNode;
    begin
      Result := AXNParent.ItemByName(AName);
      if Result = nil then
        Result := AXNParent.Add(AName);
      AValue := Result.Text;
    end;
    
    type
      EInvalidVersion = Class(Exception);
    
      TVersion = record
      public
        procedure Init;
        function IsEmpty: Boolean;
        procedure FromString(AStr: string);
        function ToString(ADelimiter: Char = '.'): string;
    
        case Integer of
          0: (Data: array[0..3] of UInt32);
          1: (MajorVer, MinorVer, Release, Build: UInt32);
      end;
    
    { TVersion }
    
    procedure TVersion.FromString(AStr: string);
    var
      i: Integer;
    begin
      Init;
      with TStringList.Create do
      try
        Delimiter := '.';
        StrictDelimiter := True;
        DelimitedText := AStr;
        try
          if Count <> 4 then
            Abort;
          for i := 0 to 3 do
            Data[i] := StrToInt(Strings[i]);
          if IsEmpty then
            Abort;
        except
          Init;
          raise EInvalidVersion.Create(AStr + '不是有效的版本号');
        end;
      finally
        Free;
      end;
    end;
    
    procedure TVersion.Init;
    begin
      MajorVer := 0;
      MinorVer := 0;
      Release := 0;
      Build := 0;
    end;
    
    function TVersion.IsEmpty: Boolean;
    begin
      Result := Data[0] + Data[1] + Data[2] + Data[3] = 0;
    end;
    
    function TVersion.ToString(ADelimiter: Char = '.'): string;
    begin
      Result := Format('%1:d%0:s%2:d%0:s%3:d%0:s%4:d', [ADelimiter, Data[0], Data[1], Data[2], Data[3]])
    end;
    
    function _Compare(const AStr: string; const AL: array of string): Boolean;
    var
      i: Integer;
    begin
      Result := False;
      for i := Low(AL) to High(AL) do
      begin
        if CompareText(AStr, AL[i]) <> 0 then
          Continue;
        Result := True;
        Break;
      end;
    end;
    
    function IsIgnored(AName: string; const AIGList: TArray<string>): Boolean;
    var
      i: Integer;
    begin
      Result := False;
      for i := Low(AIGList) to High(AIGList) do
      begin
        if not MatchesMask(AName, AIGList[i]) then
          Continue;
        Result := True;
        Break;
      end;
    end;
    
    const
      _EXT = '.dproj';
    
    const
      Helps: array[0..4] of string = (
        '-p [Path] 在[Path]路径下查询所有dproj文件(可以为空, 默认路径为程序当前路径)',
        '-v [Version] 将查询到的dproj文件中Base节点版本改为[Version]并删除其他节点版本信息(可以为空, 进入程序后输入)',
        '-i [File1,File2...]要忽略的文件, 支持? *的通配符, 忽略大小写, 包含路径, 不要包含扩展名, 如: workproject?',
        '-b 修改时备份原文件到文件所在路径的dproj_bak目录下(默认不备份)',
        '-ac 工作结束自动关闭程序(默认不关闭)'
      );
    
    var
      nXDOC: TQXML;
      nXNRoot, nXN, nXNV: TQXMLNode;
      l, i, nParamIndex, nFileIndex, nXNIndex, nIKIndex: Integer;
      nStrs: TStringList;
      nName, nVersionStr, nPath, nFile, nStr, nPK: string;
      nIgnoredList: TArray<string>;
      nVersion, nOldVersion: TVersion;
      nFiles: TStringDynArray;
      nBackup, nAutoClose: Boolean;
    begin
      try
        { TODO -oUser -cConsole Main : Insert code here }
        ChDir(ExtractFilePath(ParamStr(0)));
    
        nPath := '.';
        nVersion.Init;
        SetLength(nIgnoredList, 0);
        nBackup := False;
        nAutoClose := False;
    
        nParamIndex := 1;
        while nParamIndex <= ParamCount do
        begin
          nStr := ParamStr(nParamIndex);
    
          l := nStr.Length;
          if not (nStr[1] in ['-', '/']) then
            Continue;
          nStr := Copy(nStr, 2, l - 1);
    
          if _Compare(nStr, ['p']) then {路径}
          begin
            nPath := ParamStr(nParamIndex + 1);
            Inc(nParamIndex, 2);
          end
          else if _Compare(nStr, ['v']) then {版本号}
          begin
            nVersionStr := ParamStr(nParamIndex + 1);
            Inc(nParamIndex, 2);
          end
          else if _Compare(nStr, ['i']) then {忽略的文件}
          begin
            with TStringList.Create do
            try
              StrictDelimiter := True;
              Delimiter := ',';
              DelimitedText := ParamStr(nParamIndex + 1);
              SetLength(nIgnoredList, Count);
              for i := 0 to Count - 1 do
                nIgnoredList[i] := '*' + ChangeFileExt(Strings[i], '') + _EXT;
            finally
              Free;
            end;
            Inc(nParamIndex, 2);
          end
          else if _Compare(nStr, ['b']) then {备份}
          begin
            nBackup := True;
            Inc(nParamIndex, 1);
          end
          else if _Compare(nStr, ['ac']) then {自动关闭}
          begin
            nAutoClose := True;
            Inc(nParamIndex, 1);
          end
          else if _Compare(nStr, ['h', '?', 'help']) then {帮助}
          begin
            for i := Low(Helps) to High(Helps) do
              Writeln(Helps[i]);
            Abort;
          end
          else
            Inc(nParamIndex, 1);
        end;
    
        if nPath = '' then
          raise Exception.Create('无效的路径');
        nPath := TPath.GetFullPath(nPath);
        if not DirectoryExists(nPath) then
          raise Exception.CreateFmt('"%s" 路径不存在', [nPath]);
    
        if nVersionStr = '' then
          Writeln('清输入版本号:')
        else
        try
          nVersion.FromString(nVersionStr);
        except
          on E: Exception do
            Writeln('错误: ' + E.Message);
        end;
    
        while nVersion.IsEmpty do
        begin
          Write('> ');
          Readln(nVersionStr);
          try
            nVersion.FromString(nVersionStr);
          except
            on E: Exception do
              Writeln('错误: ' + E.Message);
          end;
        end;
    
        Writeln('');
        Writeln('******** 开始处理 ********');
        Writeln(Format('目标目录: %s', [nPath]));
        Write('忽略的对象:');
        for i := Low(nIgnoredList) to High(nIgnoredList) do
          Write(Format(' "%s"', [nIgnoredList[i]]));
        Write(#10);
    
        nFiles := TDirectory.GetFiles(nPath, '*' + _EXT, TSearchOption.soAllDirectories);
    
        if Length(nFiles) = 0 then
          raise Exception.Create('待处理的文件数量为0');
    
    
        Writeln(Format('待处理文件数量: %d', [Length(nFiles)]));
        Writeln('');
    
        nXDOC := TQXML.Create;
        nStrs := TStringList.Create;
        try
          nStrs.Delimiter := ';';
          nStrs.StrictDelimiter := True;
    
          for nFileIndex := Low(nFiles) to High(nFiles) do
          begin
            if IsIgnored(nFiles[nFileIndex], nIgnoredList) then
            begin
              Writeln('* 忽略 ' + nFiles[nFileIndex]);
              Continue;
            end;
    
            Writeln(nFiles[nFileIndex]);
            try
              nOldVersion.Init;
              nXDOC.LoadFromFile(nFiles[nFileIndex]);
              nXNRoot := nXDOC.Items[0];
              for nXNIndex := 0 to nXNRoot.Count - 1 do
              begin
                nXN := nXNRoot.Items[nXNIndex];
                if nXN.Name <> 'PropertyGroup' then
                  Continue;
                if nXN.Attrs.AsString['Condition'] = '''$(Base)''!=''''' then
                begin
                  _GetXNode(nXN, 'VerInfo_MajorVer', nStr).Text := nVersion.MajorVer.ToString;
                  nOldVersion.MajorVer := StrToIntDef(nStr, 0);
                  _GetXNode(nXN, 'VerInfo_MinorVer', nStr).Text := nVersion.MinorVer.ToString;
                  nOldVersion.MinorVer := StrToIntDef(nStr, 0);
                  _GetXNode(nXN, 'VerInfo_Release', nStr).Text := nVersion.Release.ToString;
                  nOldVersion.Release := StrToIntDef(nStr, 0);
                  _GetXNode(nXN, 'VerInfo_Build', nStr).Text := nVersion.Build.ToString;
                  nOldVersion.Build := StrToIntDef(nStr, 0);
    
                  with _GetXNode(nXN, 'VerInfo_Keys', nStr) do
                  begin
                    nStrs.DelimitedText := Text;
                    for nIKIndex := 0  to nStrs.Count - 1 do
                    begin
                      nName := nStrs.KeyNames[nIKIndex];
                      if CompareText('FileVersion', nName) = 0 then
                        nStrs[nIKIndex] := 'FileVersion=' + nVersion.ToString;
                    end;
                    Text := nStrs.DelimitedText;
                  end;
    
                  _GetXNode(nXN, 'VerInfo_IncludeVerInfo', nStr).Text := True.ToString(TUseBoolStrs.True);
                end
                else
                begin
                  {删除其他版本信息}
                  nXN.Delete('VerInfo_MajorVer');
                  nXN.Delete('VerInfo_MinorVer');
                  nXN.Delete('VerInfo_Release');
                  nXN.Delete('VerInfo_Build');
                  nXN.Delete('VerInfo_Keys');
                end;
              end;
              if nBackup then
              begin
                nPath := ExtractFilePath(nFiles[nFileIndex]) + 'dproj_bak';
                ForceDirectories(nPath);
                nStr := nPath + ExtractFileName(nFiles[nFileIndex]) + '.#' + nOldVersion.ToString + '#.bak';
                if FileExists(nStr) then
                  TFile.Delete(nStr);
                TFile.Copy(nFiles[nFileIndex], nStr);
              end;
              nXDOC.SaveToFile(nFiles[nFileIndex], TTextEncoding.teUTF8, True, False, True);
            except
              on E: Exception do
                Writeln('错误: ' + E.Message);
            end;
          end;
        finally
          nStrs.Free;
          nXDOC.Free;
        end;
        Writeln('');
        Writeln('******** 处理完毕 ********')
      except
        on E: EAbort do;
        on E: Exception do
        begin
          Writeln('错误: ', E.Message);
          nAutoClose := False;
        end;
      end;
      if not nAutoClose then
      begin
        Writeln('');
        Writeln('按任意键关闭');
        Read(nStr);
      end;
    end.
  • 相关阅读:
    ubuntu 构建Xilinx交叉编译环境
    codeSourcery交叉编译环境
    ZYNQ学习之路1. Linux最小系统构建
    静态代码块的执行顺序
    storm maven-shade-plugin
    spring 3.2.7 applicationContext.xml
    ZipUtils
    成员内部类
    jetty jndi数据源
    applicationContext中普通数据源不用jndi数据源
  • 原文地址:https://www.cnblogs.com/lzl_17948876/p/7840383.html
Copyright © 2020-2023  润新知