Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation (https://www.delphipraxis.net/184971-mshtml-64-bit-anwendung-erzeugt-float-invalid-operation.html)

Perlsau 5. Mai 2015 16:23

MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
IDE: Delphi XE7
OS: Windows 7 Ultimate 64-bit

Zum Extrahieren des reinen Textes aus einer HTML-Datei verwende ich MsHtml:
Delphi-Quellcode:
// ----- Extrahiert den Text der übergebenen HTML-Datei --------------------------------------------------------------------------
// ..... http://www.swissdelphicenter.ch/de/showcode.php?id=2352
Function GetHtmlBodyText(Const HtmlText : String) : String;
Var
  IDoc : IHTMLDocument2;
  v   : Variant;

Begin
  Idoc := System.Win.ComObj.CreateComObject(Class_HTMLDOcument) as IHTMLDocument2;
  Try
    IDoc.designMode := 'on';
    While IDoc.readyState <> 'complete' Do
      Application.ProcessMessages;
    v := VarArrayCreate([0, 0], VarVariant);
    v[0] := HtmlText;
    IDoc.Write(PSafeArray(System.TVarData(v).VArray));
    IDoc.designMode := 'off';
    While IDoc.readyState <> 'complete' Do
      Application.ProcessMessages;
    Result := IDoc.Body.InnerText;
  Finally
    IDoc := Nil;
  End;
End;
Das funktioniert wunderbar, solange es sich um eine 32-Bit-Anwendung handelt. Lasse ich das Projekt jedoch als 64-Bit-Anwendung in der IDE (Debug-Modus) ausführen, erscheint diese Fehlermeldung und das Programm beendet sich sofort, nachdem ich auf Fortsetzen gedrückt habe:

... eine Exception der Klasse $C0000090 mit der Meldung 'c0000090 FLOAT_INVALID_OPERATION' aufgetreten.

Ohne IDE gestartet beendet sich das Programm kommentarlos.

Nun ist ja der Internet-Explorer in Win 7-64 eine 32-Bit-Anwendung, somit auch die DLL, auf die MsHtml zurückgreift. Okay, das hatten wir ja schon, daß man für das Einbinden einer DLL in eine 64-Bit-Anwendung eben auch die 64-Bit-DLL benötigt. Kein Problem, dachte ich mir, holst du dir eben den IE-64 für Win7-64. So einfach macht es mir Microsoft aber nicht, denn die Installation des IE-11-64bit bricht mit dem Hinweis auf notwendige Updates ab. Man landet dann auf dieser Seite. Gut, dann lade ich mir jetzt eben diese Updates runter und installiere sie.

Ich starte mit Windows6.1-KB2729094-v2-x64.msu
Ein Update ist für die Segoe UI-Symbol-Schriftart in Windows 7 und Windows Server 2008 R2 verfügbar. Dieses Update bietet Unterstützung für Emoji-Zeichen und einige Serversteuerelement-Glyphen, die in Windows 8 und Windows Server 2012 enthalten sind. Nach der Installation dieser Komponente müssen Sie den Computer neu starten.

Daraufhin erhalte ich folgende Fehlermeldung:

Eigenständiges Windows Update-Installationsprogramm
Das Installationsprogramm hat einen Fehler festgestellt: 0x80070422
Der angegebene Dienst kann nicht gestartet werden. Er ist deaktiviert oder nicht mit aktivierten Geräten verbunden.


Was ist das für ein Dienst? Der Windows-Installer-Service läuft (gestartet). Ich komme da erstmal nicht weiter ...

Alternativen wären:
  1. auf MsHtml zu verzichten und einen Html-Parser zu verwenden. Doch die guten kosten was, die kostenlosen taugen nichts (zumindest soweit mir bekannt). Das Projekt ist nicht kommerziell, sondern ein rein privater "Spaß", der eigentlich außer Zeit und Mühe nichts kosten sollte ...
  2. nur das 32-Bit-Kompilat zu verwenden (werde ich wohl machen müssen)

Dalai 5. Mai 2015 16:52

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
Zitat:

Zitat von Perlsau (Beitrag 1300293)
Nun ist ja der Internet-Explorer in Win 7-64 eine 32-Bit-Anwendung, somit auch die DLL, auf die MsHtml zurückgreift.

Irrtum. Auf jedem Windows x64 gibt es den IE in beiden Ausführungen, 32 und 64 Bit, inkl. der mshtml.dll.

MfG Dalai

Union 5. Mai 2015 16:55

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
In welcher Programmzeile wird denn die Exception geworfen?

Der schöne Günther 5. Mai 2015 16:58

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
Ist das nicht das "übliche" dass die Exception nicht in deinem Programm, sondern im IE Code kommt? Und zwar weil Delphi mit seinem Floating Point-Exception Masking sich nicht "standard-microsoftig" verhält?

Im Internet findet man auf den ersten Blick eine Menge zu TWebBrowser und Fließkomma-Exceptions, alle scheinen darauf hinauszulaufen, die FPU-Exceptions so zu drehen wie der IE-Code es auch erwartet:

z.B. http://stackoverflow.com/q/9359223/2298252

Perlsau 5. Mai 2015 17:43

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
Zitat:

Zitat von Dalai (Beitrag 1300299)
Zitat:

Zitat von Perlsau (Beitrag 1300293)
Nun ist ja der Internet-Explorer in Win 7-64 eine 32-Bit-Anwendung, somit auch die DLL, auf die MsHtml zurückgreift.

Irrtum. Auf jedem Windows x64 gibt es den IE in beiden Ausführungen, 32 und 64 Bit, inkl. der mshtml.dll.

Danke für den Hinweis. Da war ich offensichtlich auf der falschen Fährte :roll:
Zwar konnte ich den IE-11-64 nun doch noch installieren (nach Aktivierung diverser Update-Services, die bei mir deaktiviert waren), doch tritt der Fehler weiterhin auf.

Zitat:

Zitat von Union (Beitrag 1300300)
In welcher Programmzeile wird denn die Exception geworfen?

Delphi-Quellcode:
    While IDoc.readyState <> 'complete' Do
      Application.ProcessMessages;
    Result := IDoc.Body.InnerText;
Entweder beim Abfragen von
Delphi-Quellcode:
IDoc.readyState
oder beim Zuweisen von
Delphi-Quellcode:
IDoc.Body.InnerText
. Genauer läßt sich das nicht eingrenzen, da beim Durchsteppen mehrere Male ReadyState abgefragt wird und der Fehler manchmal beim dritten, manchmal erst beim zehnten Durchlauf auftritt. Ich bin mir nicht sicher, ob die Zuweisung von
Delphi-Quellcode:
IDoc.Body.InnerText
den Fehler auslöst oder die Abfrage von
Delphi-Quellcode:
IDoc.readyState
.

Zitat:

Zitat von Der schöne Günther (Beitrag 1300301)
Ist das nicht das "übliche" dass die Exception nicht in deinem Programm, sondern im IE Code kommt? Und zwar weil Delphi mit seinem Floating Point-Exception Masking sich nicht "standard-microsoftig" verhält? Im Internet findet man auf den ersten Blick eine Menge zu TWebBrowser und Fließkomma-Exceptions, alle scheinen darauf hinauszulaufen, die FPU-Exceptions so zu drehen wie der IE-Code es auch erwartet:
z.B. http://stackoverflow.com/q/9359223/2298252

Okay, da vermeine ich etwas Licht am Ende des Tunnels zu erkennen. Ich hab jetzt erstmal das gemacht, was im Emba-Beispielcode steht:
Delphi-Quellcode:
...
VAR
  FormMain   : TFormMain;
  Saved8087CW : Word;

IMPLEMENTATION
...
Procedure TFormMain.FormCreate(Sender: TObject);
begin
  Saved8087CW := Default8087CW;
  {$IFDEF WIN64}
  Self.Caption := GLD.Programmtitel + '64-Bit-Version';
  System.Set8087CW($133f);
  {$ELSE}
  Self.Caption := GLD.Programmtitel + '32-Bit-Version';
  System.Set8087CW(Saved8087CW);
  {$ENDIF}
...

Procedure TFormMain.FormDestroy(Sender: TObject);
begin
  System.Set8087CW(Saved8087CW);
end;
Nach dem Neu-Erzeugen tritt der Fehler jedoch leider immer noch auf. Doch wir sind ja noch nicht am Ende der Fahnenstange, denn David Heffeman bietet bei StackOverFlow eine Alternative an:
Alternatively, you can call SetSSEExceptionMask and SetFPUExceptionMask passing exAllArithmeticExceptions to mask all exceptions. These convenience methods would make your code more readable. If you are satisfied that you only need to mask exceptions on 8087 under x86 and SSE under x64 then you can just call SetExceptionMask. This will change the 8087 control state under x86 and change the SSE control state under x64.

Allerdings muß ich gestehen, daß ich diese Alternative nicht wirklich verstehe. Wo und wie muß ich diese drei Methoden aufrufen?

hathor 5. Mai 2015 17:54

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
Man braucht die Unit Math.

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
SetExceptionMask(exAllArithmeticExceptions);
...
end;

himitsu 5. Mai 2015 18:00

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
Laufen lassen und warten, wo der Debugger nach dem Knall hält, sagt dir nicht die Zeile?

Notlösung:
Delphi-Quellcode:
try
  while IDoc.readyState <> 'complete' Do
    try
      Application.ProcessMessages;
    except
      raise; // hier einen Haltepunkt
    end;
except
  raise; // hier einen Haltepunkt
end;
try
  Result := IDoc.Body.InnerText;
except
  raise; // hier einen Haltepunkt
end;
Und da wo er zuerst hällt, hat es zuvor geknallt.
Vor dem Raise ein
Delphi-Quellcode:
asm INT 3 end;
geht im Win64 ja leider nicht mehr, um im Debugger einen Zwangsstopp zu veranlassen, falls es nicht von alleine anhält
Eventuell könnte man einen MSDN-Library durchsuchenDebugBreak aufrufen, aber das funktionierte ja auch nicht immer.

Perlsau 5. Mai 2015 18:30

AW: MsHtml in 64-Bit-Anwendung erzeugt Float Invalid Operation
 
Zitat:

Zitat von hathor (Beitrag 1300307)
Man braucht die Unit Math.

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
SetExceptionMask(exAllArithmeticExceptions);
...
end;

Hathor, du bist ein Schatz :love:
Das war der entscheidende Hinweis :!: (asexuell natürlich) Damit läuft es nun auch im 64-Bit-Mode :-D
Delphi-Quellcode:
Procedure TFormMain.FormCreate(Sender: TObject);
begin
  {$IFDEF WIN64}
  SetExceptionMask(exAllArithmeticExceptions);
  Self.Caption := GLD.Programmtitel + '64-Bit-Version';
  {$ELSE}
  Self.Caption := GLD.Programmtitel + '32-Bit-Version';
  {$ENDIF}
...
Zitat:

Zitat von himitsu (Beitrag 1300308)
Laufen lassen und warten, wo der Debugger nach dem Knall hält, sagt dir nicht die Zeile?

Du natürlich auch :!: Aber die genaue Zeile läßt sich damit auch nicht herausfinden. Der Cursor steht immer da, wo ich ihn zuletzt hingestellt habe, auch mit deiner "Notlösung". Es gibt da offenbar keinen Rücksprung zum Delphi-Programm ... von wo auch immer ...

Zitat:

Zitat von Der schöne Günther (Beitrag 1300301)

Das hat auf die richtige Fährte geführt. Danke Günter, du bist auch ein Schatz :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:57 Uhr.

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