Entwickler-Ecke

Dateizugriff - Speichern einer Datei ohne Userabfrage?


SunnyDream - So 04.06.06 12:25
Titel: Speichern einer Datei ohne Userabfrage?
Hi!
Ich bins mal wieder. Sorry für die Masse an Fragen mit der ich euch bombardiere... Zumal sie zum Großteil einfache Anfängerfragen sind, aber ich bin halt noch nicht so weit :(

Naja wie dem auch sei:

Ich möchte in einen HTML Konverter eine Vorschau Funtkion einbauen.
D.h. beim Klicken auf den Button "Vorschau" soll der Inhalt eines RichEdit Feldes als "temp.html" an einem festgelegten Ort gespeichert werden. Jedoch ohne dass der User nach dem Ort gefragt wird, quasi ohne sein Wissen, dass die Datei gespeichert wird.

Ich weiss zwar wie man den Inhalt des RichEdits speichert, ich weiss auch wie man einen Namen vorgeben kann, und auch wie man einen Datei-Filter einschaltet. Aber ich weiss eben nicht, wie ich die Datei speichern kann, ohne dass der User davon etwas mitbekommt.


Desweiteren möchte ich die Datei dann ausführen, und ich weiss leider garnicht wie man sowas in Delphi macht... Also eine Datei ausführt =(

Last but not least möchte ich die Datei dann bei Beendigung des Programmes dann löschen. Ratet mal? Ich habe keinen blassen Schimmer wie ich das anstelle... =(

Ich hoffe ihr könnt mir so schnell und kompetent wie bisher helfen, und dass ich euch nicht allzusehr auf die Nerven gehe =)


Hack Gott - So 04.06.06 12:31

Ich hatte den ganzen Text schonmal getippt, jetzt wurde der beiträg gesperrt, nochmal von vorne:

Also du erstellst deine Datei ohne SaveDialog:

Delphi-Quelltext
1:
Listbox1.Items.SaveToFile('C:\temp.html');                    


Dann lässt du sie ausführen, dazu fügst du in deiner Form bei den Uses ShellApi hinzu. Dann kanst du folgenden Code verwenden:

Delphi-Quelltext
1:
ShellExecute(Handle, 'open''iexplorer.exe''"C:\temp.html"''C:\Programme\Internet Explorer\', SW_SHOWNORMAL);                    


Wahlweise kannst du auch SW_SHOWMINIMIZED oder SW_SHOWMAXIMIZED verwenden (ich denke der Sinn ergibt sich von selbst). Erklärung der Code startet die Datei iexplorer.exe, zusätzlich erhält der Explorer deine Datei als Paramenter, er sollte sie jetzt ausführen.

Es ist einfacher die Datei einfach bei Beenden zu löschen (es geht auch nach Schließen des IE aber das ist komplizierter...), also einfach bei deiner Form der Eigenschaft OnClose folgendes hinzufügen:

Delphi-Quelltext
1:
if fileexists('C:\temp.html'then deletefile('C:\temp.html');                    


SunnyDream - So 04.06.06 12:36

Danke!
Echt Super Erklärung und eine erstklassige Hilfstellung.
Dank dir :)


Andreas L. - So 04.06.06 12:37

Hi,

Delphi-Quelltext
1:
Richedit1.lines.savetofile('C:\temp.html');                    


Es wäre ratsam wenn du die Datei in das Temp-Verzeichnis des jeweiligen Users speicherst. Sicherheitbewusste User arbeiten nicht mit den Adminkonto und haben somit keine Rechte auf C:\ oder andere Ordner zu schreiben. Da das Temp-Verzeichnis immer wo anders sein kann solltest du die Funktion Suche in der Delphi-PRAXiS GETSHELLFOLDER verwenden.

Um die Datei aufzurufen kannst du entweder das ActiveX-Control "TWebBrowser" verwenden:

Webbrowser1.navigate('C:\temp.html'); Dies wäre also ein integrierter Browser. Willst du die Datei mit den Standard-browser des Users öffnen solltest du mal nach Suche in der Entwickler-Ecke SHELLEXECUTE, URL suchen.

Zum Löschen kannst du mal nach Suche in der Entwickler-Ecke DELETEFILE suchen. Das ist eine WinAPI-Funktion.


Gausi - So 04.06.06 12:39

Ich würde nur ggf. 'C:\tmp.html' durch etwas ersetzen, was auch ein normaler User schreiben kann. Ich darf z.B. keine Dateien im Stammverzeichnis meiner Systempartition erstellen ;-)

Besser wäre da z.B. das Anwendungsverzeichnis des Users. Das bekommt man z.B. so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
function GetShellFolder(CSIDL: integer): string;
var   
  pidl              : PItemIdList;   
  FolderPath        : string;   
  SystemFolder      : Integer;   
  Malloc            : IMalloc;   
begin   
  Malloc := nil;   
  FolderPath := '';   
  SHGetMalloc(Malloc);   
  if Malloc = nil then   
  begin   
    Result := FolderPath;   
    Exit;   
  end;   
  try   
    SystemFolder := CSIDL;   
    if SUCCEEDED(SHGetSpecialFolderLocation(0, SystemFolder, pidl)) then   
    begin   
      SetLength(FolderPath, max_path);   
      if SHGetPathFromIDList(pidl, PChar(FolderPath)) then   
      begin   
        SetLength(FolderPath, length(PChar(FolderPath)));   
      end;   
    end;   
    Result := FolderPath;   
  finally   
    Malloc.Free(pidl);   
  end;   
end;

// Aufruf:
const CSIDL_APPDATA = $001a;
//...
MeinSavePath := GetShellFolder(CSIDL_APPDATA);


Ach Mensch. Ich bin heute echt zu langsam. Aber noch mal lösche ich meine Beitrag nicht nachträglich. :schmoll:


SunnyDream - So 04.06.06 12:52

Danke für den Tipp mit dem Shellfolder, ich werds umsetzen aber dennoch habe ich vorerst folgendes Problem:



So, also die Datei Speichert und Löscht er wie ich es wollte, jedoch führt er den IE nicht aus.
Ich weiss nicht wo das Problem liegt deshalb poste ich einfach meine "Uses" und den Code des OnClicks:


Uses:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, Spin, ShellApi, Buttons;


Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
// Vorschau Prozedur!
procedure TForm1.SBPreviewClick(Sender: TObject);
begin
ROutPut.PlainText:= true;
ROutPut.Lines.SaveToFile('C:\temp.html');

//ausführen der temp.html im Internetexplorer!
ShellExecute(Handle, 'open''iexplorer.exe''"C:\temp.html"''C:\Programme\Internet Explorer\', SW_SHOWNORMAL);
end;


Hack Gott - So 04.06.06 12:55

Ist mein Fehler, die Datei die du ausführen müsst muss nicht iexplorer.exe heißen sondern iexplore.exe!


SunnyDream - So 04.06.06 12:57

O.k. Danke - jetzt funktioniert es. Ich werde jetzt aber direkt auf die oben genannten Tipps eingehen (was den Speicherort betrifft) und versuchen diese umzusetzen!


SunnyDream - So 04.06.06 13:28

So für mich hat sich nun ein Problem eröffnet.
Wenn ich oben genannte Prozedur verwende, wird ja der Pfad in den die temp.html gespeichert werden soll in die Variable "MeinSavePath" gespeichert.
Wie ist dann die korrekte Syntax bei der Pfadangabe in der Speicher/Ausführ Funktion?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
// Vorschau Prozedur!-----------------------------------------------------------
procedure TForm1.SBPreviewClick(Sender: TObject);
begin
ROutPut.PlainText:= true;
ROutPut.Lines.SaveToFile('C:\temp.html');

//ausführen der temp.html im Internetexplorer!
ShellExecute(Handle, 'open''iexplore.exe''"C:\temp.html"''C:\Programme\Internet Explorer\', SW_SHOWNORMAL);
end;


so sieht es bisher aus, wie muss ich es schreiben damit er dann den in "MeinSavePath" gespeicherten Pfad verwendet?


Hack Gott - So 04.06.06 13:36


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
// Vorschau Prozedur!-----------------------------------------------------------
procedure TForm1.SBPreviewClick(Sender: TObject);  
var MeinSavePath: string;
begin  
MeinSavePath := 'C:\temp.html'//Oder halt was anderes...
ROutPut.PlainText:= true;  
ROutPut.Lines.SaveToFile(MeinSavePath);  

 
//ausführen der temp.html im Internetexplorer!  
ShellExecute(Handle, 'open''iexplore.exe''"' + MeinSavePath + '"''C:\Programme\Internet Explorer\', SW_SHOWNORMAL);  
end;


SunnyDream - So 04.06.06 13:40

Danke soweit!
Du verwendest jetzt den Pfad "MeinSavePath", enthält dieser auch den Dateinamen? Also, eigentlich wird ja nur der Systemordner "temp" gesucht, und dann der komplette Pfad in "MeinSavePath" gespeichert. Wie heisst jetzt aber die Datei? Was ja zB für das Löschen wichtig wäre, sonst würde das Programm ja beim Schließen den Ordner Temp löschen, was sicher nicht Ziel der Sache sein soll^^;


Hack Gott - So 04.06.06 13:43

Dann must du es so machen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
// Vorschau Prozedur!-----------------------------------------------------------  
procedure TForm1.SBPreviewClick(Sender: TObject);    
begin    
MeinSavePath := MeinSavePath+'temp.html'//MeinSavePath sollte jetzt halt weiter oben deklariert sein  
ROutPut.PlainText:= true;    
ROutPut.Lines.SaveToFile(MeinSavePath);    

 
//ausführen der temp.html im Internetexplorer!    
ShellExecute(Handle, 'open''iexplore.exe''"' + MeinSavePath + '"''C:\Programme\Internet Explorer\', SW_SHOWNORMAL);    
end;


SunnyDream - So 04.06.06 13:49

Was den Pfad angeht, das scheint so zu funktionieren...
Aber, die Funktion "GetShellFolder" macht mir Probleme...

ich bekomme als Fehlermeldungen:

Zitat:

Erzeugen
[Fehler] Unit1.pas(63): Undefinierter Bezeichner: 'PItemIdList'
[Fehler] Unit1.pas(66): Undefinierter Bezeichner: 'IMalloc'
[Fehler] Unit1.pas(70): Undefinierter Bezeichner: 'SHGetMalloc'
[Fehler] Unit1.pas(71): Operator ist auf diesen Operandentyp nicht anwendbar
[Fehler] Unit1.pas(78): Undefinierter Bezeichner: 'SHGetSpecialFolderLocation'
[Fehler] Unit1.pas(81): Undefinierter Bezeichner: 'SHGetPathFromIDList'
[Fehler] Unit1.pas(88): Operator oder Semikolon fehlt
[Fehler] Unit1.pas(380): Anweisung erwartet, aber 'CONST' gefunden


Der Code der Funtkion in meinem Programm sieht wie folgt aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
//GetShellFolder Funktion!------------------------------------------------------
function TForm1.GetShellFolder(CSIDL: integer): string;
var
  pidl              : PItemIdList;
  FolderPath        : string;
  SystemFolder      : Integer;
  Malloc            : IMalloc;
begin
  Malloc := nil;
  FolderPath := '';
  SHGetMalloc(Malloc);
  if Malloc = nil then
  begin
    Result := FolderPath;
    Exit;
  end;
  try
    SystemFolder := CSIDL;   
    if SUCCEEDED(SHGetSpecialFolderLocation(0, SystemFolder, pidl)) then
    begin
      SetLength(FolderPath, max_path);   
      if SHGetPathFromIDList(pidl, PChar(FolderPath)) then
      begin   
        SetLength(FolderPath, length(PChar(FolderPath)));
      end;
    end;
    Result := FolderPath;   
  finally   
    Malloc.Free(pidl);
  end;
end;


SunnyDream - So 04.06.06 14:53

Hab die "undefinierten" Bezeichner nu in die "Uses" geschrieben,da scheints zu gehen. Jedoch sacht er mir bei der PItemIdList dass er die "PItemIdList.dcu" nicht finden kann?
Woran liegt das?


Gausi - So 04.06.06 14:58

Nene, das is Quatsch.

In die Uses Liste muss iirc nur ShlObj und ShellApi. Das andere sind ja Funktionen, keine Units ;-)


SunnyDream - So 04.06.06 15:02

Aber wo liegt dann das Problem mit der Funktion als solches? Er sagt nämlich immernoch das "IMalloc" ein undefinierter Bezeichner ist o.O