Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Erweiterte Dateiinformationen schreiben (https://www.delphipraxis.net/20244-erweiterte-dateiinformationen-schreiben.html)

Luckie 15. Apr 2004 02:43


Erweiterte Dateiinformationen schreiben
 
Unter NTFS Dateisystemen kann man noch zusätzlich Dateiinformnationen zu den Dateien Hinterlegen. Zum Beispiel ein Kommentar oder den Autor und sonstige Informationen. Im Internet habe ich jetzt schon Code gefunden diese auszulesen:
http://www.howtodothings.com/showart...sp?article=447
Nur leider fehlende so ziemllich alle Kommentare. Zum Laufen habe ich ihn gebracht nur verstehe ich nicht, was da passiert. Wenn mir da mal jemand auf die Sprünge helfen könnte.

Desweiteren will ich mit meinem Programm diese Infos setzen können. Also ich gebe die Datei an, welche Information ich setzten möchte und einen String mit der Information. Leider habe ich davon keinen Plan, wie ich das hinbekommen könnte.

Habe was gefunden: http://www.delphipages.com/news/detaildocs.cfm?ID=104

Aber was da genau passiert, hätte ich trotzdem gerne erklärt bekommen. :gruebel:

Hier nun meine Umsetzung des Codes: FileComment. Ich habe mich dabei auf das Setzen und Auslesen des Kommentares beschränkt.

mumu 15. Apr 2004 12:51

Re: Erweiterte Dateiinformationen schreiben
 
was willste denn genau wissen? welche zeilen verstehst du nicht? ich find den code eigentlich nicht so schwer.

Luckie 15. Apr 2004 12:57

Re: Erweiterte Dateiinformationen schreiben
 
Wie wäre es mit denen hier:
Delphi-Quellcode:
  OleCheck(StgOpenStorageEx(PWideChar(FileName),
  STGM_READ or STGM_SHARE_DENY_WRITE,
  STGFMT_FILE,
  0, nil, nil, @IID_IPropertySetStorage, stg));

  PropSetStg := Stg as IPropertySetStorage;

  OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
     STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));

  OleCheck(PropStg.Enum(PropEnum));
Und der Schleife:
Delphi-Quellcode:
  hr := PropEnum.Next(1, PropStat, nil);
   while hr = S_OK do
   begin
     inc(I);
     SetLength(PropSpec,I);
     PropSpec[i-1].ulKind := PRSPEC_PROPID;
     PropSpec[i-1].propid := PropStat.propid;
     hr := PropEnum.Next(1, PropStat, nil);
  end;

mirage228 15. Apr 2004 13:06

Re: Erweiterte Dateiinformationen schreiben
 
Zitat:

Zitat von Luckie
Wie wäre es mit denen hier:
Delphi-Quellcode:
  OleCheck(StgOpenStorageEx(PWideChar(FileName),
  STGM_READ or STGM_SHARE_DENY_WRITE,
  STGFMT_FILE,
  0, nil, nil, @IID_IPropertySetStorage, stg));

  PropSetStg := Stg as IPropertySetStorage;

  OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
     STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));

  OleCheck(PropStg.Enum(PropEnum));
Und der Schleife:
Delphi-Quellcode:
  hr := PropEnum.Next(1, PropStat, nil);
   while hr = S_OK do
   begin
     inc(I);
     SetLength(PropSpec,I);
     PropSpec[i-1].ulKind := PRSPEC_PROPID;
     PropSpec[i-1].propid := PropStat.propid;
     hr := PropEnum.Next(1, PropStat, nil);
  end;

Hi,
hier einige Erklärungen ;)
  • OleCheck löst eine EOleSysError-Exception aus, wenn der Ergebniscode einen Fehler anzeigt. (siehe OH)
  • PropSetStg := Stg as IPropertySetStorage -> Stg wird zum Interface IPropertySetStorage gecastet (ist wahrs. vorher IInterface) ("To get a pointer to the NTFS implementation of IPropertySetStorage, we have to call the StgCreateStorageEx function:")
  • Die Schleife wird sooft wiederholt, bis PropEnum.Next nicht Ok zurückgibt, sprich es keine Eigenschaften mehr zu setzten gibt.

mfG
mirage228

Luckie 15. Apr 2004 13:07

Re: Erweiterte Dateiinformationen schreiben
 
So weit bin ich auch schon gekoommen. Das reicht mir aber nicht.

mirage228 15. Apr 2004 13:14

Re: Erweiterte Dateiinformationen schreiben
 
Zitat:

Zitat von Luckie
So weit bin ich auch schon gekoommen. Das reicht mir aber nicht.

Was möchtest du denn noch wissen? Die Deklaration der Interface?

Bei OleCheck und der Schleife gibt es aber nicht mehr allzu viel zu erklären.

mfG
mirage228

schitho 15. Apr 2004 21:23

Re: Erweiterte Dateiinformationen schreiben
 
Hi,

ich hab mir die Unit1 von FileComment angesehen.

So jetzt kommen ein paar typische Anfängerfragen (ersuche schon jetzt dafür um Nachsicht): :oops:

Mit

Delphi-Quellcode:
SetFileSummaryInfo('c:\tmp\test.txt,PID_COMMENTS,'Hier könnte ein Kommentar stehen')
setze ich einen Kommentar.

Nun zu meinen ersten Fragen:
  • Die Funktion liefert einen Rückwert. Welche Information beinhaltet dieser Rückgabewert? Wann war alles OK?
  • Wie rufe ich die Funktion auf, wenn ich in mehrere Felder schreiben möchte (z.B. Kommentar und Autor)?
  • Ich hab keine Möglichkeit gefunden die Quelle und Revisonsnummer zu ändern. Geht das wirklich nicht?

Nun zum Auslesen:

Mit
Delphi-Quellcode:
GetFileSummaryInfo('c:\tmp\test.txt')
liefert den Kommentar in einem String zurück.
  • Wie kann man die anderen Felder auslesen?
Wär super-nett, wenn Ihr mir da weiterhelfen könntet.

Danke!

Gruß
Thomas

Luckie 15. Apr 2004 21:50

Re: Erweiterte Dateiinformationen schreiben
 
Delphi-Quellcode:
function SetFileSummaryInfo(const FileName: WideString; PID_InfoType: Cardinal;
  InfoStr: string): DWORD;
Ich dachte das wäre klar. Wenn du gibst mit PID_Infotype (mir ist nichts besseres um halb fünf morgens eingefallen) das Feld an in das du schreiben willst. Mögliche Werte:
PID_AUTHOR
PID_TITLE
PID_SUBJECT
PID_KEYWORDS
PID_COMMENTS

Sie liefert null wenn alles geklappt hat oder wenn was nicht geklappt hatt sollte sie den letzten Systemfehler des Prozesses zurückgeben.

In mehrer Felder schreiben geht nicht, entweder du schreibst sie dir selber um, dass sie es kann oder rufst sie entsprechend oft nacheinander auf. Ich habe daraurf verzichtet mir diese Arbeit zu machen, weil es mir von Anfang an eigentlich nur um den Kommentar ging. (Alle anderen Felder erscheinen mir sowieso unwichtig.)

Auslesen? Na kuck es dir an:
Delphi-Quellcode:
S := PropVariant[k].pwszVal;
if PropSpec[k].propid = PID_COMMENTS then
  Result := S;
Hier lasse ich mir nur den Wert von s zurückgeben wenn die PropID PID_COMMENTS entspricht. So, denk nach und mach was draus. ;)

schitho 15. Apr 2004 22:50

Re: Erweiterte Dateiinformationen schreiben
 
Hallo Luckie!

Danke für Deine geduldige Antwort!

Zitat:

Zitat von Luckie
Ich dachte das wäre klar. Wenn du gibst mit PID_Infotype (mir ist nichts besseres um halb fünf morgens eingefallen) das Feld an in das du schreiben willst. Mögliche Werte:
PID_AUTHOR
PID_TITLE
PID_SUBJECT
PID_KEYWORDS
PID_COMMENTS

Sie liefert null wenn alles geklappt hat oder wenn was nicht geklappt hatt sollte sie den letzten Systemfehler des Prozesses zurückgeben.

In mehrer Felder schreiben geht nicht, entweder du schreibst sie dir selber um, dass sie es kann oder rufst sie entsprechend oft nacheinander auf. Ich habe daraurf verzichtet mir diese Arbeit zu machen, weil es mir von Anfang an eigentlich nur um den Kommentar ging. (Alle anderen Felder erscheinen mir sowieso unwichtig.)

So hätte ich es eh auch verstanden. Doch irgendwie funktioniert das nicht. Sobald ich einen Wert (z.B. PID_COMMENTS) schreibe funktioniert das. Schreib ich aber noch einen (z.B. PID_TITLE), indem ich die Funktion nochmals aufrufe, verschwindet der vorige Eintrag wieder. :cry:

Somit funktioniert der mehrmalige Aufruf nicht (zumindest bei mir).

Außerdem hab ich keine Möglichkeit gefunden, wie ich das Feld Revisionsnummer und Quelle mit Daten füllen kann. :?

Zitat:

Zitat von Luckie
Auslesen? Na kuck es dir an:
Delphi-Quellcode:
S := PropVariant[k].pwszVal;
if PropSpec[k].propid = PID_COMMENTS then
  Result := S;
Hier lasse ich mir nur den Wert von s zurückgeben wenn die PropID PID_COMMENTS entspricht. So, denk nach und mach was draus. ;)

Ups. Das hab ich übersehen. :oops:

Danke für Deine prompte Antwort.

Gruß
Thomas

MathiasSimmack 27. Apr 2004 20:06

Re: Erweiterte Dateiinformationen schreiben
 
Ich muss mal diesen Beitrag aus der Versenkung holen, weil mich ein paar Dinge interessieren -

Ich nehme mal an, dass du, @Luckie, die Funktion "GetFileSummaryInfo" so beschnitten hast, dass sie grundsätzlich den Kommentar zurückliefert. Ich wollte mir auch andere Werte anzeigen lassen und musste die Funktion dafür erst einmal öffnen. Dabei ist mir aufgefallen, dass die Funktion nichts anzeigt, wenn man die gewünschte Eigenschaft vorher mit Bordmitteln (sprich: Rechtsklick auf die Datei -> Eigenschaften -> Dateiinfos) setzt.

Erst wenn ich bspw. mit dem Programm den Kommentar eintragen lasse, wird er hinterher von "GetFileSummaryInfo" auch angezeigt. Der Witz dabei: Wenn ich jetzt andere Eigenschaften über den Windows-Dialog eintrage, dann werden mir die auch von der Funktion angezeigt. Das wäre das erste Problem, über das man diskutieren müsste. @mirage: Vorschläge? :mrgreen:


Der zweite Punkt ist kein Problem sondern ein Vorschlag. Die Funktion aus deinem Programm, @Luckie, lässt sich nämlich wie folgt verkürzen
Delphi-Quellcode:
function GetFileSummaryInfo(const FileName: WideString;
  GUID_SummaryType: TGUID; PID_InfoType: cardinal): WideString;
var
  Stg        : IStorage;
  PropSetStg : IPropertySetStorage;
  PropStg    : IPropertyStorage;
  PropSpec   : TPropSpec;
  PropVariant : TPropVariant;
begin
  Result     := '';

  if(StgOpenStorageEx(pwidechar(FileName),STGM_READ or STGM_SHARE_DENY_WRITE,
    STGFMT_FILE,0,nil,nil,@IID_IPropertySetStorage,Stg) = S_OK) then
  begin
    PropSetStg := Stg as IPropertySetStorage;

    if(PropSetStg.Open(GUID_SummaryType,STGM_READ or
      STGM_SHARE_EXCLUSIVE,PropStg) = S_OK) then
    begin
      PropSpec.ulKind := PRSPEC_PROPID;
      PropSpec.propid := PID_InfoType;

      if(PropStg.ReadMultiple(1,@PropSpec,@PropVariant) = S_OK) and
        (PropVariant.vt = VT_LPWSTR) and
        (PropVariant.pwszVal <> nil) then
      Result := PropVariant.pwszVal;
    end;
  end;
end;
und funktioniert trotzdem noch. ;) Vorteil: Man kann auch die gewünschte GUID übergeben, um bspw. die Kategorie auszulesen:
Delphi-Quellcode:
dummy := GetFileSummaryInfo('MeineDatei.txt',FMTID_DocSummaryInformation,
  PID_CATEGORY);
MessageBoxW(self.handle,pwidechar(dummy),nil,0);
Weiter -

In der Funktion "SetFileSummaryInfo" gibt es IMHO das Problem, dass
Delphi-Quellcode:
OleCheck(PropSetStg.Create(FmtID_SummaryInformation, FmtID_SummaryInformation,
  PROPSETFLAG_DEFAULT,
  STGM_CREATE or STGM_READWRITE or STGM_SHARE_EXCLUSIVE, PropStg));
verwendet wurde. Laut PSDK wird durch "Create" ein neues Property-Set angelegt, und das hat zur Folge, dass die anderen Werte (in dem Fall Autor, Titel und Betreff) gelöscht werden. Nach ein bisschen Herumspielen bin ich der Meinung, dass die Funktion besser so aussehen sollte:
Delphi-Quellcode:
function SetFileSummaryInfo(const FileName: WideString; GUID_InfoType: TGUID;
  PID_InfoType: Cardinal; InfoStr: WideString): boolean;
var
  PropSetStg : IPropertySetStorage;
  PropSpec   : TPropSpec;
  hr         : HRESULT;
  PropStg    : IPropertyStorage;
  PropVariant : TPropVariant;
  Stg        : IStorage;
begin
  Result := false;

  if(StgOpenStorageEx(pwidechar(FileName),STGM_SHARE_EXCLUSIVE or
    STGM_READWRITE,STGFMT_ANY,0,nil,nil,@IID_IPropertySetStorage,stg) =
    S_OK) then
  begin
    PropSetStg := Stg as IPropertySetStorage;

    // try to open an existing Property set
    hr        := PropSetStg.Open(GUID_InfoType,STGM_READWRITE or
      STGM_SHARE_EXCLUSIVE,PropStg);

    // create a new set
    if(hr <> S_OK) then
      hr      := PropSetStg.Create(GUID_InfoType,GUID_InfoType,
        PROPSETFLAG_DEFAULT,STGM_CREATE or STGM_READWRITE or
        STGM_SHARE_EXCLUSIVE,PropStg);

    if(hr = S_OK) then
    begin
      PropSpec.ulKind    := PRSPEC_PROPID;
      PropSpec.propid    := PID_InfoType;
      PropVariant.vt     := VT_LPWSTR;
      PropVariant.pwszVal := PWideChar(InfoStr);

      if(PropStg.WriteMultiple(1,@PropSpec,@PropVariant,2) = S_OK) then
      begin
        Result := (PropStg.Commit(STGC_DEFAULT) = S_OK);
      end;
    end;
  end;
end;
Damit bleiben die alten Werte erhalten, und man kann auch wieder andere Eigenschaften wählen, indem man die passende GUID angibt (s. oben beim Beispiel der Kategorie). Und der Rückgabewert ist gleich vom bool-Typ.

So, das war´s erst mal von meiner Seite.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:51 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz