-
Content Count
3001 -
Joined
-
Last visited
-
Days Won
135
Everything posted by Remy Lebeau
-
Storing a large amount of elements in a 50k lines unit
Remy Lebeau replied to Clément's topic in Algorithms, Data Structures and Class Design
Why are you hard-coding so much data directly in your source code to begin with? Why not simply store the data in an external file or database and then load it from there at runtime? If you absolutely need the data to be present statically in your app's executable, I would suggest having the auto-generator store the data in a separate file that is then linked into the app's resources at compile time, and then you can load the data from that resource at runtime. This much data really DOES NOT belong in the source code directly at all. Another benefit of this approach (using either a file, database, resource, etc) is that you can update the data on the user's machine without having to deliver a new executable from your dev machine every time (in the case of using a resource, there are plenty of 3rd party tools available to update an app's resources directly). You can, of course, also update the data on your dev machine and recompile if you really want to. -
PDF File Send as Base64 from c# to Delphi REST
Remy Lebeau replied to mazluta's topic in Network, Cloud and Web
That should only happen if you are sending the data in the URL query string, or in the HTTP body in 'application/x-www-webform-urlencoded' format. You need to show your actual C# and Delphi codes for the REST request, you are clearly not setting up and/or processing the request correctly. DO NOT employ the workaround you have described, that is the wrong solution. You need to fix the underlying bug in your code that is messing up the data in the first place. -
communicate between 2 progs with sendmessage.
Remy Lebeau replied to JeanCremers's topic in Windows API
Is "myprog" the title for your program's TApplication window or TForm window? It makes a big difference. I'm suspecting the latter. You are installing a message handler for the TApplication window. To handle messages for the TForm window, override the TForm's virtual WndProc() method instead: void __fastcall TMainForm::WndProc(TMessage &Message) { if (Message.Msg == WM_USER) { Application->MessageBox("", "", MB_OK); Message.Result = 1; } else TForm::WndProc(Message); } That being said, WM_USER is not a good choice for inter-process communications. Use WM_APP or RegisterWindowMessage() instead. -
TThread.Queue() runs asynchrously - it returns to the caller immediately and its passed procedure is executed in the main thread at some future time. So, your first example is mostly correct - the anonymous procedure will have to transfer ownership of the TStringList to the main thread so it can free the TStringList after updating the UI. However, be sure to move your try..finally into the procedure as well to ensure the TStringList is actually freed even if something goes wrong, eg: procedure TForm16.ShowComputedDetail; begin TTask.Run( procedure var lTstrings: TStrings; begin lTstrings := TStringList.create; try ComputeDetail(lTstrings); TThread.Queue(nil, procedure begin try MyTMemo.BeginUpdate; try MyTMemo.Lines.Assign(lTstrings); finally MyTMemo.EndUpdate; end; finally lTstrings.Free; end; end); except lTstrings.Free; raise; end; end); end; In your 2nd example, you will need to change TThread.Queue() to TThread.Synchronize() to ensure the TStringList is not freed before the main thread has a chance to use it, eg: procedure TForm16.ShowComputedDetail; begin TTask.Run( procedure var lTstrings: TStrings; begin lTstrings := TStringList.create; try ComputeDetail(lTstrings); TThread.Synchronize(nil, procedure begin MyTMemo.BeginUpdate; try MyTMemo.Lines.Assign(lTstrings); finally MyTMemo.EndUpdate; end; end); finally lTstrings.Free; end; end); end;
-
PDF File Send as Base64 from c# to Delphi REST
Remy Lebeau replied to mazluta's topic in Network, Cloud and Web
Can you provide a concrete example of such a difference? -
PDF File Send as Base64 from c# to Delphi REST
Remy Lebeau replied to mazluta's topic in Network, Cloud and Web
Why are you using Base64 at all? REST runs over HTTP, and HTTP handles binary data without needing to encode it. -
Prevent Multiple Instance from running at the same time
Remy Lebeau replied to new_x's topic in Windows API
You should also set the bInitialOwner parameter to False in the CreateMutex() call. You don't need ownership of the mutex just to create it and test for its existence. You can then remove the call to ReleaseMutex() as well. -
Call for Delphi 12 Support in OpenSource projects.
Remy Lebeau replied to Tommi Prami's topic in Delphi Third-Party
Embarcadero already has private channels/forums available for its beta testers and MVPs/TPs. -
I need advice on converting a 500k lines 32bit Delphi 7 application to 64bit
Remy Lebeau replied to Yaron's topic in General Help
Just note that WideString is very inefficient in general, since it is an ActiveX/COM string type managed by the OS, not the Delphi RTL. But you also said a lot of your strings are UTF-8, and you can't store UTF-8 in a WideString. But you can use UTF8Encode()/UTF8Decode() to convert strings between UTF8String and WideString as needed. I doubt it, and if I'm not mistaken, TNT isn't even around anymore. Not to mention it is largely unnecessarily anyway, as the core Delphi classes are now Unicode capable since 2009. So many/most of the TNT classes you are using can be replaced with the native RTL/VCL counterparts (TForm, TListBox, TStringList, etc). Hard to say without seeing your actual code, and what kind of workarounds you are using. You can still use ASM coding in modern Delphi, although 64bit does have some additional restrictions on its usage. -
I need advice on converting a 500k lines 32bit Delphi 7 application to 64bit
Remy Lebeau replied to Yaron's topic in General Help
Possibly. Depends on the context in which it's being used. In any case, if you need UTF-8 strings, you should use the native UTF8String type instead of AnsiString (even in Delphi 7, you should have been doing that). If you must use UTF8 encoded AnsiString in D2009+, at least use SetCodePage() to make sure the CP_UTF8 (65001) codepage is assigned to its data. UTF8String and UnicodeString are assignment-compatible in D2009+, the RTL will automatically convert between them without any data loss (in Delphi 7, you would have had to use the UTF8Encode()/UTF8Decode() functions for that). At least with SetCodePage(), you can make sure not to lose any data if a UTF8 encoded AnsiString is assigned to a UnicodeString (the reverse is not true, though). -
Insert text value into form with webbrowser android Delphi FMX with function WEBBROWSER.EvaluateJavaScript
Remy Lebeau replied to Alisson's topic in FMX
Already covered on StackOverflow: https://stackoverflow.com/questions/77326298/trouble-inserting-text-value-into-html-input-with-twebbrowser-evaluatejavascript -
I need advice on converting a 500k lines 32bit Delphi 7 application to 64bit
Remy Lebeau replied to Yaron's topic in General Help
None of that has anything to do with migrating from 32-bit to 64-bit. Only with migrating from ANSI to Unicode. You can still use the ANSI types in 64-bit code if you need to, albeit more explicitly than before. -
Didn't say there is one. From the get go, the discussion has been about compiling with <windows.h> in general, and how Microsoft doesn't force the alignment but Embarcadero does. Yes, a shame (FreePascal does). Even Marco agreed it would be a useful feature to add, but they still haven't added it yet.
-
That header is modified by Embarcadero, as evident by the check for __CODEGEARC__. Microsoft doesn't care about checking for CodeGear/Embarcadero compilers. The question is, what does Microsoft's native SDK version of the header look like?
-
Use of dynamic control names
Remy Lebeau replied to Bart Verbakel's topic in Algorithms, Data Structures and Class Design
That "works" but may be overkill, as you would potentially be iterating through a lot of other controls that you are not interested in. -
Use of dynamic control names
Remy Lebeau replied to Bart Verbakel's topic in Algorithms, Data Structures and Class Design
Don't do that! You are invoking undefined behavior. You can only iterate using a pointer like that if the values are in an array, Otherwise, you can't be sure the compiler is not adding padding between them inside the class. If you want to use a pointer to iterate the members, you have to put them into an array first and iterate that instead. -
Searching Edit component with autocomplete for Directory/Files
Remy Lebeau replied to Carlo Barazzetta's topic in VCL
Ah. No, it does not. In that case, you would indeed need a custom enumerator. -
I would just stick with using the <pshpack#.h>/<poppack.h> headers, since they support multiple compilers, and will use #pragma pack(push) if the compiler supports it. I have never seen that warning before when using #pragma pack directly. But then, I don't ever wrap the standard Win32 headers with it, either. I doubt it, but anything is possible, I guess. You will have to review the headers for yourself.
-
Searching Edit component with autocomplete for Directory/Files
Remy Lebeau replied to Carlo Barazzetta's topic in VCL
Why implement a custom IEnumStrings class for directories/files? There is already a pre-made data source provided by the OS for that exact purpose - CLSID_ACListISF, which can be created with CoCreateInstance(), configured via IACList2::SetOptions(), and then passed to IAutoComplete::Init(). -
Register COM Object for create process/Fightiing AntiVirus
Remy Lebeau replied to RTollison's topic in General Help
Creating a COM object to run a process won't bypass the AV if it is looking for process creations. That will just add more overhead to the app that is wanting to create the processes. Unless the AV ignores COM objects that run elevated, which would be pretty risky. Besides, it's not really possible for an AV to determine whether a process creation is occurring inside a COM object vs an application anyway. I think your IT is acting stupid, but that is just my opinion. Do you really need to run an external process on every file? What is the new process doing exactly that you can't do directly inside your own app with an equivalent library? -
My example assigns the TIdSMTP object as the Owner of the SSLIOHandler object. When the TIdSMTP object is freed, it will free the SSLIOHandler object for you. This is a memory management mechanism that is implemented by all TComponent descendants. If you want to free the object yourself, you certainly can do so, eg: procedure SendTestEmail2; var SMTP: TIdSMTP; SSLHandler: TIdSSLIOHandlerSocketOpenSSL; Message: TIdMessage; begin try SMTP := TIdSMTP.Create(nil); try SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); try SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_2]; // and/or sslvTLSv1, sslvTLSv1_1, etc. SSLHandler.SSLOptions.Mode := sslmClient; SMTP.IOHandler := SSLHandler; SMTP.Host := 'smtp.gmail.com'; SMTP.Port := 465; // or 587, depending on your server SMTP.UseTLS := utUseImplicitTLS; // or utUseExplicitTLS, depending on your server SMTP.Username := 'UserName'; SMTP.Password := 'Pass'; Message := TIdMessage.Create(nil); try Message.From.Address := 'men@gmail.com'; Message.Recipients.EMailAddresses := 'grantful@yahoo.com'; Message.Subject := 'Test Subject'; Message.Body.Add('Test message.'); SMTP.Connect; try SMTP.Send(Message); finally SMTP.Disconnect; end; finally Message.Free; end; finally SSLHandler.Free; end; finally SMTP.Free; end; except on E: Exception do begin ShowMessage('Error: ' + E.Message); end; end; end; It is customary to assign a nil Owner when you want to free an object yourself. But it is safe to manually free an object that has an Owner assigned, as the freed object will simply remove itself from its Owner to avoid being freed again. Are you debugging your app on those platforms to see what is actually going on? Which line of code is actually raising those errors?
-
On 32bit systems, as well. Using the Windows Headers What structure packing do the Windows SDK header files expect?
-
Yes - 8 bytes Because the Windows SDK is old and predates those headers? I don't know. Not sure if the original SDK headers do this, but In Embarcadero's copy of windows.h and other SDK headers, there are actually #pragma statements to setup 8-byte alignment, eg: #pragma option push -b -a8 -pc -A- /*P_O_Push*/ ... #pragma option pop /*P_O_Pop*/ The -a8 parameter is the alignment. Yes, and most VCL headers have #pragma statements for that purpose, eg: #pragma pack(push,8) ... #pragma pack(pop)
-
Look at that code very carefully. You have commented out the creation of an SSLHandler object, but then are accessing its members. Crash. And, if that one line were not commented out, you would then be creating a 2nd SSLHandler object and assigning it to the same variable, leaking the 1st object. You need to fix your object creation. This is not specific to Indy, this is a fundamental issue to how Pascal/OOP programming works in general. You have to create an object before you can use it. Now, after fixing that, your code has another problem - SMTP port 465 is an implicit TLS port, but you are setting the TIdSMTP.UseTLS property to utUseExplicitTLS. SMTP port 587 is the explicit TLS port. Use utUseImplicitTLS for port 465, and utUseExplicitTLS for port 587 (and optionally 25). Try this: procedure SendTestEmail2; var SMTP: TIdSMTP; SSLHandler: TIdSSLIOHandlerSocketOpenSSL; Message: TIdMessage; begin try SMTP := TIdSMTP.Create(nil); try SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(SMTP); SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_2]; // and/or sslvTLSv1, sslvTLSv1_1, etc. SSLHandler.SSLOptions.Mode := sslmClient; SMTP.IOHandler := SSLHandler; SMTP.Host := 'smtp.gmail.com'; SMTP.Port := 465; // or 587, depending on your server SMTP.UseTLS := utUseImplicitTLS; // or utUseExplicitTLS, depending on your server SMTP.Username := 'UserName'; SMTP.Password := 'Pass'; Message := TIdMessage.Create(nil); try Message.From.Address := 'men@gmail.com'; Message.Recipients.EMailAddresses := 'grantful@yahoo.com'; Message.Subject := 'Test Subject'; Message.Body.Add('Test message.'); SMTP.Connect; try SMTP.Send(Message); finally SMTP.Disconnect; end; finally Message.Free; end; finally SMTP.Free; end; except on E: Exception do begin ShowMessage('Error: ' + E.Message); end; end; end;
-
That is not a good idea. Store them outside of the exe (config file, database, etc), and secure them with encryption, etc in case they need to be changed over time. If a hacker has access to your exe, all bets are off. Nothing stops a competent hacker from discovering the memory blocks your app is using and just pull the login values directly from that memory as soon as your app uses it.