-
Content Count
2633 -
Joined
-
Last visited
-
Days Won
110
Everything posted by Remy Lebeau
-
Good catch. VERY hard to see that...
-
Yes, sadly. In my experience, XE2 is quite stable. Although I do have newer versions installed in VMs, I never really used any of them. I never upgraded my projects beyond XE2.
-
Like I said earlier, 255.255.255.255 is not a valid multicast group IP. If that is what you are seeing being used on the network, then it is not multicast to begin with. Where EXACTLY are you seeing that?
-
In addition to what has already been said, 255.255.255.255 is not a valid Multicast group IP, it is a UDP subnet broadcast IP. Subnet broadcasts are very different than Multicast broadcasts. Valid multicast group IPs (for IPv4) are in the range of 224.0.0.0 to 239.255.255.255.
-
project.exe is open in another program errors
Remy Lebeau replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Using Process Explorer, you can actually force-close a given handle to a file in any process. So, if you find an unexpected handle is open to your file, try simply closing it before resorting to a reboot. -
Hack to access an ancestor's private method
Remy Lebeau replied to dummzeuch's topic in RTL and Delphi Object Pascal
https://stackoverflow.com/a/36716715/65863 -
project.exe is open in another program errors
Remy Lebeau replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Did you try using SysInternals' Process Explorer or Process Monitor tools to see exactly which process(es) have your EXE file open at the time of the error? -
Visitor Pattern implemenation
Remy Lebeau replied to Ethan Yager's topic in Algorithms, Data Structures and Class Design
See Uwe Raabe's blog articles about the Visitor Pattern in Delphi: Part 1 Part 2 Part 3 Part 4 He shows how to work around the circular referencing issue using interfaces and multiple units. -
Um, yes it can. It has a full JSON library built-in.
-
Undocumented "Interface flag" for IInvokable?
Remy Lebeau replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
Yes, sorry, that is what I meant. -
That is not what I was referring to. It takes multiple writes to the socket to send a web request, and multiple reads to receive a complete response. Those writes and reads get logged individually by Indy's Intercept components. They are not going to log a complete request in one go, or a complete response in one go. No, that is not the cause of the error. And besides, the TIdHTTP.Intercept gets assigned to the IOHandler.Intercept internally. So assigning the TIdHTTP.Intercept is just a shortcut. Make sure you DO NOT have multiple conflicting versions of Indy on your machine. If you do, then it is likely that the compiler is finding an old file that does not match the latest interface. That is perfectly fine, especially if you are only seeing it in the debugger. It just means the web server closed the connection on its end while TIdHTTP was still reading from the socket. Which is one possible way (not the preferred way, but still possible) for a web server to signal the end of a response. TIdHTTP should be handled such an error internally. You can configure your debugger to ignore that particular exception. Make sure you set the Active property of the TIdLog... component to True. Then those PHP devs don't really understand what they are doing. You can't post JSON using 'application/x-www.form-urlencoded'. If they are enforcing that, they are doing something wrong on their end. Makes sense, since you can't post JSON using 'application/x-www-form-urlencoded'.
-
Undocumented "Interface flag" for IInvokable?
Remy Lebeau replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
OK. https://quality.embarcadero.com/browse/RSP-24631 I'm aware of that. But that is not the exact text you originally showed, which is why I questioned it. -
TIdLogEvent is not an abstract class, as it does implement all of the abstract methods of TIdLogBase. There is also TIdLogFile, which is not abstract, either. TIdInterceptSimLog and TIdLogFile are completely different file loggers. They write data in different formats. TIdLogFile is more "raw", logging data as-is, with optional timestamp and text replacements of CR and LF bytes. While TIdInterceptSimLog prefixes each read/write with a summary line describes whether the data is textual with a EOL present, or is raw bytes and what the byte size is, and appends a line break after each data.
-
Why not TIdLogFile instead? Especially since you are saving data to files. For debugging purposes, you DON'T want individual reads/writes to be logged to separate files. It makes more sense to keep them in a single file. Even if you use TIdLogEvent with separate files for input and output, you are creating filenames based on timestamps with seconds precision, so you are likely to end up with multiple files that contain smaller pieces of the overall data. At the very least, I would suggest either dropping the seconds from the filename, or use the timestamp at the very beginning of the initial request rather than the timestamps of the individual reads/writes. Also FYI, TFile.WriteAllText() overwrites an existing file. You need TFile.AppendAllText() instead. Even if it were secured with HTTPS, the TIdLog... components would be able to log the unencrypted HTTP data, as they log outgoing data before it is encrypted, and log incoming data after it is decrypted. I see nothing in your code that would cause an Abstract error, as there are no abstract classes being used. That being said, you don't need to instantiate an IOHandler manually in this case, since you are not using HTTPS. TIdHTTP has its own Intercept property, and will create an IOHandler internally for you: var NewsRec: TGetNewsRequest; Json: string; SS: TStringStream; Http: TIdHTTP; LogEvent: TIdLogEvent; Response: string; ResponseRec: TGetNewsResponse; begin // some non-relevant code for json preperation, etc. deleted SS := TStringStream.Create(Json); try LogEvent := TIdLogEvent.Create(nil); try LogEvent.OnSent := frmMain.IdLogEvent1Sent; LogEvent.OnReceived := frmMain.IdLogEvent1Received; Http := TIdHTTP.Create(nil); try Http.Intercept := LogEvent; Http.Request.ContentType := 'application/x-www-form-urlencoded'; Response := Http.Post(GetNewsURL, SS); // try..except removed to simplify code finally Http.Free; end; finally LogEvent.Free; end; finally SS.Free; end; // some non-relevant code to deal with result deleted end; On a side note, 'application/x-www-form-urlencoded' is the wrong ContentType to use for JSON data, use 'application/json' instead. If you really want to send an 'application/x-www-form-urlencoded' post, you need to use the overloaded version of TIdHTTP.Post() that takes a TStrings as input, not a TStream.
-
Undocumented "Interface flag" for IInvokable?
Remy Lebeau replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
Are you saying the returned IntfFlags *contains* a bit that *represents* an enum value of 3? Or that the IntfFlags *itself* is a numeric value of 3? In the former case, I have seen something similar before: https://stackoverflow.com/questions/49950534/strange-behaviour-of-typeinfo-by-anonymous-methods In the latter case, the TRttiInterfaceType.IntfFlags property returns a TIntfFlags Set, and a Set is implemented as a bitmask, where each bit represents a specific enum value. A bitmask value of 3 means the 1st 2 bits in the bitmask are set. And since TIntfFlags contains all of the TIntfFlag values, that would mean a bitmask value of 3 has the ifHasGuid and ifDispInterface flags enabled. Which, I guess the latter does not make sense in this situation, because IInvokable is not a dispinterface. So, it must be the former. -
Good design for "file was just saved" message
Remy Lebeau replied to Mike Torrettinni's topic in General Help
When I display filenames in Task Dialogs, I like to put them in the ExpandedText section, so they are hidden initially but the user can choose to see them if desired. -
TObject.NewInstance, TObject.InitInstance, GetMem and Pointer address
Remy Lebeau replied to santiago's topic in General Help
InitInstance() fills the allocated memory with zeros and inserts a pointer to the class's vtable at the front of the memory You should not need the type cast. ANY pointer can be assigned as-is to an untyped Pointer variable/parameter. -
Good design for "file was just saved" message
Remy Lebeau replied to Mike Torrettinni's topic in General Help
What about using a single TButton with its Style set to bsSplitButton and a DropDownMenu assigned? The button could default to "Open", but the drop-down menu could have other actions for the user to choose from. Here is rough mockup of it (I don't have access to a working IDE at the moment): -
In both C/C++ and Delphi, enums begin at 0, and values are sequential, unless explicitly otherwise stated. Since VmbPixelLayoutYCbYCr422 and VmbPixelLayoutYCbCr444 do not have explicit values, they are implicitly +1 from the values they immediately follow. Thus: VmbPixelLayoutYCbYCr422 = VmbPixelLayoutCbYYCrYY411 (= VmbPixelLayoutYUV411 = 8 ) + 1 = 9 VmbPixelLayoutYCbCr444 = VmbPixelLayoutCbYCrY422 (= VmbPixelLayoutYUV422 = 9 ) + 1 = 10
-
Embarcadero's documentation says otherwise: Enumerated Types with Explicitly Assigned Ordinality
-
Double check to make sure that you don't have a ModalResult assigned to btnOK itself. You should be able to click on btnOK and call DoLogin() as many times as you want without closing the Form until the Form's ModalResult is assigned when the Fail counter reaches the desired limit.
-
RTTI usage and edge cases :) Can't use GetType on T
Remy Lebeau replied to Andrea Raimondi's topic in RTL and Delphi Object Pascal
In addition, in XE7+ the compiler has an (undocumented) GetTypeKind() intrinsic function: function GetTypeKind(T: TypeIdentifier): TTypeKind; So you can do this instead: procedure TCSVSchemaBuilder.BuldSchema<T>(SchemaTemplate: T); begin FSchemaItems.Clear; FNumRequired := 0; case GetTypeKind(T) of tkClass: BuildSchemaFromClass(...); tkRecord: BuildSchemaFromRecord(...); tkInterface: BuildSchemaFromInterface(...); else raise EImportSchema.Create('Cannot create schema by type'); end; if FSchemaItems.Count = 0 then raise EImportSchema.Create('Schema is missing critical information. Cannot proceed'); end; Prior to XE7, you can replace GetTypeKind() with this instead: case PTypeInfo(TypeInfo(T)).Kind of Either way, the advantage is that T's Kind is known at compile time, which allows this code to optimize out unused code branches at compile-time, whereas the original code does not allow that since the Kind is being queried dynamically at runtime. -
Works fine for me just now.
-
I would suggest rewriting the function to something more like this: function IsFileInUse(const FileName: String): Boolean; var hf: THandle; begin hf := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if hf <> INVALID_HANDLE_VALUE then begin CloseHandle(hf); Result := False; end else begin Result := (GetLastError() = ERROR_SHARING_VIOLATION); end; end;
-
TIdHTTPServer.OnCommandGet - Timeout
Remy Lebeau replied to chkaufmann's topic in Network, Cloud and Web
That means either TCP connections are not being closed, or the threads that own them are not being terminated correctly (deadlocks, etc). Well, you need to debug your code and find out. Something like that, yes.