C ++ Forum | | | | Georg Hovenbitzer | Hallo Sebastian,
ich habe mal wieder ein größeres Problem. Der geniale folgende Code stammt vom Pascal, soetwas könnte ich mir nicht ausdenken. Er ermittelt den Quellcode aus einem geöffneten IE Fenster, wie z.B. www.google.de. Zum Test bitte keine große Seite nehmen, da die Zuweisung zum Edit Feld im Beispielt noch per SetText geht.
Im Interpreter und als Profan Exe läuft er super, übersezt kommt immer eine Schutzverletzung. Die Zeile die den Fehler verursacht ist die: Error& = CallMethod(IHTMLElement&,62,@Addr(Text&))
Der Grund ist dafür, dass der Aufruf davor von: Error& = CallMethod(IHTMLDocument2&,9,@Addr(IHTMLElement&))
Eine Error& Nummer <> 0 zurückt gibt und IHTMLElement&, gleich 0 ist.
Könnte dieses Problem des Übersetzen sein ? KompilierenMarkierenSeparieren $H D:PrivatProfanXProfan9INCLUDEWindows.ph
---------------Umwandlung String > globally unique identifier
Proc StringToGUID
Parameters GUID$,GUID&
Declare Temp$
Temp$ = @Space$(80)
~MultiByteToWideChar(1,1,@Addr(GUID$),-1,@Addr(Temp$),80)
@External("ole32","CLSIDFromString",@Addr(Temp$),GUID&)
EndProc
-----------------------------------------------------------------------
--------------------------Methode eines COM-Interfaces aufrufen
Proc CallMethod
Parameters IFace&,Method&
Declare VTable&
VTable& = @Long(IFace&,0)
Method& = @Long(VTable&,(Method& * 4))
Case %PCount = 2 : Return @Call(Method&,IFace&)
Case %PCount = 3 : Return @Call(Method&,IFace&,@&(3))
Case %PCount = 4 : Return @Call(Method&,IFace&,@&(3),@$(4))
Case %PCount = 5 : Return @Call(Method&,IFace&,@&(3),@&(4),@&(5))
EndProc
-----------------------------------------------------------------------
----------WideChar (UniCode) zu MultiByte (Ansi) [nur OLE!]
Proc OLE_WideToMulti
Parameters Text&
Declare Text$,Size&,Text#
Size& = @External("oleaut32","SysStringLen",Text&)
Dim Text#,Size&
Clear Text#
~WideCharToMultiByte(0,0,Text&,-1,Text#,Size&,0,0)
@External("oleaut32","SysFreeString",Text&)
Text$ = @String$(Text#,0)
Dispose Text#
Return Text$
EndProc
-----------------------------------------------------------------------
------------------------------EnumChildProc---------------------------
Proc EnumChildProc
Parameters wnd&
Declare Name#
Dim Name#,255
~GetClassName(wnd&,Name#,255)
Case @String$(Name#,0)="Internet Explorer_Server" : IEServerWnd& = wnd&
Dispose Name#
Return 1
EndProc
---------------------------------------------------------------------------------
--------------------------RunningIE_GetText-----------------------
Proc RunningIE_GetText
Parameters IEHwnd&
Declare Error&,IID#,Msg&,Result&,oleacc&,IHTMLDocument2&,IHTMLElement&,Text&,Text$,Url&,Url$
Dim IID#,16
Declare IEServerWnd&
~EnumChildWindows(IEHwnd&,@ProcAddr(EnumChildProc,2),0)
@ProcAddr(EnumChildProc,-2)--ProcAddr freigeben
Print "IEServerwnd&",IEServerWnd&
Print
Msg& = ~RegisterWindowMessage("WM_HTML_GETOBJECT")
Print "msg",Msg&
Print
Error& = ~SendMessageTimeout(IEServerWnd&,Msg&,0,0,~SMTO_ABORTIFHUNG,1000,@Addr(Result&))
Print "Error SendMessageTimeout",Error&
Print "Result SendMessageTimeout",Result&
@External("ole32","CoInitialize",0)
oleacc& = @UseDLL("oleacc.dll")
Print "oleacc",oleacc&
Print
StringToGUID("{332c4425-26cb-11d0-b483-00c04fd90119}",IID#)--IID_IHTMLDocument2
Error& = @External("oleacc","ObjectFromLresult",Result&,IID#,0,@Addr(IHTMLDocument2&))
Print "Error ObjectFromLresult",Error&
Print "IHTMLDocument2",IHTMLDocument2&
FreeDLL oleacc&
Error& = CallMethod(IHTMLDocument2&,9,@Addr(IHTMLElement&))--IHTMLDocument2::get_body
Print "Error IHTMLDocument2::get_body",Error&
Print "IHTMLElement",IHTMLElement&
Print
----------------------------------------------Quelltext ermitteln
Error& = CallMethod(IHTMLElement&,62,@Addr(Text&))--IHTMLElement::get_outerHTML
Print "Error IHTMLElement::get_outerHTML",Error&
Print "Result get_outerHTML",Text&
Print
Text$ = OLE_WideToMulti(Text&)
-------------------------------------------------------URL ermitteln
Error& = CallMethod(IHTMLDocument2&,40,@Addr(Url&))--IHTMLElement::get_URL
Print "Error IHTMLElement::get_URL",Error&
Print "Result get_URL",URL&
Print
Url$ = OLE_WideToMulti(Url&)
Print "URL = ";Url$
Dispose IID#
@External("ole32","CoUninitialize")
Return Text$
EndProc---------------------------------------------------------------------------------
Window 0,0-800,600
Declare Fenster&
Declare Edit&
Declare Quell$
Declare IEServerWnd&
Fenster& = ~FindWindow("IEFrame",0)--Hier könnte man auch andere Möglichkeiten nehmen,
IfNot Fenster&---------------------z.B. Suche nach Fenstertitel.
Print "Bitte IE starten!!"------Benötigt wird das gewünschte Hauptfenster des IE!
WaitInput
End
EndIf
Quell$ = RunningIE_GetText(Fenster&)
If @Len(Quell$)
Edit& = @Create("multiedit",%hwnd,"",300,20,450,500)----Text anzeigen
SetText Edit&,Quell$
EndIf
WaitKey
End
|
| | | Viele Grüsse, Georg Hovenbitzer(Windows XP Pro, XProfan 11.2, Profan2Cpp 1.6a) | 17.05.2006 ▲ |
| |
| | Sebastian König | Hallo Georg,
danke für den Hinweis - das Problem tritt auch bei mir auf - leider konnte ich die Ursache noch nicht feststellen ...
Wie Du schon geschrieben hast, schlägt der Aufruf
Error& = CallMethod(IHTMLDocument2&,9,@Addr(IHTMLElement&))
fehl, sodass IHTMLElement& keinen gültigen Schnittstellenzeiger enthält und der Versuch, eine Methode damit aufzurufen, zum Abstruz führt.
Nur was genau da schiefläuft, ist mir noch ein Rätsel... Das CallMethod selbst ist ja noch in Ordnung, es wird nur ein Fehler-Cdoe zurückgegeben... Ich werde mal versuchen, dessen Bedeutung herauszufinden und melde mich nochmal, wenn ich etwas neues weiß...
MfG
Sebastian |
| | | | |
| | Sebastian König | Hallo Georg,
Der Code steht für RPC_E_CANTCALLOUT_ININPUTSYNCCALL. Die Beschreibung dafür lautet:
Ein ausgehender Aufruf kann nicht ausgeführt werden, da die Anwendung einen Eingabe-synchronisierten Aufruf weiterleitet.
Sehr komisch...
Da mir sonst nichts einfiel, hatte ich irgendwie das MultiThread-Konzept im Verdacht (der Gedanke kam mir, weil da ja angeblich irgendwas gleichzeitig stattfindet ...
Jedenfalls habe ich dann folgendes probiert: Call() und External() werden in den übersetzen Programmen ja grundsätzlich im Kontext des Haupt-Threads ausgeführt, weil man ja nie wissen kann, ob irgendwie Fenster oder Controls erstellt/bearbeitet werden... Es gibt jedoch eine Möglichkeit, dies zu ändern: Wenn ich den Code zunächst nur übersetze, also make.bat nicht automatisch starte, und in die erzeugte [Projektname].cpp-Datei (Achtung: nicht die PrfMain.cpp) nach den ganzen #include-Anweisungen die beiden Zeilen
#define External External_ST #define Call Call_ST
einfüge, funktioniert es auf einmal...
Kannst Du das bestätigen?
MfG
Sebastian
P.S.: Das ganze scheint ein bekannter Windows-Bug zu sein... Gut möglich, dass es sich genau um das [...] beschriebene Problem handelt. Der Abschnitt Symptoms beschreibt nämlich genau das aktuelle Problem |
| | | | |
| | Georg Hovenbitzer | Hallo Sebastian,
deine Lösung funktioniert mit dem Demo sehr gut
Ich werde sie im laufe des Tages im Programm testen um zu sehen ob dort Schwierigkeiten auftreten.
Melde mich dann hier. |
| | | Viele Grüsse, Georg Hovenbitzer(Windows XP Pro, XProfan 11.2, Profan2Cpp 1.6a) | 18.05.2006 ▲ |
| |
| | Sebastian König | Hallo Georg,
leider ist es sehr wahrscheinlich, dass das pauschale Umstellen auf die *_ST-Versionen in Deinem Programm zu Problemen führt . In der Regel ist es ja wie schon erwähnt sogar notwendig, dass API-Funktion im Kontext des Haupt-Threads ausgeführt werden, da dort die ganze Fensterverwaltung stattfindet...
Ich habe inzwischen auch mal den unter dem Link (siehe PS in meinem Posting oben) gegebenen Vorschlag Use PostMessage instead of an inter-process/inter-thread SendMessage. ausprobiert - auch damit ist der Fehler behoben.
Das blöde ist nur: Die Alternative kommt eigentlich nicht in Frage. Ursprünglich hatte ich für External() und Call() tatsächlich PostThreadMessage() benutzt, bis irgendwann (ich glaube es war noch in der Beta-Phase vor der Veröffentlichung von Profan2Cpp) auffiel, dass es damit in Extremsituationen (sehr viele Aufrufe in sehr kurzer Zeit) zu Problemen kommen konnte . Mit dem Umstieg auf SendMessage() war dann alles in Ordnung und obendrein noch die Performance etwas besser, da ja der Umweg über die Nachrichtenschleife entfiel ...
So, jetzt nach dem ganzen Erklären, was nicht geht, mal ein Vorschlag zur Lösung des Problems :
Dass es in der Demo mit den _ST()-Funktionen auch bei Dir funktioniert, ist ja schonmal super! Meine Idee wäre jetzt, Profan2Cpp so zu erweitern, dass mit einer speziellen Anweisung im Profan-Code automatisch für einen bestimmten Abschnitt auf die _ST-Varianten umgeschaltet werden kann. Damit sich XProfan selbst nicht über unbekannte Befehle beschwert, würden sich spezielle Kommentare anbieten. In Deinem Code könnte es dann in etwa so aussehen: KompilierenMarkierenSeparieren Was hältst Du von dem Vorschlag?
MfG
Sebastian |
| | | | |
| | Georg Hovenbitzer | Hallo Sebastian,
ich kann dich beruhigen
Mein Programm läuft nun ohne Fehler, es gab zwar ein paar seltsame Effekte wie z.B. dass ich alle DLLs mit UseDLL Laden musste, was ohne Übersetzen nicht nötig war. Anderseits mach das Programm auch nicht viel, es ließt den Quelltext der Seite aus und sucht dort nach Links, speichert Bilder und Text Dateien. Für die Zukunft wäre deine angedacht Lösung sehr vom Vorteil, da sie sehr leicht in den Profan Code einzubauen ist und man sich dadurch auch nicht die Möglichkeit nimmt deine Plugins zu benutzen (da ich noch nicht herausgefunden habe wie ich mit dem ResHacker Versions Informationen in eine Datei bekomme). |
| | | Viele Grüsse, Georg Hovenbitzer(Windows XP Pro, XProfan 11.2, Profan2Cpp 1.6a) | 19.05.2006 ▲ |
| |
| | Sebastian König | Hallo Georg,
wenn es sogar so schon funktioniert, ist das natürlich erst recht super!
Die vorgeschlagen Kommentar-Schalter werde ich dann in die nächste Version einbauen - für größtmögliche Flexibilität sogar getrennte Schalter für Call() und External(), die aber in einer einzigen Zeile gesetzt werden können, z.B.
P2CPP: <USE_EXTERNAL_ST,USE_CALL_ST>
MfG
Sebastian |
| | | | |
| | Georg Hovenbitzer | Hallo Sebastian,
ich habe mich etwas zu früh gefreut
Ich habe dir mal ein Codebeispiel geschrieben der leider nach dem manuellen Einfügen von: #define External External_ST #define Call Call_ST nicht funktioniert. Das Problem liegt daran, dass &UwParam keinen Wert mehr erhält KompilierenMarkierenSeparierenDef RegisterHotKey(4) !"USER32.DLL","RegisterHotKey"
Def UnregisterHotKey(2) !"USER32.DLL","UnregisterHotKey"
Declare Edit&
Window 100,100-400,400
Edit& = @Create("Edit",%hWnd,"",100,100,150,20)
UserMessages $312
RegisterHotKey(%hWnd,11111,3,80) Strg + Alt + P
WhileNot %Key = 2
WaitInput
SetText Edit&,""
DrawText 20,30,@Space$(30)
DrawText 20,20,"&UwParam = " + @Str$(&UwParam)
If ((&UwParam = 11111) And (%GetFocus = Edit&))
SetText Edit&,"TREFFER !"
EndIf
EndWhile
UnRegisterHotKey(%hWnd,11111)
UserMessages 0
End
|
| | | Viele Grüsse, Georg Hovenbitzer(Windows XP Pro, XProfan 11.2, Profan2Cpp 1.6a) | 23.05.2006 ▲ |
| |
| | | Mir viel da auch noch was ein!
P2CPP: <USE_EXTERNAL_ST,USE_CALL_ST>
Ist denkbar schlecht als Indikator - Rems sollten immer wegoptimierbar sein.
XProfan selbst hat schon solch tollen Befehl SET
Warum also nicht KompilierenMarkierenSeparieren Ich glaub das wäre eleganter. |
| | | | |
| | Sebastian König | Hallo iF,
[quote:26d3b84306]XProfan selbst hat schon solch tollen Befehl SET
Warum also nicht
Set(P2CPP:...,1)
Ich glaub das wäre eleganter. [/quote:26d3b84306] das geht leider aus 2 Gründen nicht:
1. Die Information muss schon zum Zeitpunkt der Übersetzung zur Verfügung stehen - bei Set() ist das leider nicht so, weil man ja auch eine Stringvariable benutzen könnte... (dehalb ließ sich zum Beispiel das @Set(ESCAPE, n%) von XProfan 9 nicht richtig umsetzen ).
2. XProfan würde eine solche Anweisung mit Unbekannter Schalter: P2PP... quittieren...
Oh, gerade fällt mir noch ein:
3. Abwärtskompatibilität! Ältere Profan²-Versionen kennen gar kein Set()...
Kannst Du dem XPSE nicht einfach beibringen, bei bestimmten Kommentaren ein bischen Zurückhaltung zu üben?
MfG
Sebastian |
| | | | |
| | | [quote:a8da9240c6=Sebastian König]Hallo iF,
[quote:a8da9240c6]XProfan selbst hat schon solch tollen Befehl SET
Warum also nicht
Set(P2CPP:...,1)
Ich glaub das wäre eleganter. [/quote:a8da9240c6] das geht leider aus 2 Gründen nicht...
...Kannst Du dem XPSE nicht einfach beibringen, bei bestimmten Kommentaren ein bischen Zurückhaltung zu üben?
[/quote:a8da9240c6] Ohhhh mein Gott.
Ok, noch ne Idee: p2cppcompiler$=blub |
| | | | |
| | Sebastian König | [quote:f983247403]Ohhhh mein Gott.
Ok, noch ne Idee: p2cppcompiler$=blub [/quote:f983247403] Ich weiß jetzt nicht so ganz, was Du meinst...
Die Lösung mit diesen Kommentar-Befehlen gefällt mir eigentlich auch ziemlich gut, weil sie sehr flexibel ist (man könnte sogar für einzelne Aufrufe das Verhalten ändern), den XProfan-Interpreter bzw. Compiler überhaupt nicht stört und auch gar keinen unnötigen Overhead erzeugt... |
| | | | |
|
AntwortenThemenoptionen | 5.986 Betrachtungen |
ThemeninformationenDieses Thema hat 4 Teilnehmer: |