Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 07/05/20 in Posts

  1. Mahdi Safsafi

    GExperts supports even more laziness

    @Stefan Glienke @dummzeuch I made some debugging and conclude to three place where a hook could be used : - ShowException : this is the top-level function that call DoShowException->ReportExceptionNotification. - DoShowException : this is called by ShowException and returns False(break) and True(continue). When returning continue, a call to Run is necessary in order to continue running the application. - ReportExceptionNotification: this is the best place (no need to call run) but unfortunately it inits internally a list that is used later. without calling the original method an AV would be thrown. type TShowException = procedure(Obj: TObject); TDoShowException = function(Obj: TObject): Integer; TGetExceptionMessage = procedure(Obj: TObject; var Msg: string); TReportExceptionNotification = function(Msg: Pointer; Unkown: ShortInt; Unkown2: Pointer): ShortInt; var TrampolineShowException: TShowException; TrampolineDoShowException: TDoShowException; TrampolineReportExceptionNotification: TReportExceptionNotification; GetExceptionMessage: TGetExceptionMessage; Hooked: Boolean = false; procedure ShowExceptionHooked(Obj: TObject); var Msg: string; begin { this is the toplevel function. calls DoShowException(). } GetExceptionMessage(Obj, Msg); ShowMessage(Msg); // TrampolineShowException(Obj); end; function DoShowExceptionHooked(Obj: TObject): Integer; var Msg: string; MsgResult: Cardinal; begin { DoShowException calls ReportExceptionNotificationHooked } GetExceptionMessage(Obj, Msg); MsgResult := MessageBox(0, 'Yes=continue No=Break Cancel=OriginalDialog', PChar(Msg), MB_YESNOCANCEL); case MsgResult of IDYES: begin Result := 1; // continue. // need to call Run(); end; IDNO: begin Result := 0; // break. end; IDCANCEL: begin Result := TrampolineDoShowException(Obj); // original dialog. end; end; end; function ReportExceptionNotificationHooked(Msg: Pointer; Unkown: ShortInt; Unkown2: TObject): ShortInt; var MsgResult: Cardinal; begin { this is the best place where to make a patch ... however internally, it inits a list if you don't call original function, an AV (list) will be thrown. } // type of Msg = string. MsgResult := MessageBox(0, 'Yes=continue No=Break Cancel=OriginalDialog', '', MB_YESNOCANCEL); case MsgResult of IDYES: begin Result := 0; // continue. // no need to call Run(). end; IDNO: begin Result := 1; // break. end; IDCANCEL: begin Result := TrampolineReportExceptionNotification(Msg, Unkown, Unkown2); // original dialog. end; end; end; procedure InstallHook(); var ShowExceptionPtr: Pointer; DoShowExceptionPtr: Pointer; ReportExceptionNotificationPtr: Pointer; begin if Hooked then exit; ShowExceptionPtr := GetProcAddress(GetModuleHandle('dbkdebugide260.bpl'), '@Debug@TDebugger@ShowException$qqrv'); DoShowExceptionPtr := GetProcAddress(GetModuleHandle('win32debugide260.bpl'), '@Win32debug@TNativeDebugger@DoShowException$qqrv'); @GetExceptionMessage := GetProcAddress(GetModuleHandle('dbkdebugide260.bpl'), '@Debug@TDebugger@GetExceptionMessage$qqrv'); ReportExceptionNotificationPtr := GetProcAddress(GetModuleHandle('dbkdebugide260.bpl'), '@Exceptionnotificationdialog@ReportExceptionNotification$qqrx20System@UnicodeString83System@%Set$56Exceptionnotificationdialog@TExceptionNotificationOptiont1$i0$t1$i2$%r83System@%Set$56Exceptionnotificationdialog@TExceptionNotificaTY6J18n0Wfo24G1hyGAqTA'); assert(ReportExceptionNotificationPtr <> nil); if Assigned(DoShowExceptionPtr) then begin @TrampolineDoShowException := InterceptCreate(DoShowExceptionPtr, @DoShowExceptionHooked); Hooked := true; ShowMessage('hook is installed'); end; end; procedure RemoveHook(); begin if Hooked then InterceptRemove(@TrampolineDoShowException); end;
  2. GExperts supports even more laziness I got into programming because I am lazy, I’d rather have the computer do the boring work than doing it myself. So it’s no wonder that I always liked Delphi and GExperts because both support my laziness. Today I added yet another feature to save me a key stroke or mouse click: The “Close Exception Notification” expert. You probably have encountered those libraries that always raise the same exception class on errors, or even worse, raise the generic Exception class instead of bothering to declare their own. And if I should guess, you have probably been guilty of doing that yourself (as I definitely have). Why is that a problem, you ask? Because you can’t easily ignore these exceptions during debugging. You always get this “Debugger Exception Notification” dialog, have to read it and decide whether you want to break and look at the code or ignore the exception. Read on in the blog post.
  3. Stefan Glienke

    One more memory leak and FastMM4

    Solution: Pass TRefCounting.True to AsSingleton because otherwise the container uses a very basic way to determine if the instance is reference counted or not and that is often false if it was implemented by yourself. Explanation: The container needs to know that in order to store the instance served as singleton and properly destroy it in the end: - either by letting go the interface reference if it was reference counted - or calling Free on the object reference if it was not reference counted The issue has been open for a while now and I have a few ideas but it did not make it to the top of my priority list yet: https://bitbucket.org/sglienke/spring4d/issues/237 Alternative solution: If you are using the instance as singleton why implement reference counting in the first place - it makes no sense. By the way: Stop using so many delegates if all you do is resolve all the ctor parameters yourself - that defeats the purpose of using a DI container. If you want to force the DI container to use a certain ctor then put the [Inject] attribute over the ctor- then you will get a resolve exception when it could not provide all parameters. That might be important because by default the container falls back to a less greedy ctor if it cannot provide all parameters (you can configure that behavior) which sometimes lead to defects at it always ultimately falls back to TObject.Create (RTTI cannot see that it might not be visible because information about method overloading is not available) If you want to use a certainly named service to be injected then put the [Inject(<servicename>)] attribute on the specific ctor parameter. Another way would be to use InjectConstructor in the registration and provide the parameternames (at this time you have to specify all parameters - if you want to use the default service then pass TValue.Empty or nil) - I am working on being able to provide value/servicename for individual ctor parameters because that also makes things robust agains refactorings. The code you wrote actually serves no purpose at all - it would be shorter and faster if you used pure DI instead because with all the DelegateTo calls you basically did just that. If you put a parameterless ctor into your DM class which just calls inherited Create(nil); then you can get rid of all DelegateTo calls in your registration and just let the container do its job.
  4. John Kouraklis

    Client Library for FusionAuth?

    Hi @Dan Moore, I ended up writing my own. It does not provide full cover of the API; I only added the calls I needed. I can share it with the community but need to clear it up a bit as at the moment it uses some proprietary code. I only used it for simplicity but it can be replaces with open source. Thanks John
  5. Uwe Raabe

    About missing property TComboBox.Text

    I suggest to create a class helper: type TComboBoxHelper = class helper for TComboBox private function GetText: string; public property Text: string read GetText; end; function TComboBoxHelper.GetText: string; begin Result := ''; if Selected <> nil then Result := Selected.Text; end;
  6. Der schöne Günther

    GExperts supports even more laziness

    Can I make a suggestion? I have so often tripped over ignoring an exception and then forgetting about it, the exception being ignored even days later. Would it be possible to add something like "scope" for these rules? Something like This debugger session This project Global
×