Leaderboard
Popular Content
Showing content with the highest reputation on 02/14/23 in Posts
-
Important hint regarding LSP Yesterday I noticed that with both Delphi 10.4 and Delphi 11, an invalid path reliably knocks out the LSP. (Yes, this is reported and goes its way). This invalid path can be at least in the system PATH, the library path and unfortunately already simply the search path. You can easily test this yourself by entering a non-existent path there and restart Delphi. Important: If you correct it, you may have to restart Windows. For some reason it is not always enough to restart Delphi and the DelphiLSP.exe (even if the system PATH is not changed). I haven't looked into that yet and it doesn't always happen.
-
I don't know if you'd believe this but I actually 'solved' (I think) my problem by going into the registry and taking a look at which path was used. As I had already a BDE installed before and installing the 10.3 BDE added a new Borland Shared in my Program Files directory. I went to HKLM\Software\Winw6432Node\Borland\Database Engine, and noticed that CONFIGFILE01 key was pointing to c:\ProgramData\Common Files\Borland\BDE\IDAPI.CFG, whereas DLLPATH was c:\program files (x86)\Common Files\Borland Shared\BDE. I removed the "Shared" and now both 10.2 and 10.3 can run. Planning to remove the Borland Shared directory in a bit after a bit of testing. Thanks Ed
-
Well, being the best it has ever been does not really mean it will be great. It simply means it wont be as bad as it is now.
-
Thank you, I didn't know that existed. I will create a bug report and link it here when done. Yes I just recreated the same behaviour with the host application written in Delphi. Here is the full code: program app; {$APPTYPE CONSOLE} uses Winapi.Windows; var lib: HMODULE; res: Boolean; begin while True do begin lib := LoadLibraryA('lib.dll'); if lib = 0 then begin WriteLn('LoadLibraryA failed'); Exit; end; res := FreeLibrary(lib); if res = False then begin WriteLn('FreeLibrary failed'); Exit; end; lib := 0; end; end.
-
Marco Cantu has written a blog where exactly this topic was discussed. https://blog.marcocantu.com/blog/2022-december-suggestions-help-delphi-compiler.html
-
If you don't need to access Paradox, only DBF, you can try TDbf. See If you need SQL queries, use FireDAC LocalSQL witf TDbf.
-
Important hint regarding LSP Yesterday I noticed that with both Delphi 10.4 and Delphi 11, an invalid path reliably knocks out the LSP. (Yes, this is reported and goes its way). This invalid path can be at least in the system PATH, the library path and unfortunately already simply the search path. You can easily test this yourself by entering a non-existent path there and restart Delphi. Important: If you correct it, you may have to restart Windows. For some reason it is not always enough to restart Delphi and the DelphiLSP.exe (even if the system PATH is not changed). I haven't looked into that yet and it doesn't always happen.
-
Ugh, don't you just hate it when that happens?
-
More than 10% from 12500 installations in last year are Windows 7 and 8
-
But this doesn't work for Windows 7 from what I understand. We used Chrome approach for this and avoided elevation to write in 'Program files'. Elevation is necessary only first time at installation when we create a task in scheduler on the SYSTEM account. Actually two tasks: one with a day trigger and one with a trigger that can be started from our app at demand.
-
You have to store your data somewhere right? Could be registry, text file, DB. etc. I choose binary files because you save your data "as it is". No need to convert back and forth from (for ex) TDateTime to string and then back. You just save the TDateTime as it is (double, I think). That's it! You use "padding". At the end of your file, you keep something like 64 bytes empty. You can put later whatever you want there. Make the padding large if you know your Object is still under design and it will change. If your object changes dramatically, you use file versioning: each binary file has a header. You detect which file version the user presents to you and you load the appropriate decoder for that version. I used this for the last 20 years. 1 gazillion times faster than a DB. Easy to write. No more conversions between data types. I have some libraries for that https://github.com/GodModeUser This is for ex a list of orders (TOrders). It will save/load all orders in the list. The TOrder is quite complex but the streaming is handle just by one line of code (load/save). {------------------------------------------------------------------------------------------------------------- I/O STREAM -------------------------------------------------------------------------------------------------------------} procedure TOrders.Load(IOStream: TCubicBuffStream; Drivers: TObject; Products: TProducts); VAR i, iCount: Integer; begin Assert(Drivers <> NIL); Assert(Products <> NIL); if IOStream.ReadHeader(StreamSignature) <> 1 then RAISE Exception.Create('Invalid TOrders header!'); iCount:= IOStream.ReadInteger; { Total items in this list } IOStream.ReadPadding(1024); { Write each orders } for i:= 0 to iCount-1 DO begin VAR Order:= CreateNewOrder; Order.Load(IOStream); end; end; procedure TOrders.Save(IOStream: TCubicBuffStream); VAR i: Integer; begin IOStream.WriteHeader(StreamSignature, 1); { Local header } IOStream.WriteInteger(Count); { Total items in this playlist } IOStream.WritePadding(1024); { WRITE EACH ITEM } for i:= 0 to Count-1 DO Self[i].Save(IOStream); end; See how I reserve space for the future with WritePadding/ReadPadding. Also observe the Header of the file (StreamSignature) followed by version umber (1). Easy-peasy, instant objects to file 🙂
-
Nested TParallel.For: Immediate deadlock
Dalija Prasnikar replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
The problem happens when outer For loop consumes all available threads and hits maximum where no new threads are being allocated for newly requested task. And then if inner tasks cannot get free thread to run, they cannot complete their job. I have test case that will break more easily as number of needed threads is higher, and sleep also increases the time inner thread runs and gives more time for outer for loop to consume all available threads. Using separate pool for inner for loop solves the problem. This can still be an issue if you have code that indirectly uses nested parallel loops. begin var counter := 0; var pool := TThreadPool.Create; const COUNT = TThreadPool.Default.MaxWorkerThreads * 4; TParallel.For( 0, Pred(count), procedure(i: Int64) begin TParallel.For( 0, Pred(count), procedure(i: Int64) begin TInterlocked.Increment(counter); Sleep(10); end , pool); end ); Writeln(counter); Readln; end. Probably the best solution for parallel for loops that can spawn too many tasks would be to create dedicated thread pool for each loop. The cost of creating a thread pool is not big when dealing with longer running tasks. And for fast running tasks, like in this example, parallel loop is overkill anyway as it can run slower than simple for loop in single task. -
exception message : Error connecting with SSL. EOF was observed that violates the protocol.
Remy Lebeau replied to david_navigator's topic in Indy
Yes, I do, and that is a VERY old version of OpenSSL, you need to upgrade. Indy currently supports up to 1.0.2u dated 21/12/2019, which you can find at https://github.com/IndySockets/OpenSSL-Binaries/ Work on supporting 1.1.x is in progress: https://github.com/IndySockets/Indy/pull/299 The Method property is deprecated, you should be using the SSLVersions property instead. TLS 1.0 has been (almost) completely phased out of modern servers. Most modern servers support, if not require, TLS 1.2, so that really should be your minimum going forward nowadays. You should also have TLS 1.1 enabled as a fallback, just in case, but even that is being phased out as well. To enable multiple TLS versions with the Method property, you would have to set it to sslvSSLv23, which will set the SSLVersions property to all SSL/TLS versions supported by Indy (including SSL 2.0, SSL 3.0, and TLS 1.x), but it is better to use the SSLVersions property directly (ie, don't enable SSL 2.0 and 3.0 anymore), eg: SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; Having multiple TLS versions enabled at a time will allow OpenSSL to negotiate the highest version that both client and server support. That being said, on a side note, you do not need to assign ANY of the following SSLIOHandler properties, as Indy handles them internally for you: Setup the necessary Host/Port only in the client component, ie TIdIMAP4. The Connect() method will then copy them into the IOHandler as needed.