Change dproj file and product version

by Dec 4, 2015

If you have a project with automatic builds is posible that you want change the File/Product version of the file.

Using the code below you can create a console application for to modify these values easily.

program ChangeVersion;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  UnParseDproj in 'UnParseDproj.pas';

procedure ChangeDprojVersion;
var
  DprojParser : TDprojParser;
begin
  DprojParser := TDprojParser.Create;
  try
    DprojParser.DprojFile := ParamStr(1);
    DprojParser.VersionString := ParamStr(2);
    DprojParser.ChangeVersion;
  finally
    DprojParser.Free;
  end;
end;

begin
  try
    if ParamCount < 2 then
    begin
      WriteLn('Wrong syntax. Usage:');
      WriteLn('ChangeVersion "Delphi project file (dproj)" "Version string(x.x.x.x)"');
    end
  else
    begin
      ChangeDprojVersion;
    end;

  except
    on E: Exception do
      WriteLn(E.ClassName, ': ', E.Message);
  end;

end.
unit UnParseDproj;

interface

uses
  System.Sysutils,
  Winapi.Ole2,
  Xml.XMLIntf,
  Xml.XMLDoc;

type

  TDprojParser = class
    private
      FXMLDocument: IXMLDocument;
      FDprojFile: string;
      FVersionString: string;
      procedure SetDprojFile(const Value: string);
      procedure SetVersionString(const Value: string);
    public
      property DprojFile: string read FDprojFile write SetDprojFile;
      property VersionString: string read FVersionString write SetVersionString;
      procedure ChangeVersion;
      constructor Create;
      destructor Destroy; override;
  end;

implementation

{ TDprojParser }

procedure TDprojParser.ChangeVersion;
var
  Project, Node, VerInfo_Keys: IXMLNode;
  I, J, K: Integer;
  Keys_String: String;
  Keys : TArray<string>;
  Version: TArray<string>;
begin
  try
    FXMLDocument.LoadFromFile(DprojFile);
    Project := FXMLDocument.ChildNodes.First;
    J := Project.ChildNodes.Count - 1;
    for I := 0 to J do
    begin
      Node := Project.ChildNodes.Nodes[I];
      VerInfo_Keys := Node.ChildNodes.FindNode('VerInfo_Keys');
      if VerInfo_Keys <> nil then
        begin
        Keys_String := VerInfo_Keys.NodeValue;
        Keys := Keys_String.Split([';']);
        for K := 0 to Length(Keys) - 1  do
          begin
            Version := Keys[K].Split(['=']);
            if Version[0]= 'FileVersion' then
              Keys[K] := 'FileVersion='+FVersionString;
            if Version[0]= 'ProductVersion' then
              Keys[K] := 'ProductVersion='+FVersionString;
          end;
        Keys_String := '';
        for K := 0 to Length(Keys) - 1 do
          Keys_String := Keys_String + Keys[K] + ';';
        Keys_String := Keys_String.Substring(0,Keys_String.Length -1);
        VerInfo_Keys.NodeValue := Keys_String;
        end;
    end;
    FXMLDocument.SaveToFile(Dprojfile);
    WriteLn('dproj file changed');
  except
    on E: Exception do
      WriteLn(E.ClassName + ':' + E.Message)
  end;
end;

constructor TDprojParser.Create;
begin
  FXMLDocument := TXMLDocument.Create(nil);
  FXMLDocument.ParseOptions := FXMLDocument.ParseOptions+[poPreserveWhiteSpace];
end;

destructor TDprojParser.Destroy;
begin
end;

procedure TDprojParser.SetDprojFile(const Value: string);
begin
  FDprojFile := Value;
end;

procedure TDprojParser.SetVersionString(const Value: string);
begin
  FVersionString := Value;
end;

initialization
  CoInitialize(nil);

end.