Werte Kollegen, bitte verzeiht mir, dass ich dieses uralte Thema ausgrabe.
Aufgrund eines aktuellen Datenschutzvorfalls möchte ich alle Leser auf folgendes Problem hinweisen:
TL;DR: Wenn der Kunde vor Programmstart bereits PowerPoint offen hat, exportiert + zerstört die Prozedur von OP *diese* Präsentation (falls nicht gespeichert), statt die mit dem Dateinamen übergebene Präsentation umzuwandeln!
In Länge:
Ich wollte solche Probleme bereits im Vorfeld vermeiden und habe immer mit einer leeren PowerPoint-Instanz mit "PowerPoint := CoPowerPointApplication.Create" gearbeitet, statt mich auf die bestehende PowerPoint-Instanz "draufzuschalten". (Spoiler: Nein, sie ist nicht leer!)
Aber auch wenn die von OP beschriebene Ermittlung (AppWasRunning) weggelassen wird, ob eine PowerPoint-Instanz bereits läuft oder nicht, wird mit "PowerPoint := CoPowerPointApplication.Create;" KEINE neue PowerPoint-Instanz erzeugt, FALLS bereits PowerPoint mit einer anderen Datei geöffnet ist. Das PowerPoint-
Handle zeigt stattdessen auf die bereits geöffnete Instanz.
Im vorliegenden Fall verwendet OP (wissentlich) die bestehende Instanz von PowerPoint, falls diese bereits geöffnet war.
Ich habe sie unwissentlich/unfreiwillig verwendet, wegen: siehe Oben.
Daraus resultiert:
1) In der Prozedur von OP wird die in PowerPoint
bereits vor Programmstart geöffnete Präsentation nun als Bild gespeichert. NICHT die Präsentation, die über Open() geöffnet wird. (Die Zufälligerweise-bei-Programmstart-geöffnete-PowerPoint mit sensiblen Daten wird als Bild gespeichert und weiterverarbeitet, nicht die mit "Path" übergebene! --> PowerPoint.Presentations.Item(1) = schon offene PowerPoint, Item(2) wäre die eben von uns geöffnete!
2) Nach der Umwandlung in ein Bild wird die "erste" PowerPoint-Präsentation (ohne Speichern) geschlossen: PowerPoint.Presentations.Item(1).Close . Evtl. hat der Benutzer schon den ganzen Tag an der Präsentation gearbeitet ohne zu Speichern, will kurz in deinem Programm was machen und dann wird ihm die Präsentation kommentarlos zugemacht.
Keine Anschuldigung, keine Beschwerde! Ich arbeite ja auch mit dem Code, und bin dankbar für die Mitarbeit in der Community, und mir ist es ja auch vorher nicht aufgefallen.
Mein Lösungsvorschlag, bitte korrigiert ihr mich hier gerne:
Bei "Open()" erhält man das
Handle/Interface/was-auch-immer auf die eben geöffnete PowerPoint-Datei (hier die Variable "SelectedPresentation", nehmt gerne einen sinnvolleren Namen). Nur damit arbeiten!
Delphi-Quellcode:
function ConvertPowerPoint(var _FileName: String; _RootFolder: string; _SubFolder: string; _ForceSubdirectory: Boolean = False): Boolean;
const
P = 'ConvertPowerPoint';
var
PowerPoint: PowerPointApplication;
AppWasRunning: Boolean;
OleResult: HRESULT;
Unknown: IUnknown;
SelectedPresentation: _Presentation;
begin
Result := False;
try
// ...
AppWasRunning := False;
OleResult := GetActiveObject(CLASS_PowerPointApplication, nil, Unknown);
if (OleResult = MK_E_UNAVAILABLE) then begin
PowerPoint := CoPowerPointApplication.Create;
end else begin
OleCheck(OleResult);
OleCheck(Unknown.QueryInterface(PowerPointApplication, PowerPoint));
AppWasRunning := True;
end;
if assigned(PowerPoint) then begin
try
SelectedPresentation := PowerPoint.Presentations.Open(_FileName, msoTrue, msoFalse, msoFalse);
if SelectedPresentation <> NIL then begin
try
// ...
SelectedPresentation.Export(TargetFolder, 'png', w, h);
finally
SelectedPresentation.Close;
end;
end;
finally
if not AppWasRunning then PowerPoint.Quit;
end;
end else begin
LogP(M, P, 'Unable to connect to PowerPoint!', '', ws_SEVERITY_FAILED);
end;
Vielen Dank für eure Aufmerksamkeit!
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit