-
Content Count
2914 -
Joined
-
Last visited
-
Days Won
130
Everything posted by Remy Lebeau
-
Check port in use exception
Remy Lebeau replied to Hafedh TRIMECHE's topic in Network, Cloud and Web
Under normal conditions, that particular exception class should not be getting raised in this code, as a connect attempt should never report a WSAENOTSOCK error. On the other hand, 200ms is a fairly short timeout, and Indy does use a worker thread internally to implement a timed connect, so it is likely that the timeout is elapsing and closing the socket before the thread even has a chance to attempt to connect. However, in that scenario, the code that is calling TIdTCPClient.Connect() would receive an EIdConnectTimeout exception instead of an EIdNotASocket, The thread would raise EIdNotASocket internally and swallow it, but your JCL debugging does not appear to be taking that into account. -
That is wrong. Don't assign the new TFormatSettings instance to the global FormatSettings variable at all (in fact, pretend that global variable doesn't even exist). Pass the new TFormatSettings instance directly to FormatFloat() instead, eg: fs := TFormatSettings.Create(SysLocale.DefaultLCID); // customize fs as needed... ShowMessage(FormatFloat('###,###.00', 1234.25, fs));
-
Indy's TIdFTP component has a similar option. Except that, rather than attempt the reply IP first then fallback to the connected IP, it has a PassiveUseControlHost property to control whether it should just ignore the reply IP altogether and use the connected IP only. Not quite the same thing. I'm thinking now that I should add FileZilla's behavior to TIdFTP if PassiveUseControlHost is false.
-
Will getit work for C++ Builder
Remy Lebeau replied to alank2's topic in ICS - Internet Component Suite
Has CodeGuard EVER worked? I stopped using it many years ago, and I've seen plenty of users reporting in the various forums over the years about problems with it. -
Because it dictates which offset is used for calculating UTC from the PC's location. For example, a PC clock set to 12:00PM PST is going to report a different UTC time than if its clock were set to 12:00PM EST instead.
-
Yes, it is the UTC time of the local PC clock. Internally, it converts the result to local time, yes. But the NTP protocol itself (RFC 5905) reports time in UTC. Technically, the DAYTIME protocol (RFC 867) does not define any particular string format or locale for the output, so it could be anything the server wants, in any format, any timezone, etc. The TIME protocol (RFC 868) is expressed in UTC. Indy's TIdTime and TIdTimeUDP implement this protocol. They both convert the result to local time when queried as a TDateTime, same as TIdSNTP does, however you can also get the original UTC response in UInt32 format instead via the DateTimeCard property. Per https://tf.nist.gov/tf-cgi/servers.cgi, NIST suggests that all clients of NIST servers update to using the NTP protocol, which is what TIdSNTP implements, which you have already ruled out as a solution. TIdSNTP does not expose access to the UTC response.
-
TDialogService.MessageDialog() is asynchronous on Android, per the documentation, so the dialog won't appear until after SpeedButton5Click() has exited. As such, your code is trying to use the Reply variable before it has actually been assigned a value, which is why StartLogin10() is not being called. Android simply does not support modal dialogs, and so the RTL does not implement any synchronous dialogs on Android. See Using FireMonkey Modal Dialog Boxes, TCommonCustomForm.ShowModal(), and IFMXWindowService.CanShowModal() for more details. You need to move the call to StartLogin10() inside the MessageDialog() callback, eg: procedure TFrmLogin.SpeedButton5Click(Sender: TObject); begin if (lst2.Items.Count <> 0) and (lst2.ItemIndex <> -1) then begin TDialogService.MessageDialog('you are gonna edit something ', TMsgDlgType.mtInformation, [TMsgDlgBtn.mbYes], TMsgDlgBtn.mbYes,0, procedure(const AResult: TModalResult) begin if AResult = mrYes then StartLogin10 else ShowMessage('you have cancel the operation'); end ); end else ShowMessage('chose something from the list'); end;
-
No, that project has been dead for a long time. No. The only thing I can find is this: https://sourceforge.net/projects/indysoap/
-
There is no way to answer that without seeing your actual code, and a trace of the underlying HTTP traffic. But the fact that your whole app hangs suggests that either you are not using threading correctly, or your main UI thread is waiting on the HTTP thread when it shouldn't be.
-
Then you should be fine using the latest Indy with OpenSSL 1.0.2, as it supports TLS 1.2
-
Can somebody help me to translate a short Delphi console app to C++ Builder?
Remy Lebeau replied to TurboMagic's topic in General Help
It is not enough to just use the .hpp files, you have to link to the RTL library as well. You are not finding SYSTEM.CLASSES.OBJ because is not actually a standalone file that exists anywhere. System.Classes is a unit that exists inside of the RTL. So make sure you are linking against rtl.dcp, IIRC. The easiest way to go is to just start with a newly created VCL-enabled console project and then add the translated C++ code into it as needed. -
GetSystemTime() is dependent on the local computer's clock/timezone being configured properly, which Ian doesn't want to rely on.
-
EIdTLSClientTLSHandShakeFailed is raised when another exception is caught internally during the SSL/TLS handshake process. So the EIdTLSClientTLSHandShakeFailed.InnerException should not be nil. What are the values of the ClassName and Message of that InnerException?
-
Can somebody help me to translate a short Delphi console app to C++ Builder?
Remy Lebeau replied to TurboMagic's topic in General Help
.hpp files are auto-generated by the Delphi compiler when run with the -JL or -JPHNE switch. See Creating C++ Files from DCC32 -
multi-threading question
Remy Lebeau replied to David Schwartz's topic in RTL and Delphi Object Pascal
A pool would make sense only if you want to limit the number of threads that are run simultaneously. Say, you have all 40 tasks, but you only want 10 to run at a time. So you create 40 tasks and put them in a queue, and then start the first 10 tasks, and each time a task finishes then it starts the next task in the queue until the queue is empty. If you are doing the wait in the main UI thread, MsgWaitForMultipleObjects() would be a better choice, so that you can detect when the message queue has pending messages waiting to be processed. But really, you shouldn't be waiting on the tasks at all, you should let them notify you when they are finished, like @Fr0sT.Brutal described. Except maybe at app shutdown, when you need to terminate and wait on any tasks that haven't finished yet. -
Can somebody help me to translate a short Delphi console app to C++ Builder?
Remy Lebeau replied to TurboMagic's topic in General Help
A straight C++ translation of the Hash_Console demo would look something like this: /****************************************************************************** The DEC team (see file NOTICE.txt) licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. A copy of this licence is found in the root directory of this project in the file LICENCE.txt or alternatively at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ******************************************************************************/ /// <summary> /// Most simple demonstration of DEC hash routines /// </summary> #include <vcl.h> #pragma hdrstop #include <System.SysUtils.hpp> #include <DECFormat.hpp> #include <DECHash.hpp> #include <iostream> #include <limits> int main() { THash_RipeMD160* Hash = new THash_RipeMD160; try { try { // Calculate a hash value in accordance to the original author's test data // http://homes.esat.kuleuven.be/~bosselae/ripemd160.html RawByteString s = "message digest"; std::cout << "RipeMD160 digest (hash value) of " << s.c_str() << " is \n" << Hash->CalcString(s, __classid(TFormat_HEX)).c_str() << std::endl; std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); THash_Whirlpool1* W = new THash_Whirlpool1; s = "The quick brown fox jumps over the lazy dog"; std::cout << "RipeMD160 digest (hash value) of " << s.c_str() << " is \n" << W->CalcString(s, __classid(TFormat_HEX)).c_str() << std::endl; delete W; std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } catch(const Exception &E) { std::wcout << const_cast<Exception&>(E).ClassName().c_str() << _D(": ") << E.Message.c_str(); } } __finally { delete Hash; } } -
Set the Selection property to a TGridRect containing all -1's. var gr: TGridRect; gr.Left := -1; gr.Right := -1; gr.Top := -1; gr.Bottom := -1; DrawGrid.Selection := gr;
-
Yes, it has done so for a very long time, since at least Delphi 5, probably even since TThread was first introduced. But just because it CAN doesn't mean it SHOULD. And like I have said, many people have had problems related to this "feature" over the years, which is why I never recommend relying on it.
-
That implies that Play() is acting synchronously, not exiting until the audio is finished, thus blocking the main thread from rendering UI updates. Is that actually the case? It should be running asynchronously instead.
-
Get rectangle of the button that was pushed on another form...
Remy Lebeau replied to RTollison's topic in General Help
Only if the mouse is being used to click the button in the first place, and not the keyboard. And even then, this is assuming the user does not have a system setting enabled that moves the mouse to a popup window's default button whenever a new popup opens. -
I always advise people NOT to rely on the TThread destructor terminating and waiting on the running thread, as doing so has been the source of many headaches in the past. Terminating and waiting on the running thread should always be an explicit operation before destroying the TThread object, IMHO.
-
Yes. Get rid of the use of TThread.CurrentThread when calling TThread.Queue(), pass nil instead, like I described earlier. Chances are that the thread is terminating before the Queue() requests are processed by the main thread, so they are getting cancelled. I would also suggest getting rid of the final call to TThread.Queue() after the loop, use the thread's OnTerminate event instead. Try this: procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin StopThread; end; procedure TForm1.StopThread; begin if Assigned(FMyThread) then begin FMyThread.Terminate; FMyThread.WaitFor; end; end; procedure TForm1.Button2Click(Sender: TObject); begin FMyThread := TThread.CreateAnonymousThread( procedure var I: Integer; begin for I := 1 to MaxValue do begin TThread.Queue (nil, procedure begin ListView1.Items.Add.Text := 'Th: ' + I.ToString; Button2.Text := I.ToString; end ); if TThread.CurrentThread.Terminated or Application.Terminated then Exit; end; end ); FMyThread.FreeOnTerminate := False; FMyThread.OnTerminate := ThreadFinished; FMyThread.Start; AniIndicator1.Visible := True; AniIndicator1.Enabled := True; ListView1.Enabled := False; ListView1.BeginUpdate; end; procedure TForm1.ThreadFinished(Sender: TObject); begin TThread.ForceQueue(nil, FMyThread.Free); FMyThread := nil; NotifyComplete; end; procedure TForm1.NotifyComplete; begin ListView1.EndUpdate; ListView1.Enabled := True; AniIndicator1.Enabled := False; AniIndicator1.Visible := False; end;
-
Note that passing a TThread object in the 1st parameter of TThread.Queue() will associate the request with that thread. If the thread terminates before the request is processed by the main thread, the request will be cancelled. The reason for this is to handle cases where a request accesses data/objects that exist inside the thread, you don't want the thread termination to invalidate that data before the request can use it. But, if the request does not depend on the thread, ie the anonymous procedure is able to capture everything it needs to run independantly, then you should set the 1st parameter to nil instead.
-
It is OK to wait on the thread if you use TThread.WaitFor() instead of WaitForSingleObject() directly. When TThread.WaitFor() is called in the main thread, it dispatches pending TThread.Synchronize()/TThread.Queue() requests while waiting for the thread to terminate. Just don't use TThread.WaitFor() with TThread.FreeOnTerminate=True, or else TThread.WaitFor() will crash when the thread actually terminates. If you do use WaitForSingleObject() directly, you can call it in a loop with a timeout so that you can call CheckSynchronize() periodically. Or, you can use (Msg)WaitForMultipleObjects() instead, waiting on both the thread and the global SyncEvent (and the message queue) at the same time. In this particular example, yes, since the thread does not depend on the results of the sync requests. But that is not always the case, sometimes Synchronize() is actually needed.
-
Get rectangle of the button that was pushed on another form...
Remy Lebeau replied to RTollison's topic in General Help
The mouse could have moved between the time it took the button click to be queued and processed and the time the dialog is displayed. If the DLL is being called in the context of the click handler, then GetMessagePos() would make more sense. But again, the button could have been invoked by the keyboard (or even programmably) instead of by the mouse. This is why I think it is better to hook and intercept the original click event itself so you can detect which button HWND is triggering the event in the first place.