Search code examples
delphiguiddelphi-xe3msbuild-projectreference

How to employ DPROJ <ProjectGUID> within Delphi code?


I want to use a GUID to uniquely identify my Application and to get at this value from within the code. I see that there is a GUID that would be ideal in the DPROJ:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProjectGuid>{D4DB842C-FB4C-481B-8952-77DA04E37102}</ProjectGuid>

Does this get into the exe anywhere, eg as a resource? If not, what is the neatest way of linking in this GUID value into my exe file and reading it in code. The above GUID resides in a dedicated text file and is pasted into the DPROJ with my DprojMaker tool, so I can INCLUDE it in anything you might suggest. Thanks


Solution

  • AFAIK the <ProjectGUID> is not embedded in the Exe file, but you can create an application to read the project guid and insert as a resource in your exe.

    Check this sample app which read a file a create/updates a resource in a exe.

    program UpdateResEXE;
    
    {$APPTYPE CONSOLE}
    
    uses
      Classes,
      Windows,
      SysUtils;
    
    //you can improve this method to read the ProjectGUID value directly from the dproj file using XML.
    procedure UpdateExeResource(Const Source, ResourceName, ExeFile:string);
    var
      LStream    : TFileStream;
      hUpdate    : THANDLE;
      lpData     : Pointer;
      cbData     : DWORD;
    begin
      LStream := TFileStream.Create(Source,fmOpenRead or fmShareDenyNone);
      try
        LStream.Seek(0, soFromBeginning);
        cbData:=LStream.Size;
        if cbData>0 then
        begin
          GetMem(lpData,cbData);
          try
            LStream.Read(lpData^, cbData);
            hUpdate:= BeginUpdateResource(PChar(ExeFile), False);
            if hUpdate <> 0 then
              if UpdateResource(hUpdate, RT_RCDATA, PChar(ResourceName),0,lpData,cbData) then
              begin
                if not EndUpdateResource(hUpdate,FALSE) then RaiseLastOSError
              end
              else
              RaiseLastOSError
            else
            RaiseLastOSError;
          finally
            FreeMem(lpData);
          end;
        end;
      finally
        LStream.Free;
      end;
    end;
    
    begin
      try
        if ParamCount<>3 then
        begin
         Writeln('Wrong parameters number');
         Halt(1);
        end;
        Writeln(Format('Adding/Updating resource %s in %s',[ParamStr(2), ParamStr(3)]));
        UpdateExeResource( ParamStr(1), ParamStr(2), ParamStr(3));
        Writeln('Done');
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end. 
    

    Now from your app, you can use the Post build events to call this application on this way

    "C:\The path where is the tool goes here\UpdateResEXE.exe"  "C:\The path of the file which contains the ProjectGUID goes here\Foo.txt"  Project_GUID  "$(OUTPUTPATH)"
    

    And use like so :

    {$APPTYPE CONSOLE}
    
    uses
      Windows,
      Classes,
      System.SysUtils;
    
    
    function GetProjectGUID : string;
    var
      RS: TResourceStream;
      SS: TStringStream;
    begin
      RS := TResourceStream.Create(HInstance, 'Project_GUID', RT_RCDATA);
      try
        SS:=TStringStream.Create;
        try
          SS.CopyFrom(RS, RS.Size);
          Result:= SS.DataString;
        finally
         SS.Free;
        end;
      finally
        RS.Free;
      end;
    end;
    
    
    begin
      try
        Writeln(Format('Project GUID %s',[GetProjectGUID]));
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      readln;
    end.