Jump to content

Der schöne Günther

Members
  • Content Count

    693
  • Joined

  • Last visited

  • Days Won

    12

Everything posted by Der schöne Günther

  1. Der schöne Günther

    RIO: Start Debug Session changes source

    I was talking about a "version control" system that helps you keeping track of what files were changed, when, and why. Notable examples include Git, Mercurial or the good old Subversion.
  2. Der schöne Günther

    RIO: Start Debug Session changes source

    Did you really add your .res file to your project? I think it's an auto-generated one and you should neither have it in source control, nor added to your project...
  3. Der schöne Günther

    Funny Code in System.Types

    I think it was Nick Hodges who called out for Embarcadero to make their unit tests open source and let the community contribute. Unfortunately, not much happened. Personally, I assume that there are unit tests, but only very few. Otherwise, things like that System.Generics.Collections disaster with XE8 certainly wouldn't have happened...
  4. Der schöne Günther

    IDE can not create ancestor TFrame

    I have never done that but thank you for encouraging me! I just found out that, at least in my special case, the IDE runs into this error when you Are using the form designer Edit -> Hide non-visual components (Ctrl+H) Close the project After that, the registry path HKEY_CURRENT_USER\Software\Embarcadero\BDS\17.0\Form Design has "Show NonVisual Components"="False" This appears to be deadly. Just setting this value back to "True" makes my RAD Studio work again. I am on Delphi 10.0 Seattle. Not sure if it also affects other versions.
  5. Der schöne Günther

    IDE can not create ancestor TFrame

    Can you still open the ancestor frame in the form designer? Several times a week, my IDE somehow corrupts itself so that the form designer does no longer work for inherited frames. I then load a backup of my registry for HKCU\Software\Embarcadero\BDS\17.0 and everything is fine again for the next few days. I'm on 10 Seattle. Apart from that, it sometimes also just corrupts the DFM files for a frame. Your version control should be able to show you what happened.
  6. Der schöne Günther

    track process execution

    Your question is relatively vague. I guess the technical definition of "programs executed" means "whenever the WinApi CreateProcess(..) routine is called"? In that case, the Microsoft or MahdiSafsafi libraries are probably the fastest way: https://github.com/MahdiSafsafi/DDetours https://github.com/microsoft/detours/wiki/Using-Detours
  7. You can use the RTTI to evaluate certain properties of interace types. Please see the following snippet: program Project1; uses System.Rtti; var context: TRttiContext; rttiInterface: TRttiInterfaceType; begin context := TRttiContext.Create(); rttiInterface := context.GetType( TypeInfo(IInterface) ) as TRttiInterfaceType; rttiInterface.IntfFlags; // is [ifHasGuid] rttiInterface := context.GetType( TypeInfo(IInvokable) ) as TRttiInterfaceType; rttiInterface.IntfFlags; // is [3]. 3 is not a valid enum value end. You can put a breakpoint on both lines with a comment for evaluating the value of IntfFlags yourself. IInvokable (and every interface that derives from it) has an undocumented value of "3". What does it mean? I have not been able to find anything in the source code. Clearly, System.TypInfo.TIntfFlag is declared as TIntfFlag = (ifHasGuid, ifDispInterface, ifDispatch);
  8. Der schöne Günther

    Undocumented "Interface flag" for IInvokable?

    I wonder where this value actually comes from. I guess not from RTL code that exists as a .pas file?
  9. Der schöne Günther

    Is it possible to know when a TObject is instanciated/freed?

    Maybe this could be related? http://blog.marcocantu.com/blog/2017-june-delphi-packages-creators-update.html
  10. Der schöne Günther

    RadStudio Roadmap 2019

    What's so interesting about that? I still don't get quite behind that language server thing. I see that they will be able to delegate things like Code Completion and Error Insight to some external process in the background. Is that also going to work the other way round? Will tools like VS Code be able to access Delphi's debugger? I am already looking forward to 10.4 because of High DPI. Maybe I will once again be able to use Delphi at home, not just at work.
  11. Consider the following: uses System.Threading; procedure TForm1.Button1Click(Sender: TObject); var task: ITask; begin task := TTask.Run( procedure() begin raise EProgrammerNotFound.Create('test'); end ); try task.Wait(); // << raises EAggregateException except ShowMessage('ex'); end; task.Wait(); // no exception. returns true // task.Status is now TTaskStatus.Exception end; I find this irritating. Why does waiting for a task raise an exception one time, but not the other? Apart from the fact that the Embarcadero documentation on ITask.Wait(..) does not even mention an exception should be expected, I guess they (once again) modelled it after .NET's Task.Wait(..) method which clearly states an exception is to be expected if the task was cancelled or failed with an exception. Some fine gentleman even reported this to Embarcadero almost five years back: https://quality.embarcadero.com/browse/RSP-9548 But two years later, it was closed as "Works as expected". I still don't understand. Can someone elaborate? I believe the implementation is wrong.
  12. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    Thank you for taking the time to explain. It sounds like a good point, although a bit artificial 😉 And I have trouble achieving just that. Even with something like procedure TForm1.Button1Click(Sender: TObject); var task: ITask; e: Exception; begin event := TSimpleEvent.Create(); task := TTask.Run( procedure() begin raise EProgrammerNotFound.Create(EmptyStr); end ); try try task.Wait(); finally task := nil; end; except e := Exception( AcquireExceptionObject() ); end; end; The task still lives. Maybe because the default thread pool still has a reference to it.
  13. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    Thank you for replying. If that can happen, then yes, then that won't work. But right now, I have no idea how that could happen, to be honest. In order to catch the exception, I have to call .Wait() on the task - Meaning I have to have a reference to it. Meaning the task cannot be freed yet. What am I missing?
  14. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    And because of that, it's even more important the exceptions do not get lost and you get a reliable and reproducible behaviour. 😎 As so often, it seems to be modelled after .NET. And what .NET does (raise the exception(s) every time you wait for the task) is perfectly achievable with Delphi. I just don't understand why they took this weird approach.
  15. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    There is no need to change anything about raising exceptions or lifetime management of exceptions. It's just that an EAggregateException always owns the exception it refers to. I believe that should be optional. Raise the exception normally, or acquire ownership and free it later - It doesn't matter. As long as the task owns its exceptions, not the EAggregateException. You can do with the AggregateExcption whatever you like. It's not the same, but TThread is similar. It has a FatalException property you can query for the exception that happened in the thread. The exception is owned by the thread. It is there for as long as the thread object is alive. With the way tasks are implemented, the first one to call .Wait() on a task gets the exceptions - After that, they're gone. It makes no sense.
  16. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    But "the exception" is an artificially generated EAggregateException that references exceptions that are already stored. The "true" exceptions have never been raised directly. There would be nothing wrong with raising an EAggregateException that does not own the exceptions it referred and instead the task can free those exceptions when it is destroyed. Which is what was suggested in https://quality.embarcadero.com/browse/RSP-9548. Wouldn't that solve all those problems?
  17. Der schöne Günther

    ITask.Wait() behaving differently when called multiple times

    Does that mean 10.3 raises an exception for both times? Because I accidentally typed it would raise an EOperationCancelled. It does, in fact, properly raise an EAggregateException. But just for the first time.
  18. Consider the following: I have a method that raises an EAggregateException that only contains one inner exception In my try block, I would like to extract the one inner exception and raise this instead. procedure raiseAggregate(); var innerExceptions: TArray<Exception>; aggregateException: EAggregateException; begin innerExceptions := [EProgrammerNotFound.Create('hello')]; aggregateException := EAggregateException.Create(innerExceptions); raise aggregateException; end; procedure TForm1.Button1Click(Sender: TObject); begin try raiseAggregate(); except on e: EAggregateException do begin if (e.Count = 1) then raise e.InnerExceptions[0] // <<< that would be too easy else raise e; end else raise; end; end; How do I do this? I cannot simply use raise e.InnerExceptions[0] because e gets destroyed at the end of the try..except block. This is a problem because e owns its inner exceptions. When e gets destroyed, I have basically raised a destroyed exception. In case you're not familiar with the System.Threading.EAggregateException, you check the .NET documentation. Embarcadero documentation does not exist.
  19. Der schöne Günther

    Is it possible to raise an aggregated exception?

    So far, the only solution I have come up with is ripping out the wanted exception with a class helper 🤷‍♂️ and then raise this exception instead. function EAggregateExceptionHelper.Extract(const index: NativeInt): Exception; var newArray: TArray<Exception>; arrayIndex: NativeInt; begin newArray := []; Result := nil; with self do begin for arrayIndex := Low(FInnerExceptions) to High(FInnerExceptions) do if(arrayIndex = index) then Result := FInnerExceptions[arrayIndex] else newArray := newArray + [FInnerExceptions[arrayIndex]]; FInnerExceptions := newArray; end; end;
  20. Der schöne Günther

    Git UI tools

    I don't use Visual Studio for Git, but Visual Studio Code with GitLens. And, from time to time, the Windows explorer integration from TortoiseGit. As far as I recall, Visual Studio didn't even have support for Git stashes until VS 2019.
  21. Der schöne Günther

    Forked VSCode for Delphi

    There's not just VSC. Have a look at this: I honestly couldn't care less about the form designer. As horrible as it actually is, it's probably just too much work to completely rewrite it for another environment. Proper debugging capabilities are way more important.
  22. Der schöne Günther

    Touchscreen signature

    Are you sure it's a capacitive touch screen or something more sophisticated that works with a "proper" pressure-sensitive pen? There are quite a lot of W10 devices that have an additional digitizer for pen input.
  23. Der schöne Günther

    Decorating read-only controls

    Interesting read: https://ux.stackexchange.com/q/84715
  24. Der schöne Günther

    Trouble with (very) simple XML-parsing

    Doesn't getElementsByTagName(..) only list direct descendants? You will either have to search recursively, or use something like an XPath expression to get all the nodes you are interested in.
  25. Der schöne Günther

    ANN: Find leaks in Delphi and C++ with Deleaker

    That looks very exciting, but I do find the prices a bit steep 😶 Does one license work with both RAD Studio and Visual Studio integration? For VS, does it find leaks for C++/CLI Mixed mode applications?
×