Frage

Ich habe einige Code, mit D7 fein kompiliert doch irgendwie D2010. Offensichtlich ist es eine Unicode-Ausgabe:

Der Compiler-Fehler ist: E2251 Doppeldeutiger überladener Aufruf von 'StrPas'

Hier ist die ganze Prozedur:

procedure GetVersionInfo;
type
  PLangCharSetInfo = ^TLangCharSetInfo;
  TLangCharSetInfo = record
    Lang: Word;
    CharSet: Word;
  end;
var
  FileName: array [0..260] of Char;
  SubBlock: array [0..255] of Char;
  VerHandle: Cardinal;
  Size: Word;
  Buffer: Pointer;
  Data: Pointer;
  DataLen: LongWord;
  LangCharSetInfo: PLangCharSetInfo;
  LangCharSetString: string;
begin
  LabelComments.Caption := 'No version information for this program is available!';
  {Get size and allocate buffer for VerInfo}
  if GetModuleFileName(hInstance, FileName, SizeOf(FileName)) > 0 then
  begin
    Size := GetFileVersionInfoSize(FileName, VerHandle);
    if Size > 0 then
    begin
      GetMem(Buffer, Size);
      try
        if GetFileVersionInfo(FileName, VerHandle, Size, Buffer) then
        begin
          {Query first language and that language blocks version info}
          if VerQueryValue(Buffer, '\VarFileInfo\Translation', Pointer(LangCharSetInfo), DataLen) then
          begin
            LangCharSetString := IntToHex(LangCharSetInfo^.Lang, 4) +
                                 IntToHex(LangCharSetInfo^.CharSet, 4);
            if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\ProductName'), Data, DataLen) then
            begin
              LabelProductName.Caption := StrPas(Data);
              Caption := LabelProductName.Caption;
            end;
            if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\FileVersion'), Data, DataLen) then
              LabelVersion.Caption := StrPas(Data);
            if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\LegalCopyright'), Data, DataLen) then
              LabelCopyright.Caption := StrPas(Data);
            if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\Comments'), Data, DataLen) then
              LabelComments.Caption := StrPas(Data);
          end;
        end;
      finally
        FreeMem(Buffer, Size);
      end;
    end
  end;
end;

Der Doc für StrPas sagt

function StrPas(const Str: PAnsiChar): AnsiString; overload;

Diese Funktion wird fasor Rückwärtskompatibilität zur Verfügung gestellt nur. Um einen nullterminierten String in einen Ansistring zu konvertieren oder native Delphi-String, verwenden Sie eine Typumwandlung oder ein signment.

Die Frage ist also sollte ich entfernen Sie alle Anrufe an StrPas? Die einzige Art, wie ich dies machen zu kompilieren ist ein Hardcast zu Pansi char zu tun:

LabelProductName.Caption := StrPas(PAnsiChar(Data));
War es hilfreich?

Lösung

Sie bearbeiten Ihre Frage mit einer vollen Compilierung Probe. Gut!

Es ist wahrscheinlich die am einfachsten, wenn Sie die JCL für diese verwenden würden (Link unten). Dann könnten Sie TJclFileVersionInfo, das tut alles, was Sie wollen, und berücksichtigt einige esoterische Dinge, die die Version halten kann.

Dann ist Ihre Business-Logik würde so etwas wie dieses werden:

function GetStringFileInfo(
  const Buffer: Pointer; const SubBlock: PChar;
  const LangCharSetString: string; const Kind: string): string;
var
  QueryString: string;
  Data: Pointer;
  DataCharacters: PChar absolute Data;
  DataLen: LongWord;
begin
  Result := '';
  QueryString := Format('%s\StringFileInfo\%s\%s', [SubBlock, LangCharSetString, Kind]);
  if VerQueryValue(Buffer, PChar(QueryString), Data, DataLen) then
    Result := StrPas(DataCharacters);
end;

procedure GetVersionInfoStrings(var Comments: string; var ProductName: string;
  var Caption: string; var Version: string; var Copyright: string);
type
  PLangCharSetInfo = ^TLangCharSetInfo;
  TLangCharSetInfo = record
    Lang: Word;
    CharSet: Word;
  end;
var
  FileName: array [0 .. 260] of Char;
  SubBlock: array [0 .. 255] of Char;
  VerHandle: Cardinal;
  Size: Word;
  Buffer: Pointer;
  Data: Pointer;
  DataCharacters: PChar absolute Data;
  DataLen: LongWord;
  LangCharSetInfo: PLangCharSetInfo;
  LangCharSetString: string;
begin
  Comments := 'No version information for this program is available!';
  { Get size and allocate buffer for VerInfo }
  if GetModuleFileName(hInstance, FileName, SizeOf(FileName)) > 0 then
  begin
    Size := GetFileVersionInfoSize(FileName, VerHandle);
    if Size > 0 then
    begin
      GetMem(Buffer, Size);
      try
        if GetFileVersionInfo(FileName, VerHandle, Size, Buffer) then
        begin
          { Query first language and that language blocks version info }
          if VerQueryValue(Buffer, '\VarFileInfo\Translation', Pointer
              (LangCharSetInfo), DataLen) then
          begin
            LangCharSetString :=
              IntToHex(LangCharSetInfo^.Lang, 4) +
              IntToHex(LangCharSetInfo^.CharSet, 4);
            ProductName := GetStringFileInfo(Buffer, SubBlock, LangCharSetString, 'ProductName');
            Version := GetStringFileInfo(Buffer, SubBlock, LangCharSetString, 'FileVersion');
            Copyright := GetStringFileInfo(Buffer, SubBlock, LangCharSetString, 'LegalCopyright');
            Comments := GetStringFileInfo(Buffer, SubBlock, LangCharSetString, 'Comments');
            Caption := ProductName;
          end;
        end;
      finally
        FreeMem(Buffer, Size);
      end;
    end
  end;
end;

Und in der Benutzeroberfläche, müssen Sie Ihre Business-Logik nennen, und setzen die Ergebnisse in die verschiedenen Kontrollen.

- jeroen

Antwort vor edit:

Ihr Code kompiliert nicht wie es ist, so ohne mehr Kontext, ist es schwer, Ihre Suche zu beantworten.

Was sind die Datentypen von Buffer, Subblock, LongCharSetString und DataLen? Wie haben Sie Buffer erhalten?

Sind Daten wirklich bedeuten ein Zeiger auf (Ansi oder Unicode) Zeichen zu sein? Sollte es nicht letztlich seinen Hinweis auf PVSFixedFileInfo?

(A-Seite Frage: warum innerhalb der Benutzeroberfläche Ihre Business-Logik ist, wenn Sie Ihre Logik in eine separate Funktion irgendwo geteilt hatte, dann würden Sie wahrscheinlich eine Kompilierung Routine haben, die als Basis für Ihre Frage gedient haben könnte, die Macht. hat die Frage an erster Stelle beantwortet).

Für Fragen wie das Ihre, ich nehme in der Regel einen Blick auf Einheiten in der JCL oder < a href = "http://jvcl.delphi-jedi.org/" rel = "nofollow noreferrer"> JVCL . Sie haben viel Mühe in denen gestellt werden Unicode-kompatibel.

Ihr Code, die VerQueryValue ist dies ein in Einheit JclFileUtils, Methode VersionFixedFileInfo verwenden:

// Fixed Version Info routines
function VersionFixedFileInfo(const FileName: string; var FixedInfo: TVSFixedFileInfo): Boolean;
var
  Size, FixInfoLen: DWORD;
  Handle: THandle;
  Buffer: string;
  FixInfoBuf: PVSFixedFileInfo;
begin
  Result := False;
  Size := GetFileVersionInfoSize(PChar(FileName), Handle);
  if Size > 0 then
  begin
    SetLength(Buffer, Size);
    if GetFileVersionInfo(PChar(FileName), Handle, Size, Pointer(Buffer)) and
      VerQueryValue(Pointer(Buffer), DirDelimiter, Pointer(FixInfoBuf), FixInfoLen) and
      (FixInfoLen = SizeOf(TVSFixedFileInfo)) then
    begin
      Result := True;
      FixedInfo := FixInfoBuf^;
    end;
  end;
end;

Hope this wird gestartet Sie Ihre Lösung zu finden.

- jeroen

Andere Tipps

StrPas hat sich seit Delphi 1, erforderlich gewesen, da sie die Delphi-Compiler verändert die Zeichenfolge richtig ohne einen Funktionsaufruf zu konvertieren. Siehe: http: // coding.derkeiler.com/Archive/Delphi/borland.public.delphi.language.objectpascal/2004-01/1793.html

So weisen Sie einfach es wie folgt:

LabelProductName.Caption := PAnsiChar(Data);

Und ja, sollten Sie alle Anrufe an StrPas entfernen. Es kann nicht helfen, und können Sie nur in Schwierigkeiten in D2010 erhalten.

Ich denke, das Hauptproblem dabei ist, dass Daten, die als Pointer eingegeben werden und keine PChar.

Auf jeden Fall die Besetzung macht die ganze Arbeit für Sie also, wenn Sie den Code sowieso ändern müssen, die Besetzung nur so gut wie der Funktionsaufruf ist.

Lassen Sie mich anders formulieren. Wenn Sie die Zeichenfolge in einem PChar oder PAnsiChar haben, ist es zuweisungskompatibel mit String. Der Grund, warum Sie benötigen ein gegossenes hier ist, dass man es als Pointer eingegeben hat.

Konvertieren PAnsiChar zu Ansistring und dann auf Unicode-String:

LabelProductName.Caption := String(AnsiString(PAnsiChar(Data)));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top