Jump to content

Remy Lebeau

Members
  • Content Count

    3002
  • Joined

  • Last visited

  • Days Won

    135

Posts posted by Remy Lebeau


  1. I have a recruiter messaging me on LinkedIn offering a position for a Sr Software Engineer with Embarcadero RAD Studio experience:

    Quote

    Would you be open to getting details on a 100% remote Senior Software Engineer position we have open with Evisions? They need someone with embarcadero suite (RAD studio) experience... it's a direct hire and paying well... I am also open to sharing details with you to see if you know anyone!!

    Anyone interested?


  2. I've never worked with (or even looked at) Indy's LDAP classes before.  But just looking at them right now, it appears that they are meant just for parsing/producing LDAP messages, not for receiving/transmitting them over TCP/UDP.  So, you would likely need to handle the actual transmission yourself via TIdTCPClient or TIdUDPClient.  For example, via TCP, connect a TIdTCPClient to an LDAP server, using an SSLIOHandler to handle SSL/TLS if needed, and then use TIdLDAPV3Encoder to prepare an LDAP message and save it to a TIdTCPStream to transmit it, and then use TIdLDAPV3Decoder with TIdTCPStream to receive messages.  I have no idea if that actually works, but worth a try.

     

    • Thanks 1

  3. 8 hours ago, Manlio Laschena said:

    At the moment I can only code under release mode, but I must find a solution. 

    A solution could be to turn the entry phase into a dll and start from scratch the real application hoping withou the invalid compiler directive.

    I am confused. Never seen an exception only on debug mode.

    You still haven't shown the actual 'invalid compiler directive' error, or what code the error is referring to.  That error is a compile-time error.  But you said your code compiles and runs, it was just experiencing a runtime error instead, due to accessing an array out of bounds.  So, what is the REAL problem here?


  4. 5 hours ago, David Heffernan said:

    I came across this code in the RTL:

    ...

    I'm wanting to call RegQueryInfoKey and wondering if I also need to mimic this far east if statement.

    No.  It is a remnant from Delphi's pre-Unicode days (going all the way back to Delphi 5, if not earlier).  Even then, I question why it was ever added in the first place, since the API always returned the correct sizes to begin with.  So, this will cause the caller to unnecessarily waste memory (if they enumerate subkey/value names afterwards) and should be taken out.

    Quote

    Is it possible that this code is bogus?

    Yes.  The increment is not necessary.  I have filed a bug report:

    RSP-41787: TRegistry.GetKeyInfo() doubles size of MaxSubKeyLen and MaxValueLen

    • Like 4

  5. TIdSMTP.Send() will call TIdSMTP.Authenticate() for you if authentication hasn't succeeded yet.  If you try to send an email without being adequately authenticated, the server will report a failure, which TIdSMTP will raise as an exception.  So really, there is little reason to check TIdSMTP.DidAuthenticate and call TIdSMTP.Authenticate() manually.

     


  6. 4 hours ago, Scalmax said:

    One thing that stuck me the most: GStack variable. If you do not create something that does TIdStack.IncUsage you will quickly find nil-related exceptions.

    I personally stuck with it by manually creating TIdSocketHandle objects and calling AllocateSocket on them. I know that TIdComponent.InitComponent does the job, but, IdBuffer.Create also does it.

    Only components increment GStack's usage count, utility classes do not.  If you use GStack without creating any components, you are expected to call TIdStack.IncUsage()/DecUsage() directly, eg:

    TIdStack.IncUsage;
    // use GStack as needed...
    TIdStack.DecUsage;

    It doesn't hurt to call IncUsage()/DecUsage() if you are not sure whether they should be called.  Just make sure they are balanced correctly.  TIdStack is reference-counted, the 1st usage increment creates the instance, and the last usage decrement destroys it.

    Quote

    My first thought was: remove GStack and make TIdStack.Instance(), probably with lock free pattern  https://stackoverflow.com/a/24657705   and without slow critical section. It would be code-breaking change.

    I'll consider it for a future release when more design-breaking changes are being worked on.

    Quote

    Anyway, it is time to stop complain, create github account, and start asking for pull requests.

    :classic_biggrin:


  7. In RAD Studio 11 (and since 10.3), only the Windows clang compilers support C++14 and C++17, the rest of the clang compilers support only C++11.  See Modern C++ Features Supported by RAD Studio Clang-enhanced C++ Compilers for details.

     

    You should not have to do anything extra to enable C++17 by default when compiling for Windows.  However, if you want to specify a specific standard version, you can do so manually in the project options via "C++ Compiler > Advanced > Other options  > Additional options to pass to the compiler", eg:

    3B2D0529-A327-4E0C-8D79-9C7BA94430CA.thumb.png.75d396ef3c0020e83d24984eb6f04e69.png

     

    Also see How to set C++ language standard in C++ Builder on StackOverflow.

    • Like 1

  8. 52 minutes ago, robertjohns said:

    This line does not work in Tokyo

     

    MyFindFilePattern('d:\MyZip', ['*.*', '*.txt', '*.zip'], LMyResult);
    ListBox1 .Items.AddStrings(LMyResult);

     

    There is no overloaded version of 'AddStrings' that can be called with these arguments

    AddStrings() has an overload that takes a TArray<string> instead of a dynamic "array of string" (even in 10.2 Tokyo), eg:

    type
      //TMyArrToStoreTheResulted = array of string;
      TMyArrToStoreTheResulted = TArray<string>;

  9. 59 minutes ago, programmerdelphi2k said:
    
      LContinue := FindFirst(AFolderRoot + '\' + APatternToSearch, faAnyFile, LSearchRecord) = 0;

     

    If the root path already has a '\' on the end of it, you would be adding another '\' unnecessarily.  Better to use IncludeTrailingPathDelimiter() instead, eg:

    LContinue := FindFirst(IncludeTrailingPathDelimiter(AFolderRoot) + APatternToSearch, faAnyFile, LSearchRecord) = 0;
    Quote
    
    if (LSearchRecord.Name <= '..') then

     

    That comparison wont work correctly if the file name begins with any character that is lexicographically less-than '.' (a few of them are reserved, but many of them are not), namely:

    ! # $ % & ' ( ) + , -

    You need to check for '.' and '..' specifically instead, eg:

    if (LSearchRecord.Name = '.') or (LSearchRecord.Name = '..') then
    • Like 3

  10. 55 minutes ago, NBilov said:

    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;

    Most servers are phasing out TLS 1.0, or already have, You should enable TLS 1.1 and TLS 1.2 as well:

    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
    55 minutes ago, NBilov said:

        if EmPort>0 then
        IdSMTP1.Port := EmPort
        else

    If you allow the Port to be configurable, you should also allow the UseTLS value to be configurable as well.  There is a functional difference between utUseImplicitTLS vs utUsseExplicitTLS, so you should let your config indicate which to use on a non-default Port.

    55 minutes ago, NBilov said:

        IdSMTP1.Port := 465;
        IdSMTP1.UseTLS := utUseExplicitTLS;

    As mentioned earlier, this is wrong.  You need to use utUseImplicitTLS on port 465.  Use utUseExplicitTLS on port 587 instead.

     


  11. On 5/19/2023 at 1:56 PM, alank2 said:

    So as a test I tried to set a TEdit to a UTF-8 sequence and it ended up as a series of characters and not the smile face I was testing.

    Makes sense, because by default assigning a raw char* string to a UnicodeString has no way of knowing that the char string is encoded as UTF-8, so it assumes the string is encoded as ANSI instead.

    Quote

    Is there a way to make it recognizing a narrow string assignment as UTF-8 - some sort of code page setting in the application maybe?  or will it not do that?

    You might try using SetMultiByteConversionCodePage(), but it would be better to put the UTF-8 char sequence inside of a UTF8String object instead, eg:

    Edit1->Text = UTF8String("\xf0\x9f\x98\x82");

    More generically, you can use RawByteString for handle any 'char'-based encoding:

    RawByteString str("\xf0\x9f\x98\x82");
    SetCodePage(str, CP_UTF8, false);
    Edit1->Text = str;

    The RTL knows how to convert a UTF8String/RawByteString to a UnicodeString, and vice versa.


  12. void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    	int x = Sysutils::StrToInt(Edit1->Text);
    	// alternatives:
    	// int x = Edit1->Text.ToInt();
    	// int x = std::stoi(Edit1->Text.c_str());
    	// int x = CSpinEdit1->Value; (using a TCSpinEdit instead of a TEdit)
    
    	int y = Sysutils::StrToInt(Edit2->Text);
    	// same as above...
      
    	int sum = x + y;
    
    	Label3->Caption = _D("The sum is ") + String(sum);
    	// alternatives:
    	// Label3->Caption = Sysutils::Format(_D("The sum is %d", ARRAYOFCONST((sum)) );
    	// Label3->Caption = String{}.sprintf(_D("The sum is %d", sum);
    	// Label3->Caption = std::format(L"The sum is {}", sum).c_str();
    	// Label3->Caption = (std::wostringstring{} << L"The sum is " << sum).str().c_str();
    }

     


  13. 1 minute ago, programmerdelphi2k said:

    for sure, but in sometime it do it! capacity > n =  reallocate it please! at end, a List will do it, expand the items like a array! or a array-of-pointers!

    Yes, it reallocates when its Capacity is exceeded.  And, it uses an array internally.  But, that reallocation won't happen on every add, since the Capacity grows algorithmically (see SysUtils.GrowCollection()).  It is very inefficient to reallocate on every add.


  14. 3 hours ago, shineworld said:

    Since I have little time at home to develop I, unhappily, thought of taking advantage of the hour and a half of free time for lunch break I have at the office, to continue development on my personal notebook BUT attached to the company WIFI network to access the sources, do push and everything else.

    Have you considered setting up a personal VPN on your home network, and then connect to it from your work office?

    • Thanks 1

  15. 12 hours ago, programmerdelphi2k said:

    UNnecessary usage:

    Not really.  Your way reallocates the array on every item added.  Whereas TList has a Capacity so it doesn't reallocate on every individual add, and then the final array is allocated only 1 time based on the TList's final Count.


  16. 1 hour ago, Ian Branch said:

    I can't see a way to get the number of elements in the TArray.

    Use the Length() function.

    Quote

    I thought "for var i := 0 to TArray(Instances).Count do Memo1.Lines.Add(Instances);" would be a monty, but no.

    How please?

    Use this instead:

    for var i := 0 to Length(Instances)-1 do
      Memo1.Lines.Add(Instances[i]);

    Alternatively,  you can use the Low()/High() functions to get the first and last indexes of the array:

    for var i := Low(Instances) to High(Instances) do
      Memo1.Lines.Add(Instances[i]);

    Alternatively, you can use a for..in loop instead, no indexes needed:

    for var elem in Instances do
      Memo1.Lines.Add(elem);

    However, in your particular example, the TMemo.Lines property has an overloaded method that accepts a TArray<string> as input, so you don't even need a loop at all:

    Memo1.Lines.AddStrings(Instances);
    Quote

    Solved.  I added the count to the function.

    You don't need that.  Dynamic arrays know their own length.

     

    • Like 2

  17. 48 minutes ago, Ian Branch said:

    I have bothe System.SysUtils and System.Diagnostics in my Uses clause but I am still gettin an 'undeclared identifier' for TProcessList and TProcess.

    What have I missed please?

    Delphi does not have any native classes named TProcess or TProcessList.  Your example is clearly based on 3rd party code that you don't have installed, which is why the classes are undefined.


  18. 13 hours ago, PeaShooter_OMO said:

    I am no C++ expert but shouldn't the asterisks of the parameters be immediately following the types and not precede the parameter names?

    Whitespace between tokens doesn't matter in C/C++.  Thus, "Type* VarName" and "Type *VarName" and "Type   *   VarName" all mean the same thing.


  19. 22 hours ago, gioma said:

    I had seen the first example and in fact I would like to try to derive the COleDataSource class, I just need to understand in which Delphi unit it is present!

     

    6 hours ago, gioma said:

    In Delphi not Exist class COleDataSource  ( Or I haven't found it yet ) 

     

    COleDataSource has the virtual function OnRenderData that I might need.

    COleDataSource is just a Microsoft C++ helper class that implements the IDataObject interface, which can be put on the clipboard using the OleSetClipboard() function.  In Delphi, you would have to implement the IDataObject interface manually (it is declared in the Winapi.Ole2 unit), or use a 3rd party implementation, such as from Melanders' Drag&Drop suite (probably via TDropEmptySource+TDataFormatAdapter).

    • Thanks 1

  20. 8 hours ago, gioma said:

    My specific case is as follows:

    I have two applications, A and B, connected by a socket connection.
    Application A intercepts the modification of its clipboard and sends the event to application B.
    Here we have two cases:
    1 if it is a text, it copies it directly to the clipboard
    2 if it is a file, it copies the list to the clipboard.
    Up to point 1 there are, while I have difficulty understanding how to pass the list of files to PC B (or rather I can do this phase) and make sure that when I press "paste" (here is the real problem which I'm racking my brain over) the file list transfer begins and the system waits for the files to be transferred before completing the paste command.

    All the more reason to try the route I suggested.  Application A could send its file list to Application B, then B can immediately put CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS items on its local clipboard for each file, having each CFSTR_FILECONTENTS hold an IStream to access its file data.  Then, when the user pastes the clipboard somewhere (or an app reads the clipboard directly), the individual CFSTR_FILECONTENTS streams can/will be read from, which can then transfer the actual file data from machine A to B as needed.  You could even go as far as having A transfer the file data to B in the background while waiting for a paste to happen, caching the data locally on B, and when CFSTR_FILECONTENTS is read from it can read from the local cache if available, otherwise initiate/wait-for the transfer to finish (even provide the data while it is begin transferred).  When the clipboard gets cleared, the IStream's will be released, and their destructors can cancel any transfers in progress and delete any local caches as needed.

    Quote

    I can't find half an example of this on the net

    There are examples/tutorials online about working with CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS, for instance:

    https://www.codeproject.com/Articles/15576/How-to-drag-a-virtual-file-from-your-app-into-Wind

    https://www.codeproject.com/Articles/23139/Transferring-Virtual-Files-to-Windows-Explorer-in

    Quote

    I can't believe no one has ever done this before, maybe even in C, C++.

    I'm sure they have, but it is very specialized work, so you are not likely to see it talked about publicly very much.

    • Like 1

  21. 22 hours ago, programmerdelphi2k said:

    I'm not an expert on Windows messages, but you would have to intercept the "WM_DRAWCLIPBOARD" message, to receive notification that MSExplorer intends to copy some object (file/folder/etc...).

    But first your app must be registered with a "Clipboard Viewer" ( SetClipboardViewer() ), and when you finish the app, do the "Un-Register" ( ChangeClipboardChain() )

    That is the OLD way to monitor the clipboard.  Since Vista, the NEW way is using a Clipboard Format Listener instead, registered via AddClipboardFormatListener() and handling WM_CLIPBOARDUPDATE messages.

    22 hours ago, gioma said:

    Thanks for the reply.
    I already do this, in fact if I copy paste a text it works perfectly.
    The problem instead I have with the files because they are not yet available on the file system because they come from the other PC.
    I send the list of files but I would like it to start the transfer only when "paste" is pressed and then the "paste window" waits for the files to be completely transferred and therefore available.

    Have you read Microsoft's documentation on Transferring Shell Objects with Drag-and-Drop and the Clipboard and Handling Shell Data Transfer Scenarios yet?

     

    Per Shell Clipboard Formats, you will likely want to implement the CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS formats.  That way, you can put descriptions of the files onto the clipboard, and when they are pasted then you can stream in the actual file data as needed.

    • Like 2
×