Jump to content

Remy Lebeau

Members
  • Content Count

    3001
  • Joined

  • Last visited

  • Days Won

    135

Remy Lebeau last won the day on July 8

Remy Lebeau had the most liked content!

Community Reputation

1619 Excellent

Technical Information

  • Delphi-Version
    Delphi 12 Athens

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Remy Lebeau

    TIdHTTPsServer, file transfer and network errors

    Why not simply rename or move (not copy) the original temp file to the new filename, instead of copying its data to a new file? The only way I can see that happening is if you are not sending a response to the client until after the file data has been copied to the final file, and it's taking a long time to do that copy. Clients are not going to wait around forever for a response after they send their data to the server, so you should try to send a response as soon as possible, ie when the data has been saved in the temp file, or once processing of that file has begun in the background. If that is not an option, they you have no control over the client's timeout settings on the server side, so all you can do is optimize your processing to speed it up. If your processing is going to take a long time, then return a response ASAP and then provide a separate API for the client to poll the status of the processing, ie a separate REST endpoint, or a WebSocket, etc. That has nothing to do with Indy, but with your OS and/or hard drive performance. Maybe you are writing to bad sectors, or there are other I/Os in progress that slow down the OS's handling of your file, etc. No way to diagnose that from your limited description. Also, TStream.CopyFrom() was pretty basic in 10.3. It was re-written sometime after 10.3 with more buffering logic. Also, consider using TBufferedFileStream instead of a plain TFileStream, at least. TBufferedFileStream was introduced in Delphi 10.1. That way, more of the copying process is done in memory rather than directly on the hard drive. It didn't. The client timed out and closed the connection on its end. If you are doing your file processing directly in your OnCommand handler then the server CAN'T close its end of the connection until you return control back to the server, ie by exiting the handler. Yes - don't perform long-running processes directly in your OnCommand handler that makes the client wait a long time for a response. No. Especially if different threads are working on different files. There is no timeout you can set on the server side that will affect the client's own timeouts. However, one thing you might try is TCP keepalives, not HTTP keepalives, ie via the AContext.Connection.Socket.Binding.SetKeepAliveValues() method. But, that won't prevent the client from just giving up if no response arrives in a long time.
  2. Remy Lebeau

    $DEFINE: how does it work?

    Pascal code is compiled top-down in a single pass. DEFINE, IFDEF, etc are compiler directives that are evaluated only at compile-time. The resulting code is fixed, it cannot be changed at runtime. If you try to IFDEF something before it has been DEFINE'd, the result will be False. Hence the name IF-DEFined. In any case, DEFINE/IFDEF is not the correct solution for your problem anyway. You are making a decision based on data known only at runtime, so you need to add an extra parameter to your function that is called at runtime (you need to add a Sender parameter, too), eg: function doTheReport(Sender: TObject; Bo: Boolean); begin if Bo then Result := DoCharges(true, -1, False, False, False, lg('CLOSE CHARGES'), '1', dm2.SysDate.FieldByName('date').AsDateTime) else Result := DoCharges(Sender=nil, -1, False, False, False, lg(TDsFancyButton(Sender).Caption), '', 0, dm2.SysDate.FieldByName('date').AsDateTime); end; function selectReport(Sender: TObject); begin doTheReport(Sender, Sender = good1); end; Alternatively: function doTheReport(Sender: TObject); begin if Sender = good1 then Result := DoCharges(true, -1, False, False, False, lg('CLOSE CHARGES'), '1', dm2.SysDate.FieldByName('date').AsDateTime) else Result := DoCharges(Sender=nil, -1, False, False, False, lg(TDsFancyButton(Sender).Caption), '', 0, dm2.SysDate.FieldByName('date').AsDateTime); end; function selectReport(Sender: TObject); begin doTheReport(Sender); end;
  3. Remy Lebeau

    TLS Issues and TLS3 message comming from Iindy

    That is why I suggested calling it AFTER the load had already failed the first time. But, I guess it doesn't matter, since it is unable to even load the DLLs into memory, so it will not be able to call the exported function that reports the version number. If you were using an up-to-date version of Indy, then on Windows WhichFailedToLoad() would include the error code for why SafeLoadLibrary() failed. It is clear from your screenshot that you are using an old version that does have include that error code. Offhand, that looks ok. But its hard to diagnose without knowing exactly where you got those DLLs from, and what external dependencies they actually have. If you right-click on the DLLs, what version numbers do their Properties show? And have you tried running the DLLs through any Dependency Viewer tools? You might also try using SysInternal Process Monitor to see what additional files Windows tries to access while the DLLs are being loaded. Yes, but I already mentioned the dependency issue in an earlier reply and you haven't addressed it yet. That is the most common reason for (Safe)LoadLibrary() to fail.
  4. Remy Lebeau

    Freeeee

    Is Form 1 the Main form? Closing the Main form will terminate the app. You could just hide it instead, buy why do you want to close Form 1 at all? What exactly is stopping you from accomplishing what you want? What exactly have you attempted so far that is not working for you? Do you know how to create and open forms? Do you know how to add procedures to classes, and how to call them? Sounds like you are missing some fundamentals. Try something like this unit Unit1; interface ... type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); ... end; implementation uses Unit6; ... procedure TForm1.Button1Click(Sender: TObject); begin Form6 := TForm6.Create(Application); Form6.Show; Hide; Form6.DoSomething; end; end. unit Unit6; interface ... type TForm6 = class(TForm) procedure FormClose(Sender: TObject; var Action: TCloseAction); ... public procedure DoSomething; end; var Form6: TForm6; implementation ... procedure TForm6.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; Form6 := nil; end; procedure TForm6.DoSomething; begin ... end; end.
  5. Did you try it and see if it does?
  6. RSS-3777: TListItems.AddItem() documentation is misleading
  7. Project > Options > Building > C++ Compiler > Use 'classic' Borland compiler
  8. The documentation is misleading. The properties are NOT duplicated at all. If you pass in an existing TListItem then it gets inserted as-is and becomes part of the TListView.
  9. Remy Lebeau

    TLS Issues and TLS3 message comming from Iindy

    What do the IdSSLOpenSSL.OpenSSLVersion() and IdSSLOpenSSLHeaders.WhichFailedToload() functions report after the load fails? So, the problem is in loading the DLLs themselves into memory, and not with obtaining pointers to the exported functions after the DLLs are loaded into memory? Perhaps the DLLs you were using have external dependencies (ie, VC++ runtime, etc) that were missing? Most of the DLLs on Indy's GitHub are built without external dependencies. Yes. The TLS 1.2 spec was released in 2008, and TLS 1.2 was implemented in OpenSSL 1.0.1 in 2012. What do you referring to?
  10. I cannot reproduce any memory leak with that code, but I can reproduce the caption issue. You need to add the item before changing its Caption: var Item := TListItem.Create (ListView1.Items); ListView1.Items.AddItem (Item); // <-- move here Item.Caption := SomeLinkedObject.Name; Item.Checked := SomeLinkedObject.Enabled; Item.Data := SomeLinkedObject; The reason is because setting the Caption assigns the LPSTR_TEXTCALLBACK flag on the item, which TListView needs to display the assigned String data, but AddItem() does not set that same flag. So, if you set the Caption and then Add, the flag is not set and the ListView has no text data to display. Looks like a bug, I have reported it: RSS-3772: TListItems.AddItem() does not set LPSTR_TEXTCALLBACK flag for existing TListItem
  11. Remy Lebeau

    Posix source files missing

    Same here. Do you have all of the available patches installed for 12.3?
  12. As I said earlier, you are getting the event when the new item's default state image is assigned. More specifically, when TListView.Items.Add() creates a new TListItem object and inserts it into the TListView.Items, it calls the Win32 ListView_InsertItem() function, which immediately sends the TListView a LVN_ITEMCHANGED notification before it returns. In that notification, the item's uChanged field is LVIF_STATE and the state image has changed index from 0 to 1. That condition is what fires the OnItemChecked event. The item is fully initialized from the Win32 perspective before TListView.Items.Add() returns. Anything you do extra to the item after Add() returns is optional, and is initialization from your perspective, not the Win32 perspective.
  13. The checkboxes are implemented as state images. You are getting the event when the item's initial state is assigned. Just check for the nil condition and don't access the object when it's not ready yet: procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem); begin if Assigned(Item.Data) then TSomeLinkedObject(Item.Data).Enabled := Item.Checked; end; Alternatively, disable the event when adding an item, and then re-enable the event when ready: ListView1.OnItemChecked := nil; var Item := ListView1.Items.Add; ... ListView1.OnItemChecked := ListView1ItemChecked;
  14. Remy Lebeau

    THintWindow; exposing the WMLButtonDown event

    You don't need to create an instance of your hint class. By setting the HintWindowClass variable, the VCL will instantiate your class when needed. In any case, the reason your code doesn't work is because by default THintWindow responds to WM_NCHITTEST to return HTTRANSPARENT, thus all mouse activity gets directed to the window that is underneath the hint. You can intercept WM_NCHITTEST yourself to return HTCLIENT instead, so thus your WM_LBUTTONDOWN handler will be triggered when clicking on the hint window. However, then you run into a new problem, because as soon as the mouse enters the hint window, it effectively leaves the control underneath the hint, and thus the control hides the hint immediately before you can click on it. You can work around that by having TMyHintWindow override the virtual ShouldHideHint() method to return False. Then, you will have opportunity to click on the hint window. However, then you run into a new problem, because as soon as your click closes the hint, the mouse will effectively re-enter the control that was underneath the hint, and the control will reshow the hint again. Isn't this fun? What exactly are you trying to accomplish by messing with the hint window's default behavior?
×