Forum | | | | - Seite 1 - |
| | Hallo IF...
Ich habs mal getestet und hoffe nichts falsch gemacht zu haben: KompilierenMarkierenSeparieren $U thread.pcu = thread.
DEF @GetDlgCtrlID(1) !"USER32","GetDlgCtrlID"
DEF @ButtonClicked(1) @GetDlgCtrlID(@&(1))=-%MENUITEM
Testprogramm Timer
Profan Version 9
$H Windows.ph
-Main----------------------------------------------------------------
Declare Timer_Busy%,Ende%
Declare TimerID&,Create%,T_Text&,Test#
WindowStyle 26
WindowTitle "Timertest PHU-60"
Window 100,100 - 370,200
cls
Let T_TEXT&=@CREATETEXT(%HWND,"",30,30,300,30)
-Menue---------------------------------------------------------------
PopUp "&Programm"
AppendMenu 108,"&Einstellungen"
AppendMenu 109,"&Ende"
Ende% = 0
Timer setzen (4x pro Sekunde, 250ms)
thread.start 1,1
WhileNot Ende%
WaitInput
If @MenuItem(108)
Einstellungen
Endif
If @MenuItem(109)
thread.stopall
Ende% = 1
Endif
Wend
End
-Proc Einstellungen
Proc Einstellungen
Declare hD%, hA%, hB%, OK%, hTime%
Declare hF1%, hT1%
Clear OK%
Dialogfenster erzeugen
hD% = @Create("Dialog",%hWnd,"Einstellungen",%WinLeft+80,%WinTop+155,230,190)
hF1% = @Create("Font","Arial",16,0,0,0,0)
hT1% = @Create("Text",hD%,"Einstellungen...",10,10,220,20)
SetFont hT1%,hF1%
hTime% = @Create("TimeEdit", hD%, "00:00:00", 10, 35, 70, 24)
hB% = @Create("Button",hD%,"&Nachstellen",10,120,100,28)
hA% = @Create("Button",hD%,"&Abbrechen",120,120,100,28)
WhileNot Ok%
WaitInput
If @ButtonClicked(hB%) Nachstellen
Ok% = 1
Aktionen hier
ElseIf @ButtonClicked(hA%) Abbrechen
Ok% = 1
ElseIf (%Key = 2) ALT+F4 bzw. schließen
Ok% = 1
EndIf
EndWhile
DeleteObject hF1%
@DestroyWindow(hD%)
EndProc
-Prozedur die in bestimmten Zeitintervallen ausgefuehrt wird (4x pro Sekunde)
Proc thread.do
parameters n&
Dim Test#,1000000
Inc Timer_Busy%
Locate 5,5
Print "Timer:" + @str$(Timer_Busy%) + " Durchläufe"
Settext T_Text&,"Timer:" + @str$(Timer_Busy%) + " Durchläufe"
Dispose Test#
EndProc
Auch hier wird das Fenster nicht richtig angezeigt! Was bedeutet das? Werden im Hauptprogramm während ein Thread ausgeführt, überschreibt Profan intern gespeicherte Variablen zum Aufrufen von API. Je nachdem, welche Profanfunktionen im Hauptprogramm verwendet werden, ist die Gefahr mal mehr und mal weniger gegeben, sie ist aber auch (laut Roland) beim direkten Aufrufen von APIs vorhanden. Wann und ob ein Fehler auftritt, hängt vom gewählten Zeitintervall, vom Rechner und von der Programmbedienung durch den User ab. Was bedeutet das genau?
Ein Beispiel: Beim einem Rechner unter Windows2000 wird beim Aufruf der API RegUnloadKey ein solcher Crash verursacht und die API wird deshalb nicht korrekt ausgeführt. Daraufhin wird der Registryhive des User nicht wie geplant entladen und ist beim nächsten Start nicht mehr verfügbar => ein ganzes Userprofile ist unwiederbringlich verloren.
Ein anders Beispiel: Das Hauptprogramm schreibt während ein Callback läuft in die Registry. Da alles ungünstig zusammentrifft, wird in einen anderen Schlüssel geschrieben und Datenj in der Registry gehen verloren!
Weitere Fragen und Anmerkungen? |
| | | | |
| | | | | - Seite 3 - |
| | Und diese drei Quelltexte wären da unter anderem auch noch interessant: KompilierenMarkierenSeparierenDEF @GetDlgCtrlID(1) !"USER32","GetDlgCtrlID"
DEF @ButtonClicked(1) @GetDlgCtrlID(@&(1))=-%MENUITEM
DEF @GetProcAddress(2) !"KERNEL32","GetProcAddress"
Testprogramm Timer
Profan Version 9
$H Windows.ph
-Main----------------------------------------------------------------
Declare Timer_Busy%,Ende%
Declare TimerID&,Create%,T_Text&,Test#,T_TEXT2&
Declare OldWndProc&,DLL&,P_A&
LET DLL&=@Usedll("Send.DLL")
WindowStyle 26+512
WindowTitle "Subclassingtest"
Window 100,100 - 370,200
Let T_TEXT&=@CREATEButton(%HWND,"",30,80,300,30)
Let T_TEXT2&=@CREATEButton(%HWND,"Ende",30,120,300,30)
Waitinput
Set("FastMode", 1)
OldWndProc& = ~GetWindowLong(%hWnd,~GWL_WNDPROC)
LET P_A&=@GetProcAddress(DLL&,"_timer@16")
~SetWindowLong(%hWnd,~GWL_WNDPROC,@ProcAddr("Sub",4))
Ende%=0
TimerID&=~SetTimer(%HWND,333,20,P_A&)
Print TimerID&
WhileNot Ende%
WaitInput
If @Buttonclicked(T_TEXT&)
Einstellungen
Endif
If @Buttonclicked(T_TEXT2&)
~KillTimer(%HWND,333)
Ende%=1
Freedll DLL&
Endif
Wend
End
-Proc Einstellungen
Proc Einstellungen
Declare hD%, hA%, hB%, OK%, hTime%
Declare hF1%, hT1%
Clear OK%
Dialogfenster erzeugen
hD% = @Create("Dialog",%hWnd,"Einstellungen",%WinLeft+80,%WinTop+155,230,190)
hD% = @Control("Dialog","Einstellungen",$14C80084,%WinLeft+80,%WinTop+155,230,190,%HWND,0,%HINSTANCE,$101)
hF1% = @Create("Font","Arial",16,0,0,0,0)
hT1% = @Create("Text",hD%,"Einstellungen...",10,10,220,20)
SetFont hT1%,hF1%
hTime% = @Create("TimeEdit", hD%, "00:00:00", 10, 35, 70, 24)
hB% = @Create("Button",hD%,"&Nachstellen",10,120,100,28)
hA% = @Create("Button",hD%,"&Abbrechen",120,120,100,28)
WhileNot Ok%
WaitInput
If @ButtonClicked(hB%) Nachstellen
Ok% = 1
Aktionen hier
ElseIf @ButtonClicked(hA%) Abbrechen
Ok% = 1
ElseIf (%Key = 2) ALT+F4 bzw. schließen
Ok% = 1
EndIf
EndWhile
DeleteObject hF1%
@DestroyWindow(hD%)
EndProc
Proc Sub
Parameters hWnd&,Message&,wParam&,lParam&
If Message&=$401
Inc Timer_Busy%
Settext T_Text&,"Timer: " + @str$(Timer_Busy%) + " Durchläufe"
Return ~CallWindowProc(OldWndProc&,hWnd&,Message&,wParam&,lParam&)
Else
Return ~CallWindowProc(OldWndProc&,hWnd&,Message&,wParam&,lParam&)
EndIf
EndProc
KompilierenMarkierenSeparierenDEF @GetDlgCtrlID(1) !"USER32","GetDlgCtrlID"
DEF @ButtonClicked(1) @GetDlgCtrlID(@&(1))=-%MENUITEM
DEF @GetProcAddress(2) !"KERNEL32","GetProcAddress"
Testprogramm Timer
Profan Version 9
$H Windows.ph
-Main----------------------------------------------------------------
Declare Timer_Busy%,Ende%
Declare TimerID&,Create%,T_Text&,Test#,T_TEXT2&
Declare OldWndProc&,DLL&,P_A&
LET DLL&=@Usedll("Send.DLL")
WindowStyle 26+512
WindowTitle "Subclassingtest 2"
Window 100,100 - 370,200
Let T_TEXT&=@CREATEButton(%HWND,"",30,80,300,30)
Let T_TEXT2&=@CREATEButton(%HWND,"Ende",30,120,300,30)
Waitinput
Set("FastMode", 1)
OldWndProc& = ~GetWindowLong(%hWnd,~GWL_WNDPROC)
LET P_A&=@GetProcAddress(DLL&,"_timer@16")
~SetWindowLong(%hWnd,~GWL_WNDPROC,@ProcAddr("Sub",4))
Ende%=0
TimerID&=~SetTimer(%HWND,333,25,@ProcAddr("Sub",4))
Print TimerID&
WhileNot Ende%
WaitInput
If @Buttonclicked(T_TEXT&)
Einstellungen
Endif
If @Buttonclicked(T_TEXT2&)
~KillTimer(%HWND,333)
Ende%=1
Freedll DLL&
Endif
Wend
End
-Proc Einstellungen
Proc Einstellungen
Declare hD%, hA%, hB%, OK%, hTime%
Declare hF1%, hT1%
Clear OK%
Dialogfenster erzeugen
hD% = @Create("Dialog",%hWnd,"Einstellungen",%WinLeft+80,%WinTop+155,230,190)
hD% = @Control("Dialog","Einstellungen",$14C80084,%WinLeft+80,%WinTop+155,230,190,%HWND,0,%HINSTANCE,$101)
hF1% = @Create("Font","Arial",16,0,0,0,0)
hT1% = @Create("Text",hD%,"Einstellungen...",10,10,220,20)
SetFont hT1%,hF1%
hTime% = @Create("TimeEdit", hD%, "00:00:00", 10, 35, 70, 24)
hB% = @Create("Button",hD%,"&Nachstellen",10,120,100,28)
hA% = @Create("Button",hD%,"&Abbrechen",120,120,100,28)
WhileNot Ok%
WaitInput
If @ButtonClicked(hB%) Nachstellen
Ok% = 1
Aktionen hier
ElseIf @ButtonClicked(hA%) Abbrechen
Ok% = 1
ElseIf (%Key = 2) ALT+F4 bzw. schließen
Ok% = 1
EndIf
EndWhile
DeleteObject hF1%
@DestroyWindow(hD%)
EndProc
Proc Sub
Parameters hWnd&,Message&,wParam&,lParam&
Inc Timer_Busy%
Settext T_Text&,"Timer: " + @str$(Timer_Busy%) + " Durchläufe"
EndProc
KompilierenMarkierenSeparieren Der Fehler hat also wohl nichts mit Subclassing zu tun - oder was meinst du genau? |
| | | | |
| | | | - Seite 4 - |
| | | [quote:19dfeaab2b=Frank Abbing][quote:19dfeaab2b]Wie gesagt: Bitte Testen! Interessiert mich brennend. Bau mal die Callback in eine DLL - dauert ja nicht lange...[/quote:19dfeaab2b] Ich hatte das schon gemacht. Meine Dll hat einen Thread erzeugt und dieser hat eine profansche Callbackroutine aufgerufen. Nach mehreren Aufrufen brach Profan mit den sonderlichsten Fehlermeldungen ab. Je kürzer die Spanne der Aufrufe, desto schneller kamen die Fehler.[/quote:19dfeaab2b] Hallo Frank...
Endlich versteht mal einer, was ich sage . Hab deinen Beitrag leider erst jetzt gelesen. Dieses Problem ist mir ebenfalls bekannt - das liegt aber ganz woanders und läßt sich recht einfach umgehen (siehe Rolf). |
| | | | |
| | | So Andreas,
wer nicht hören kann muß fühlen.
Im Grunde gehen unsere Meinungen ja dahingehend auseinander das ich sage, das es grundsätzlich an procaddr liegt, weil dies die Schnittstelle ist dazu das von aussen Prozeduraufrufe injiziert werden können und Du meinst das es speziell mit WM_Timer zu tun hat.
Also habe ich das ganze ohne Wm_timer gelöst, ein Call wird von einer DLL direkt aufgerufen, immer und immer wieder.
Es belegt das es vokommen kann, das wenn eine proc die per procaddr verfügbar gemacht wurde, extern aufgerufen wird, xprofan sich verhäddert. Ohne ProcAddr wäre dies ja nicht möglich.
Hier der Code zum Selbertesten, unten ne versaute Dll.
Es hat demzufolge nichts mit der Thread-Unit zu tun und auch nichts mit wm_timer, weshalb ich den Thread auch aus dem Thread-Unit-Bereich entfernt, und nach Programmierung geschoben habe. KompilierenMarkierenSeparierenDef @Getdlgctrlid(1) !"USER32","GetDlgCtrlID"
Def @Buttonclicked(1) @Getdlgctrlid(@&(1))=-%Menuitem
Testprogramm Timer
Profan Version 9
$H Windows.ph
-Main----------------------------------------------------------------
Declare Timer_busy%,Ende%
Declare Timerid&,Create%,T_text&,Test#
Windowstyle 26
Windowtitle "Timertest PHU-60"
Window 100,100 - 370,200
Cls
Let T_TEXT&=@CREATETEXT(%HWND,"",30,30,300,30)
-Menue---------------------------------------------------------------
Popup "&Programm"
Appendmenu 108,"&Einstellungen"
Appendmenu 109,"&Ende"
Ende% = 0
Timer setzen (4x pro Sekunde, 250ms)
Thread.start 1,1
declare h&
h&:=usedll("thread2.dll")
h&:=external("kernel32","GetProcAddress",h&,"dodo")
external("thread2.dll","f",procaddr("thread.do",0),h&)
Whilenot Ende%
Waitinput
If @Menuitem(108)
Einstellungen
Endif
If @Menuitem(109)
Thread.stopall
Ende% = 1
Endif
Wend
End
-Proc Einstellungen
Proc Einstellungen
Declare Hd%, Ha%, Hb%, Ok%, Htime%
Declare Hf1%, Ht1%
Clear Ok%
Dialogfenster erzeugen
Hd% = @Create("Dialog",%Hwnd,"Einstellungen",%Winleft+80,%Wintop+155,230,190)
Hf1% = @Create("Font","Arial",16,0,0,0,0)
Ht1% = @Create("Text",Hd%,"Einstellungen...",10,10,220,20)
Setfont Ht1%,Hf1%
Htime% = @Create("TimeEdit", Hd%, "00:00:00", 10, 35, 70, 24)
Hb% = @Create("Button",Hd%,"&Nachstellen",10,120,100,28)
Ha% = @Create("Button",Hd%,"&Abbrechen",120,120,100,28)
Whilenot Ok%
Waitinput
If @Buttonclicked(Hb%) Nachstellen
Ok% = 1
Aktionen hier
Elseif @Buttonclicked(Ha%)Abbrechen
Ok% = 1
Elseif (%Key = 2)ALT+F4 bzw. schließen
Ok% = 1
Endif
Endwhile
Deleteobject Hf1%
@Destroywindow(Hd%)
Endproc
-Prozedur die in bestimmten Zeitintervallen ausgefuehrt wird (4x pro Sekunde)
Proc Thread.do
Parameters N&
Dim Test#,1000000
Inc Timer_busy%
Locate 5,5
Print "Timer:" + @Str$(Timer_busy%) + " Durchläufe"
Settext T_Text&,"Timer:" + @str$(Timer_Busy%) + " Durchläufe"
Dispose Test#
Endproc
|
| | | | |
| | | Hallo IF...
Im habe ich den Eindruck, wir reden im Prinzip von der selben Sache , denken aber beide nicht zuende . Hast du dir schon mal überlegt, warum der Fehler beim Verwenden von Set(FastMode, 1) nicht mehr auftritt ? Wenn das wirklich bei jedem Callback auf eine Profanfunktion vorkommt (das glaube ich dir, auch ohne den Quelltext der DLL zu sehen), müßte man unbedingt genau wissen, bei welchen Profanfunktionen da Gefahr besteht. Ich habe hier Stundenlang mit Writeini und Readini$ herumexperimentiert, ohne (zum Glück) einen Fehler zu erzeugen. Wenn das wirklich sogar (laut Roland) beim direkten Aufrufen von APIs passieren könnte, gibt es eigentlich gar keine Möglichkeit, das Messagehandling beizubehalten und etwas anderes gleichzeitig ablaufen zu lassen.
Das es an der Häufigkeit des Aufrufens der Prozedur liegt, kann ich nicht bestätigen. Je weniger die Prozedur aufgerufen wird, umso geringer ist die Wahrscheinlichkeit, das ein Fehler passiert - die Fehler passieren aber doch. In TNT wird ebenfalls ein Callback verwendet - das Programm verwende ich laufend, um irgendetwas in Windows zu untersuche. Am Anfang traten, egal wie oft der Callback aufgerufen wurde, immer irgendwelche Fehler auf. Seit ich dort einige Profanfunktionen an eine andere Stelle verschoben habe (wo sie keine Probleme mehr machen), ist Ruhe. |
| | | | |
| | | [quote:3974012546]Hast du dir schon mal überlegt, warum der Fehler beim Verwenden von Set(FastMode, 1) nicht mehr auftritt ? [/quote:3974012546] Das ist Unsinn Andreas, es hat auch nichts mit dem Fastmode zu tun.
Es liegt einfach an der Umsetzung von procaddr - ich habe mir meine Betrachtungsweise bestätigen lassen.
Im FastMode treten natürlich selbige Probleme auf! |
| | | | |
| | | Nachtrag: Gefahr besteht grundsätzlich bei allen ProfanFunktionen, die Gefahr erhöht sich - ich sag mal plump - aus desto mehr Aufrufen die Funktion intern besteht.
Diese Dinge von denen Du berichtest - sagen wir es sind Neben/Folgeerscheinungen. |
| | | | |
| | | Hallo IF...
Erst mal besten Dank für deine Bemühungen. Sollte das so stimmen (und das heißt jetzt nicht, das ich dir das nicht glaube), ist das echt eine Hiobsbotschaft - im Klartext bedeutet das ja u.a. folgendes: - Es ist in keiner Weise möglich nur mit Profan irgendetwas (gleichzeitig) fehlerfrei ablaufen zu lassen. - Es ist nicht möglich, mit Profan einen vernünftigen Service zu schreiben. - Eine vielzahl an APIs kann man mit Profan nicht verwenden (SendMessageCallback, alle Timer mit Callbacks, EnumThreadWindows, EnumWindows....)
Eignet sich Profan überhaupt dann zum Programmieren? Mal angenommen, muß in bestimmten Zeitabständen etwas über einen Callback dokumentieren und mein Programm fummelt gleichzeitig mit RegLoadKey / RegUnloadKey in der Registry rum (so wie RegEdt32 das tut), wer kommt dann für den Schaden an fremden Rechnern oder Systemen auf? Sollte man mit Profan programmierte Programme dann überhaupt in Umlauf bringen? Das muß sich schnellstens ändern! |
| | | | |
| | | Naja! Die Ausnahme - in der es keinerlei Probleme gibt - sind halt Funktionen welche eine ProcAddr benötigen aber sich erst beenden wenn die Arbeit geschehen ist! Roland hat ProcAddr eigendlich auch nur so gedacht!
Hier z.B. dieses Beispiel: [...]
Also Probs gibts nicht, wenn die Funktion die Proc hinter der ProcAddr aufruft, dies auch nur tut solange sie selbst noch läuft.
Was die Gleichzeitigkeit damit betrifft bedeutet dies für alle anderen Fälle das die Funktion ProcAddr ungeeignet ist. Leider! |
| | | | |
| | | [quote:0f571140cc=iF]Naja! Die Ausnahme - in der es keinerlei Probleme gibt - sind halt Funktionen welche eine ProcAddr benötigen aber sich erst beenden wenn die Arbeit geschehen ist! Roland hat ProcAddr eigendlich auch nur so gedacht! [/quote:0f571140cc] Also alle Enum-Funktionen machen keine Probleme. [quote:0f571140cc=iF] Also Probs gibts nicht, wenn die Funktion die Proc hinter der ProcAddr aufruft, dies auch nur tut solange sie selbst noch läuft. [/quote:0f571140cc] Also gibts u.a. mit SendMessageCallback Probleme. Das Schreiben sämtlicher Services würde ebenfalls darunter fallen und Probleme machen. Eine vernünftigen Taskmanager kann man dann ebenfalls nicht schreiben. [quote:0f571140cc=iF] Was die Gleichzeitigkeit damit betrifft bedeutet dies für alle anderen Fälle das die Funktion ProcAddr ungeeignet ist. Leider![/quote:0f571140cc] Das ist sehr schlimm. Überhaupt einen Taskmanager zu schreiben, ist also nicht möglich. Den Speicherverbrauch mehrere Prozesse im Auge zu behalten, ebenfalls nicht. Vernünftige Registryeditoren fallen wohl auch flach - während man Unterschlüssel auflistet, könnte man sein Programm nur schwer bedienbar halten. Eine Uhrzeit in meinem Programm einzublenden - geht nicht. Wenn sich das wirklich nicht mit Set(FastMode, 1) umgehen läßt, schmeiße ich Profan lieber erst mal in die Ecke. Diese Problem muß unbedingt besser dokumentiert oder am besten ganz beseitigt werden - da kann man ja in Teufelsküche kommen. |
| | | | |
| | | Naja man munkelt es könnte bald Abhilfe geben. ;)
Da bleibt wohl nichts weiter als die Erkenntnis - und etwas warten...
Zumal - das ganze wird eigendlich durch Dich aufgebauscht - das muss ich auch mal klar sagen!
Es ist tatsächlich nichtmal halb so wild!
Ich schreibe sehr viele Programme welche ProcAddrs nutzen - ich hatte noch kein solches Phänomen - muss aber auch dazu sagen - ich bin natürlich geübt darin mir sehr gut vorzustellen wie ein Source den ich schreibe genau Abläuft - und verhindere damit natürlich schon unbewusst so manch Komplikationen - zumal mir das ProcAddrProblem wie bereits oft erwähnt nicht neu ist.
Einfache verfügbare Beispiele - schon einen derartigen Fehler in Konstantinopel oder Okrea herbeiführen können? Ich glaube nein.
Das Schreiben von ganzen Hives oder grobe RegÄnderungen würde ich - egal in welcher Sprache - eh nicht so einfach draufzu abarbeiten lassen. Sowas würde ich immer in einen Pool tun welcher abgearbeitet wird wenn die Luft rein ist. Machs Dir also nicht zu leicht!
Du sprichst halt sehr spezielle Sonderfälle an - da mag es natürlich sein das die ProcAddr nicht safe ist. Für diese Sonderfälle hast Du aber als Programmierer genügend Ausweichmethoden zur Hand.
Alles geht nunmal in keiner Sprache - wohlbemerkt - ein safe ProcAddr kann ich mir vorstellen wird es in XProfan geben! |
| | | | |
| | Sebastian König | Hallo Andreas,
[quote:afe202e11c](...) Das ist sehr schlimm. Überhaupt einen Taskmanager zu schreiben, ist also nicht möglich. Den Speicherverbrauch mehrere Prozesse im Auge zu behalten, ebenfalls nicht. Vernünftige Registryeditoren fallen wohl auch flach - während man Unterschlüssel auflistet, könnte man sein Programm nur schwer bedienbar halten. Eine Uhrzeit in meinem Programm einzublenden - geht nicht. Wenn sich das wirklich nicht mit Set(FastMode, 1) umgehen läßt, schmeiße ich Profan lieber erst mal in die Ecke.[/quote:afe202e11c] Als Workaround kannst Du ja erstmal die aktuelle Profan2Cpp-Beta nehmen . Damit tritt die Problematik schließlich nicht auf, wie wir [...] schon diskutiert haben...
MfG
Sebastian |
| | | | |
| | | Habe sowieso vor, mir Profan2Cpp zuzulegen. |
| | | | |
|
AntwortenThemenoptionen | 4.248 Betrachtungen |
ThemeninformationenDieses Thema hat 4 Teilnehmer: |