Jump to content

Remy Lebeau

Members
  • Content Count

    2684
  • Joined

  • Last visited

  • Days Won

    113

Everything posted by Remy Lebeau

  1. Remy Lebeau

    File opening error C++ builder CE trivial program

    You probably need to recreate the project and make sure the VCL library is enabled. That wasn't the point of the exercise, though. It was to get more details about why the file is not opening correctly. But, if CreateFile() succeeds and std::ifstream fails, then there has to be another factor at play that is not being accounted for.
  2. You have a race condition. You are incrementing the counter at the point where the work is actually performed, but if the work is merely queued but the work thread hasn't actually started the work yet, then the counter may not have been incremented yet by the time you compare it in your destructor. You need to increment the counter at the point where the work is being queued, not where it is acted on. You didn't say which platform(s) you are targeting, On Windows for instance, a better strategy would be to put the thread's handles into an array, and then you can use (Msg)WaitForMultipleObjects() to wait for the handles to be signaled when the threads are fully terminated. However, you mention anonymous threads, so be aware that TThread.CreateAnonymousThread() sets TThread.FreeOnTerminate=true, which doesn't mix well with waiting on thread handles. So you would have to manually set FreeOnTerminate=false when starting the anonymous threads, and then free the threads yourself when they are finished running.
  3. Remy Lebeau

    NULL iterators in C++ Builder - 32 bit vs. 64 bit

    Can you show the actual code? Standard iterators are not initializable/comparable with NULL values. So your code is likely wrong to begin with and just happened to work before due to implementation details of the old standard library, but the new standard library is exposing your bugs. You need to fix your buggy code to use iterators correctly. But it's hard to explain what you need to change until we see what you are actually doing.
  4. Remy Lebeau

    TCP Port Check with timeout

    You are leaking the socket handle if connect() fails. You have to close the handle if socket() succeeds, regardless of whether connect() succeeds. You can't reduce (or even set) the timeout on a blocking connect(). You have to use a non-blocking connect() and then use select() or equivalent to implement the timeout. AFAIK, you can't disable SACK on a per-socket basis. You have to use the Registry or command-line netsh utility to disable it globally: https://superuser.com/questions/1808254/how-to-disable-tcp-sack-in-windows-xp https://www.linkedin.com/advice/3/how-can-tcp-selective-acknowledgment-sack-improve-heatc
  5. Remy Lebeau

    Memo and html

    The standard FMX TMemo simply does not support HTML (or even basic text formatting in general). You will have to use a 3rd party control (or make your own from scratch) to display rich/formatted text.
  6. Remy Lebeau

    File opening error C++ builder CE trivial program

    The C++ standard file library really sucks what it comes to error reporting. I would suggest using TFileStream or even CreateFile() directly to get better details about what the actual failure is. On a side note: kbhit() is a really old-school Borland function, it is not standard in either C or C++. Consider using C++'s standard std::cin.get() method instead. Try this: #include <iostream> #include <memory> #include <System.SysUtils.hpp> #include <System.Classes.hpp> int _tmain(int argc, _TCHAR* argv[]) { try { auto ifs = std::make_unique<TFileStream>(_D("C:\\Junk\\testfile.txt"), fmOpenRead); std::cout << "Opened OK\n"; } catch (const Sysutils::Exception &e) { std::wcout << L"Can't open input file. Error: " << e.Message.c_str() << "\n"; std::cin.get(); return 1; } std::cin.get(); return 0; } Or: #include <iostream> #include <windows.h> int _tmain(int argc, _TCHAR* argv[]) { HANDLE hFile = CreateFileW(L"C:\\Junk\\testfile.txt", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); if (hFile == INVALID_HANDLE_VALUE) { DWORD dwError = GetLastError(); cout << "Can't open input file. Error: " << dwError << "\n"; std::cin.get(); return 1; } std::cout << "Opened OK\n"; CloseHandle(hFile); std::cin.get(); return 0; }
  7. For example: procedure TDataField.SetAsAnyArray<T>(SourceItems: TArray<T>); begin case GetTypeKind(T) of tkInteger: begin ... end; tkUString: begin ... end; tkFloat: begin ... end; tkRecord: begin if TypeInfo(T) <> TypeInfo(TGuid) then raise ...; ... end; else raise ...; end; end;
  8. You can use a Generic so you have only 1 method to declare and implement which can accept multiple types as input, eg: procedure TDataField.SetAsAnyArray<T>(SourceItems: TArray<T>); But, it looks like you have different data members for each array type, so you would have to use RTTI to detect the actual type used for T and write different code branches to handle each type that you want T to accept. That's not much better than just writing a separate method for each type of T.
  9. Remy Lebeau

    idhttp.post idcompressorzlib

    At this time, TIdHTTP does not support compressing requests, only decompressing responses. You would have to manually compress your post stream yourself and then set the TIdHTTP.Request.ContentEncoding header accordingly.
  10. Remy Lebeau

    TCP Port Check with timeout

    DNS lookups and connect attempts are two different things. I don't think you can do non-blocking DNS lookups using the standard hostbyname()/getaddrinfo() APIs that most people's socket code uses. You would have to use platform-specific APIs (ie, like DnsQueryEx() on Windows), or send manual DNS queries over non-blocking sockets. A connect() timeout can be implemented by just using a non-blocking socket and close() the socket after the timeout elapses. If it uses a thread internally, that is just an implementation detail of the OS, but that shouldn't block the app from being able to move on.
  11. Remy Lebeau

    TCP Port Check with timeout

    Why TIcsIpStrmLog and not TSslWSocket directly? Are you saying that ICS does not support connect timeouts on TCP sockets at all? Or just that the TIcsIpStrmLog component specifically does not support this? In general, there are ways to implement a connect timeout on a TCP socket - namely: by using a non-blocking socket with select() or (e)poll() for the timeout. by aborting the socket from another thread. I would be surprised if ICS does not use the first one.
  12. I have never seen a "default" key value be named "(Standard)". It's always been named "(Default)" on every system I have ever used, eg:
  13. Remy Lebeau

    TIdHTTPWebBrokerBridge: Require TLS

    You should use different ports for HTTP and HTTPS. While it is technically possible to handle both HTTP and HTTPS on a single port, it requires extra coding to peek the raw TCP data before the HTTP server processes it. It is usually not worth the effort unless you are dealing with network restrictions.
  14. Remy Lebeau

    Delphi 10.4 GetIt connection issue

    What version are you using? What service url are you using? Things have changed in recent years.
  15. Remy Lebeau

    Desktop Icons

    Raymond Chen's blog article on Manipulating the positions of desktop icons includes code "to enumerate all the desktop icons and print their names and locations."
  16. Remy Lebeau

    ICS SLL3.2 much slower than Indy SSL1.0.2

    Why? You can reuse TIdHTTP for multiple requests. Are you creating it in the thread constructor? Or inside of the thread Execute()? They run in different thread contexts
  17. Remy Lebeau

    Ping-pong between two Application.ProcessMessages

    It also has the added benefit that it has an optional Delay parameter, if you need a longer sleep between steps, similar to a timer.
  18. Where do you see that documented? According to this documentation, the return type of the LogicalAnd and LocicalOr operators is simply specified as "resultType", nothing says it is required to be Boolean, so it can be whatever type the implementation wants.
  19. By definition, a TryXXX() function does not raise an exception into user code. TryISO8601ToDate() is no different. Now, it may be that it generates an internal exception on failure, but that is merely an implementation detail, such an exception will certainly not escape into user code. If you don't want to see the exception inside the debugger, you can configure it to ignore EDateTimeException and EConvertError exceptions. Regarding that exception, TryISO8601ToDate() is implemented backwards than other TryXXX() functions. In most RTL functions, DoX() calls TryDoX() to do the actual work, and then raises an exception if TryDoX() fails. But TryISO8601ToDate() is different - it calls ISO8601ToDate() to do the actual work, and then suppresses any exception that ISO8601ToDate() raises. What they SHOULD have done instead is move ISO8601ToDate()'s logic into TryISO8601ToDate(), and then make ISO8601ToDate() raise if TryISO8601ToDate() fails. But, it turns out that ISO8601ToDate() raises a different exception message depending on why it fails. Perhaps they could have created a new internal function do perform the actual work and have it report the failure reason to the caller, then TryISO8601ToDate() could ignore the reason, and ISO8601ToDate() could raise an exception based on the reason. Oh well...
  20. Remy Lebeau

    TLS v1.3

    Indy doesn't have a real CI system. But yes, generation of the cmd script could be automated in some way using information that Indy already has (there is already some automation in place to generate the Package projects themselves). To reduce duplication, I could auto-generate a separate cmd script that just deletes the known Indy files in the current directory, and then have Clean_IDE.cmd call that script where needed. Those files are not part of Indy itself, they are part of an internal wrapper on top of Indy which Embarcadero uses to separate its use of Indy from other Embarcadero code. But, there are other differences Embarcadero does make to Indy itself - most notably, the Packages are changed to use LIBSUFFIX, etc.
  21. Remy Lebeau

    TIdHTTPWebBrokerBridge: Require TLS

    That is not the correct way to handle this. You need to accept non-TLS connections on the HTTP port, and for any request that is received on that port, send an HTTP redirect response specifying the desired HTTPS port. That way, the client can then retry the same HTTP request on the HTTPS port using TLS. You don't need to handle that manually in TIdHTTPServer. Use the OnQuerySSLPort event instead, and let TIdHTTPServer handle the PassThrough for you. Any port that OnQuerySSLPort returns VUseSSL=True for will use PassThrough=False, and vice versa. ☝️☝️☝️ This is the way!
  22. Remy Lebeau

    Indy HTTP server

    There is no reason to assign a value to DefaultPort if you are creating only 1 Binding and setting its Port, thus overwriting what the DefaultPort already assigned. On the other hand, there is no point in assigning the Binding's Port if you are assigning it the same value as DefaultPort. The whole point of DefaultPort is it is the initial Port that is assigned by Add(). Such weird behavior is typically a classic symptom of "Undefined Behavior" being invoked elsewhere in your code, and this code is likely just an unexpecting victim of it. For instance, if random memory were being corrupted, and then this code tries to access that memory. Why are you using a TStringStream for raw file data? If you really need to load the file data into a String (ie, the file is textual), then you could simply use ContentText instead of ContentStream, no need to use a TStream. As I mentioned earlier in this thread, if you catch exception, you should RE-RAISE any Indy exceptions that are caught, eg: except on E: Exception do begin Log(req.URI + ' : ' + req.Document + sLineBreak + E.ClassName + ' : ' + E.Message); if E is EIdException then raise; // <-- ADD THIS end;
  23. Remy Lebeau

    How do I show a complete list of running processes?

    As Anders mentioned, you likely don't have permissions to retrieve all processes for other users. That being said, you might consider trying EnumProcesses() and see if it returns more entries. That being said, there are quite a number of issues with the code you have shown: You are leaking the THandle returned by CreateToolhelp32Snapshot(). GetName() is over-complicated. The data.szExeFile value is guaranteed to be null-terminated, so your loop is completely unnecessary (not to mention your use of a Byte for the loop counter means you might potentially truncate long filenames). You can simply assign the data.szExeFile value as-is to the Result without concatenating Char-by-Char (also, your comparison of a single Char to a blank string makes no sense at all). For that matter, you could just get rid of GetName() altogether and simply add data.szExeName as-is to your TStrings. You are not protecting your code from unexpected exceptions, which will cause several leaks if something goes wrong. There are several places in your code where you should be using try..finally blocks to free/release resources properly. You don't need to use the global Form1 variable inside of TForm1's own methods. Use each method's Self pointer instead.
  24. Remy Lebeau

    How to force update to label during a loop

    CM_TEXTCHANGED is a VCL message, it doesn't exist in FMX. When the TLabel.Text property is changed in FMX, there is no window message issued back to the TLabel, but there are virtual methods called instead, such as DoChanged() and DoTextChanged(). It should also be mentioned that the Text setter already calls Repaint() after calling the virtual methods.
  25. Remy Lebeau

    DateTimePicker - Set empty date

    Then there is no point in enabling the CheckBox on the DateTimePicker itself.
×