Jump to content

Eric Grange

Members
  • Content Count

    20
  • Joined

  • Last visited

Posts posted by Eric Grange


  1. On 10/13/2023 at 1:13 PM, Uwe Raabe said:

    The order of units with initialization code are better retrieved by the C=ICODE entries instead of the C=CODE ones.

    AFAICT there are no ICODE in the map file for Delphi 64 builds.

     

    On 10/14/2023 at 7:14 PM, JGMS said:

    Hi @Eric,

    Did you manage to solve the issue altogether? [...]
    The error is in "Parent". Thereafter the error "...c0000005 ACCES_VIOLATION..." appears. Any ideas how to solve this?

    I solved the issue by not having an exception raised... And found the unit that triggered the exception through "Halt" and bisection from the unit list.

    There were 3000+ units in the whole project, but since it was during the initialization, bisecting didn't take long (add Halt to unit initialization, run and see if Halt reached or not, bisect and repeat)

    • Like 1

  2. On 10/11/2023 at 9:31 AM, Kas Ob. said:

    Why deleted ?!!

    Because the map file provides that information already.

    For instance for Win64 binaries you will see at the top of the map file lines like
     

    Detailed map of segments
    
     0001:00000000 0001C36C C=CODE     S=.text    G=(none)   M=System   ALIGN=4
     0001:0001C36C 00001944 C=CODE     S=.text    G=(none)   M=SysInit  ALIGN=4
     0001:0001DCB0 00003980 C=CODE     S=.text    G=(none)   M=System.Types ALIGN=4
     0001:00021630 00000D40 C=CODE     S=.text    G=(none)   M=System.UITypes ALIGN=4
     0001:00022370 000068BC C=CODE     S=.text    G=(none)   M=Winapi.Windows ALIGN=4
     0001:00028C2C 000006BC C=CODE     S=.text    G=(none)   M=FastMM4LockFreeStack ALIGN=4
     0001:000292E8 00000028 C=CODE     S=.text    G=(none)   M=FastMM4Messages ALIGN=4
     0001:00029310 00002570 C=CODE     S=.text    G=(none)   M=FastMM4  ALIGN=4
     0001:0002B880 00000200 C=CODE     S=.text    G=(none)   M=Winapi.WinSvc ALIGN=4
     0001:0002BA80 000007E0 C=CODE     S=.text    G=(none)   M=System.SysConst ALIGN=4
     0001:0002C260 00000040 C=CODE     S=.text    G=(none)   M=Winapi.ImageHlp ALIGN=4
     0001:0002C2A0 00000020 C=CODE     S=.text    G=(none)   M=Winapi.SHFolder ALIGN=4
     0001:0002C2C0 00000760 C=CODE     S=.text    G=(none)   M=Winapi.PsAPI ALIGN=4
    


    And the unit order is the initialization order as well as the order in the compiled binary.

    For listing at runtime my code would not really work, because it required not only manually obtaining the address of the interval Context variable, but also resolving against the map file.

    However it's possible to bundle the MAP file in the executable, and retrieve that information, the JCL's JDBG format allows that (in addition to being useful for debug stacks)
    https://stackoverflow.com/questions/6019698/access-jcl-debug-information-contained-in-executable
     

    On 10/10/2023 at 6:11 PM, Anders Melander said:

    It's free for non-commercial use. And yes, it does handle exceptions in the initialization section.

    image.png.a85ed82e2001a22b20102a7d451de64a.png

     

    Thanks, nice to know!


  3. 1 hour ago, Anders Melander said:

    Have you tried madExcept?

    No, I do not have it. Do you know if it handles exception in the initialization section ?

     

    35 minutes ago, Uwe Raabe said:

    AFAIK; the initialization order of units follows the order of the ICODE (Initialization Code-Segment) segments in the Detailed map of segments in the map file.

    You're right it does! Haha, or in the case of the 64bit map, it's just the CODE sections.

    Ah well... 🙂

    FWIW the issue was related to the TNotificationCenter, which a unit was initializing ahead of time to avoid the incorrect app name reporting (https://en.delphipraxis.net/topic/4102-embarcadero-toaster-notification-window-caption-in-win10/), and this would sometimes fail with a Delphi 10.3 exe (the issue is not present in Delphi 11.2 afaict). The issue had been in the code for about 6 months before encountering a situation where it would be problematic with a particular combo of user rights.


  4. Ok, in case anyone encounters a similar issue, here is the ghetto method I used to obtain units initialization order.
    First after the "begin" of the main, program call a procedure like [ complicated approach deleted ]

    Just use the map file as Uwe Raabe pointed below,to get the order of initialization, the detailed segments section lists the units in order of initialization.
     

     

    • Thanks 1

  5. Quote

    Can't you just step into System.InitUnits() or put a breakpoint there?


    The project has about 4000 units... this is why I would rather have a way to get a list of those units in the order InitUnits calls them, so I can bisect.
    (also the issue is infrequent, I have been unable to get it when debugging)

    If worse comes to worse, I will probably hack to get the raw InitUnits call addresses, and then resolve them to unit names with the detailed map file.


     


  6. Hi,

    I have an application that (probably) triggers an exception in one of its initialization sections, and of course that does not happen when debugging, only occasionally when in use. I know it's in a initialization because it happens before the "begin" of the main program, and after the initialization section of unit declares as the first in the "uses" of the main program.
    There is no stack trace, just an AV, and I could reproduce something similar in the debugger by having an assert or raise in an initialization section. The exception is first raised correctly, but then the RTL goes on to trigger an AV in System._IsClass. With debug DCUs the call stack looks like:
     

    System._IsClass($5DC63C0,TClass($433C10))
    System.SysUtils.RaiseExceptObject(???)
    System._RaiseAtExcept(???,???)
    System._RaiseAgain
    System.InitUnits
    System._StartExe(???,???)
    SysInit._InitExe(???)


    this happens the second time going through RaiseExceptObject, which has a line
     

    if TObject(P.ExceptObject) is Exception then


    During the first time through, TObject(P.ExceptObject) is correct, but the second time it's obviously invalid, which triggers an AV in _IsClass

    This happens with D10.3 and D11.2, both in Win32 (Runtime Error 217) and Win64 (Access violation)

    Is there a known workaround ?

    Alternatively is there a way to dump the initialization order of InitUnits so that I can bisect to the problematic initialization using a log ?
     


  7. Quote

    You can as well override the IsImageNameAvailable function for that subclass and just return False.

     

    Unfortunately there is no IsImageNameAvailable in TVirtualImageList, in the VCL it's declared like this

        property ImageNameAvailable: Boolean read FImageNameAvailable write FImageNameAvailable default True;


     


  8. 1 hour ago, Uwe Raabe said:

    Setting that to False avoids setting the ImageName property on the linking controls. You might have to clear existing ImageName values manually, though.

    Thanks, that does it for ImageName, but now the issue becomes about ImageNameAvailable property, which did not exist in Delphi 10 🙂

    The default attribute for ImageNameAvailable property is hard-coded to True, but this could be worked out by subclassing the image list, reintroducing the property, and then using the image list subclass everywhere... I will probably stick with the hook script for now.


  9. Quote

    Simple. Develop in the lowest version that you wish to support. 

     

    Hehe 🙂 might be simpler to forego the IDE and use VSCode or Notepad++ in that scenario... IDE has a tendency to consider the dfm changed even when just opening a form's code and not changing anything.

    As to why I prefer editing in Delphi 11, well, simple code navigation (ctrl+click, etc.) stops working very quickly in Delphi 10 on larger projects.
     

    Quote

    Or write a tiny command line program that scans a dfm file and removes that property.  Run that program prior to committing code to your source code repository. TortoiseSVN allows you to fully automate this by setting "hooks", I don't know about Git.


    Yes, probably the route I will be be taking, TortoiseGit has them too.

     


  10. Hi, when saving a form containing a TToolButton or a TAction, Delphi 11 saves an ImageName property in the dfm, which did not exist in Delphi 10.

    However for my particular codebase, I would like to maintain DFM compatibility across Delphi versions, so I am looking at ways to prevent Delphi 11 from saving this property (which is unnecessary: removing it from the dfm manually doesn't break anything, and actually it only gets added to forms that were edited in Delphi 11, forms never edited in Delphi 11 compile and run fine in Delphi 11).

    One approach could be having TToolBar creating a subclass of TToolButton (either in D10 to add a dummy property, or in D11 to replace the stored), but TToolButton creations are hard-coded deep into multiple TToolBar methods (like the huge TToolBar.CNNotify), so this would require basically ripping apart TToolBar, and using simple detours would be impractical due to the many private methods.

    TToolButton.IsImageStored would be simple to detour, except I would need to do it in the IDE, which would break the use cases where it's not unnecessary.

    Any other ideas or is this a dead horse ? 😕


  11. I have been looking without success for ways to prompt the user to update an app published as appx to the Windows Store, outside of making checks to my own website.

    Anyone having any success with the Windows Store API ? The reason is that I have found that the Windows Store rarely checks for updates on its own, on many user machines, opening the Windows Store app and manually checking for updates revealed they were months behind (and this include Microsoft's own apps)... This was the case on Windows 10 and Windows 11 machines.

    So I suspect that without an in-app update prompt mechanism, many users aren't and won't see updates. But it feels a bit odd having to check for updates through a parallel mechanism, and then having to redirect the user to the store via a ShellExecute....


  12. Ok solved it! For reference the relevant Microsoft is actually this one Windows 8 touchpad gesture implementation guide

    While the MS doc mentions Windows 8 and says it's obsolete, it is still very much what happens in Windows 10.

    The touchpad pan gets mapped to WM_MOUSEWHEEL (vertical) and WM_MOUSEHWHEEL (horizontal), that last one is not exposed in the VCL as of Delphi 10.3
    The pan translations come in the WheelDelta field, so they can be easily mapped to whatever you need.
     

    • Thanks 1

  13. Yes, I tried with or without the TGestureManager though the doc (https://docwiki.embarcadero.com/RADStudio/Sydney/en/Gesturing_Overview) says it shouldn't be there for interactive gestures, if there is no TGestureManager, I get zero OnGesture events (I only get windows conversions to scroll or mouse wheel events)

    The Microsoft doc (https://learn.microsoft.com/en-us/windows/win32/wintouch/windows-touch-gestures-overview) states that WM_HSCROLL & WM_VSCROLL should be received for pan, but I do not seem to get them.


  14. Hi,

    I have been trying to get a VCL application to react to touchpad two fingers pan, with absolutely no success 😕
    But two finger pan does not seem to trigger anything AFAICT.

    Simple scrolling (tap and hold) and touchpad pinch-to-zoom get translated (by Windows) into scroll events just fine.

    Though it's not a screen touch, I tried OnGesture as well, with or with a touch manager, no success there.

    The two finger pan works just fine on other applications on the same laptop (Chrome, image editors, etc.), so it's a bit like the VCL application is missing a flag or something is eating/disabling the pan functionality.

    Am I missing something obvious and Anyone got it working ? This is a Delphi 10.3 app.

×