-
Content Count
3001 -
Joined
-
Last visited
-
Days Won
135
Everything posted by Remy Lebeau
-
Am I connected to the Internet - how can I find out?
Remy Lebeau replied to JohnLM's topic in Network, Cloud and Web
On Windows, you can use the Network List Manager API, specifically the INetworkListManager.isConnectedToInternet property. However, as there are so many different ways that a PC can be connected to the Internet nowadays, you are better off simply trying to access an online resource (such as your status file) and see if it succeeds or fails, don't even bother polling the Internet status beforehand. That just introduces a TOCTOU race condition.- 2 replies
-
- delphi xe7 11 12
- internet
-
(and 1 more)
Tagged with:
-
You don't need to use an external sniffer with TIdHTTP, as it can log its own HTTP traffic directly. Simply assign a TIdConnectionIntercept-derived component to the TIdHTTP.Intercept property, such as one of the TIdLog... components. I don't know if TNetHTTPClient has any logging capabilities, though (probably not).
- 6 replies
-
- native https
- logon
-
(and 2 more)
Tagged with:
-
Why PUT and not POST? Browsers don't use PUT for HTML-based webforms. Have you tried sniffing the HTTP traffic to see if there are significant differences between TIdHTTP's requests and TNetHTTPClient's requests? Does the logon use cookies? Do you have cookies enabled in the TNetHTTPClient?
- 6 replies
-
- native https
- logon
-
(and 2 more)
Tagged with:
-
I wonder if this is a false positive? The log shows a thread pool is involved. Makes me wonder if the pool threads are simply still running when the leak report is generated. You have to make sure everything is shutdown first before the memory manager is cleaned up.
-
Your rollback and cancel calls are backwards. Since the transaction was started first, it should be rolled back last. Cancel the edit before you rollback. Consider using a 2nd try..except block to handle this correctly. You are also not breaking the loop if the transaction is successful. Try this instead: retry := 0; repeat starttransaction; try table1.edit; try change table1; table1.post; except table1.cancel; re-raise; end; commit; Break; except Rollback; inc(retry); if retry >= 3 then showmessage & exit else sleep(500); end; until False;
-
How to correctly add a platform to a run-time package.
Remy Lebeau replied to dmitrybv's topic in Delphi IDE and APIs
In the dproj file, locate the <Platforms> element and make sure it has a <Platform> child element for each target platform, and that each platform is set to a value of True. <Platforms> <Platform value="Win32">True</Platform> <Platform value="Win64">True</Platform> ... </Platforms> Sorry, I'm not at a computer right now, so I can't lookup the exact names of the other <Platform> elements. UPDATE: here are some other platform names: iOSDevice32 iOSDevice64 iOSSimulator iOSSimARM64 OSX32 OSX64 OSXARM64 Android Android64 Linux64 -
What is a "VCL Component badge button" supposed to be? Please be more specific.
-
The SysUtils.Exception class does not have an ErrorCode property. But some descendants do, like EUpdateError, EDBClient, etc. What is the actual ClassName() of the caught Exception?
-
Custom Managed Records and Default(T)
Remy Lebeau replied to rgdawson's topic in Algorithms, Data Structures and Class Design
I'm aware of that. You seem to have missed the point I was trying to make regarding rgdawson's earlier comment about the order of initialization/finalization. Default() creates a NEW INSTANCE, which is then assigned to the EXISTING instance, ie this code: procedure Main; var r: TMyRec; begin r := Default(TMyRec); end; SHOULD BE roughly equivalent to this: procedure Main; var r: TMyRec; // allocation only begin TMyRec.Initialize(r); try var temp: TMyRec; // allocation only TMyRec.Initialize(temp); try TMyRec.Assign(r, temp); finally TMyRec.Finalize(temp); end; finally TMyRec.Finalize(r); end; end; But what it is actually doing this more like this: procedure Main; var r: TMyRec; // allocation only begin TMyRec.Initialize(r); try var temp: TMyRec; // allocation only TMyRec.Initialize(temp); try TMyRec.Initialize(temp); // <-- SHOULD NOT BE HERE! TMyRec.Assign(r, temp); finally TMyRec.Finalize(temp); end; finally TMyRec.Finalize(r); end; end; Yes, because Default() is not being called. Exactly. r is initialized, then a temporary record is created and initialized TWICE (that's the bug), then the temp is assigned to r, then the temp and r are finalized. Here is the complete code I tested with, which makes it clearer which record is being initialized and finalized. You can clearly see the temporary record created by Default() is initialized twice: program CustomManagedRecordDefaultTest; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Classes; type Stringlist = record private FData: TStringList; function GetText: string; procedure SetText(const AValue: string); public class operator Initialize(out Dest: Stringlist); class operator Finalize(var Dest: Stringlist); class operator Assign(var Dest: Stringlist; const[ref] Source: Stringlist); property Text: string read GetText write SetText; end; class operator Stringlist.Initialize(out Dest: Stringlist); begin Dest.FData := TStringList.Create; WriteLn(IntToHex(IntPtr(@Dest)) + ' Initialized'); end; class operator Stringlist.Finalize(var Dest: Stringlist); begin Dest.FData.Free; WriteLn(IntToHex(IntPtr(@Dest)) + ' Finalized'); end; class operator Stringlist.Assign(var Dest: Stringlist; const[ref] Source: Stringlist); begin Dest.FData.Assign(Source.FData); WriteLn(IntToHex(IntPtr(@Source)) + ' Assigned to ' + IntToHex(IntPtr(@Dest))); end; function Stringlist.GetText: string; begin Result := FData.Text; end; procedure Stringlist.SetText(const AValue: string); begin FData.Text := AValue; end; function AllCaps(const Strings: Stringlist): Stringlist; var sl: Stringlist; begin WriteLn(' Strings=', IntToHex(IntPtr(@Strings)), ' sl=', IntToHex(IntPtr(@sl)), ' Result=', IntToHex(IntPtr(@Result))); WriteLn(' Calling: sl := Default(Stringlist)'); sl := Default(Stringlist); WriteLn(' Default Returned, sl Assigned'); sl.Text := UpperCase(sl.Text); WriteLn(' Returning sl'); Result := sl; end; procedure DoTest; var MyStrings, TheirStrings: Stringlist; begin WriteLn(' MyStrings=', IntToHex(IntPtr(@MyStrings)), ' TheirStrings=', IntToHex(IntPtr(@TheirStrings))); WriteLn(' Calling: MyStrings := AllCaps(TheirStrings)'); MyStrings := AllCaps(TheirStrings); WriteLn(' AllCaps Returned, MyStrings Assigned'); end; begin WriteLn('Calling: DoTest'); DoTest; WriteLn('DoTest Returned'); ReadLn; end. Calling: DoTest 008FFD0C Initialized 008FFD08 Initialized MyStrings=008FFD0C TheirStrings=008FFD08 Calling: MyStrings := AllCaps(TheirStrings) 008FFCC8 Initialized Strings=008FFD08 sl=008FFCC8 Result=008FFD0C Calling: sl := Default(Stringlist) 008FFCC4 Initialized // <-- TEMP CREATED AND INIT HERE 008FFCC4 Initialized // <-- TEMP INIT AGAIN! 008FFCC4 Assigned to 008FFCC8 008FFCC4 Finalized // <-- TEMP DESTROYED HERE Default Returned, sl Assigned Returning sl 008FFCC8 Assigned to 008FFD0C 008FFCC8 Finalized AllCaps Returned, MyStrings Assigned 008FFD08 Finalized 008FFD0C Finalized DoTest Returned -
Yes, exactly, for example: uses ... {$IFDEF MSWINDOWS}, Winapi.Windows{$ENDIF} {$IFDEF ANDROID}, Androidapi.SomeOtherUnit{$ENDIF} ... ;
-
The Winapi.Windows unit is for Windows builds only. If the component is trying to use that unit in an Android build, then its code is not IFDEF'ed properly to separate any platform-specific code, and thus needs to be fixed accordingly.
-
Why are you re-compiling Winapi.Windows.pas? You should not be doing that. In any case, Winapi.Windows.pas declares the _CONTEXT record only if the CPUX64 or CPUX86 conditional is defined. Perhaps they are not defined in your situation?
-
Custom Managed Records and Default(T)
Remy Lebeau replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Maybe I'm just having a brain fart, but why would a new record instance need to be FINALIZED before it is INITIALIZED? The System.Default documentation even states: Finalizing implies destruction, not creation. And if a record contains compiler-managed types (interfaces, strings, dynarrays, etc), finalizing it before initializing it would invoke refcounting semantics on things that aren't valid yet. What am I missing here? -
What does this function mean? CharPrev / Range Check Error
Remy Lebeau replied to terran's topic in General Help
As I stated earlier, PChar(S[Length(S)]) is extracting the last single Char from the string and type-casting its value into a PChar pointer, which is wrong. You need to use the @ operator to get the address of that Char. But in any case, using S[Length(S)] doesn't take into account that a string contains encoded codeunits, so will NOT be the last full character if the character is encoded using multiple codeunits. CharPrev() takes the encoding into account. The code is getting a pointer to the null terminator and then moving the pointer backwards 1 full character regardless of how how many codeunits it actually takes. -
What does this function mean? CharPrev / Range Check Error
Remy Lebeau replied to terran's topic in General Help
The difference is that: @S[Length(S)+1] returns a pointer to the null-terminator only on a 1-based string, but goes out of bounds on a 0-based string. PChar(S)+Length(S) returns a pointer to the null-terminator on both a 1-based and a 0-based string. Range checking would need to be disabled, because the null terminator is not included in the Length of the string, so it is not an indexable character, even though it is physically present in memory. All the more reason to use pointer arithmetic instead of character indexing to access the terminator. -
Custom Managed Records and Default(T)
Remy Lebeau replied to rgdawson's topic in Algorithms, Data Structures and Class Design
When I run your code, I see your Default() statement is calling Initialize() two times on the same temporary Stringlist instance, then that temporary is Assign()'ed to the Result record, and then the temporary is Finalized() only one time. Clearly one of the Initialize() calls is erroneous. I have reported this to Embarcadero: RSS-1647: System.Default() on a Custom Managed Record calls its Initalize operator too many times -
What component I can use to display images in Android ?
Remy Lebeau replied to William23668's topic in FMX
Another option would be a TListView with an image per list item: https://docwiki.embarcadero.com/Libraries/en/FMX.ListView.TListView -
What component I can use to display images in Android ?
Remy Lebeau replied to William23668's topic in FMX
Did you look at the TImage component yet? https://docwiki.embarcadero.com/Libraries/en/FMX.Objects.TImage -
What does this function mean? CharPrev / Range Check Error
Remy Lebeau replied to terran's topic in General Help
That would not work. That is taking the last character and type-casting its value to a pointer, which is not the same thing as taking a pointer to the last character. I would have used this instead: CharPrev(PChar(S), PChar(S) + Length(S)); That would work with both 0-based and 1-based strings. -
You didn't show any of the receiving code you tried, so it is difficult to tell you why it is not working. TApplication(Event)::OnMessage does work with PostMessage(), and WndProc() does work with both PostMessage() and SendMessage(). So, either you are not looking for the correct window message ID, or you are posting/sending the message to the wrong HWND to begin with. I'm assuming "myVCLApplication" is the caption of your TForm and not some other window, correct? Is your IDE running with your project loaded when the message is being posted/sent?
-
Handling TCP send buffer overflow the right way
Remy Lebeau replied to Dmitry Onoshko's topic in Network, Cloud and Web
I wasn't suggesting you not destroy your objects. But a destructor is not always the best place to perform complex cleanups, especially during app shutdown. For instance, you could use the Form's OnClose/Query event to detect the user's desired to exit the app, signal your code to start cleaning up (close sockets, cancel I/Os, etc), and disable the UI so the user can't generate more traffic in the meantime. When the cleanup is actually finished (all I/O completions are reported, etc), then exit the app. -
Pointer casting with NativeUint
Remy Lebeau replied to duzzell's topic in Algorithms, Data Structures and Class Design
And even though Native(U)Int existed starting in Delphi 2007, they were buggy up to Delphi 2010. -
How to set Supported platforms for my component?
Remy Lebeau replied to dmitrybv's topic in Delphi IDE and APIs
By annotating it with the ComponentPlatforms attribute: https://docwiki.embarcadero.com/Libraries/en/System.Classes.ComponentPlatformsAttribute Not that I'm aware of. Which ways are you thinking of? When a component does not indicate any specific platforms, then it is available for all platforms, limited only by the framework it uses. A VCL component without ComponentPlatforms will support all platforms that VCL supports, namely Windows 32bit and 64bit. An FMX component without ComponentPlatforms will support all platforms that FMX supports. TDataSource derives directly from TComponent and has no affinity to either VCL or FMX, so it will support whichever framework your project is using, and thus whichever platforms that framework supports. -
Handling TCP send buffer overflow the right way
Remy Lebeau replied to Dmitry Onoshko's topic in Network, Cloud and Web
Not that hard, really. Common practice is to keep a counter of active I/O requests. During shutdown, set a flag to prevent new requests from starting, and cancel active requests still in progress. When requests complete, decrement the counter. Wait for the counter to fall to 0, then close the socket and exit. Probably not the best thing to do in a destructor in a GUI, though. I would have the GUI start the shutdown process and let it run asynchronously, then disable the UI and tell the user to wait, and then finish cleaning up the GUI only when all pending requests have finished. -
Yup. When I tested it, I got 3 events - 1) old item de-focused, then 2) old item de-selected, then 3) new item focused and selected together.