Jump to content

Remy Lebeau

Members
  • Content Count

    2684
  • Joined

  • Last visited

  • Days Won

    113

Everything posted by Remy Lebeau

  1. Remy Lebeau

    problem with file attributes

    Then you likely don't have access to the file, or at least don't have permissions to ask the filesystem for its attributes. You need to call GetLastError() to find out why GetFileAttributes() is failing.
  2. Remy Lebeau

    problem with file attributes

    GetFileAttributes() can return INVALID_FILE_ATTRIBUTES for a number of different reasons, not just because the file does not exist. You have to use GetLastError() to differentiate the actual cause.
  3. Remy Lebeau

    IdHttp not connect IP Camera error 401

    I suggested EITHER approach, not BOTH. Use either BASIC or DIGEST. Did you verify that TIdHTTP is actually trying to send BASIC/DIGEST authentication in its request? I'm guessing either you are not setting the TIdHTTP.Request.Username/Password correctly (are you ABSOLUTELY SURE you are using the correct credentials? Are there any non-ASCII characters present in them?), or the camera is not accepting Indy's flavor of DIGEST authentication (BASIC is very, well, basic and difficult to get wrong). Can you provide an example showing the raw HTTP messages from start to end?
  4. Until a few months ago, I also depended on BCB6 for my full-time job (my software has reached its End-Of-Life, so this is no longer an issue), but in the past 15-odd years, moving it into a VM was never really an option. The physical machine it ran in was over 500GB of logs, databases, backups, etc, so cloning it would have taken forever. But more importantly, it had specialized PCI hardware installed that didn't work inside a VM, and I never had the time to create a new VM with just BCB6 installed. I would have had to continue running my apps on the physical machine, but used the remote debugger inside a VM, and I wasn't too keen on that approach, either,
  5. Remy Lebeau

    IdHttp not connect IP Camera error 401

    Your camera supports BASIC and DIGEST authentications. By default, TIdHTTP enables only BASIC authentication, which you are explicitly disabling by setting the TIdHTTP.Request.BasicAuthorization property to False. You need to either: re-enable BASIC authentication by setting TIdHTTP.Request.BasicAuthorization to True. enable DIGEST authentication by adding the IdAuthenticationDigest, or IdAllAuthentications, unit to your Form's uses clause.
  6. Remy Lebeau

    Delete a Registry Key...

    KEY_ALL_ACCESS is meant for admins only. You should specify only the exact rights you actually need (which FYI, TRegistry.DeleteKey() also requires KEY_QUERY_VALUE, since it calls RegQueryInfoKey() to determine the number of subkeys and the maximum subkey name length), eg: reg := TRegistry.Create(_DELETE or KEY_ENUMERATE_SUB_KEYS or KEY_QUERY_VALUE); Otherwise, just use the Win32 RegDeleteTree() or SHDeleteKey() function instead of TRegistry.DeleteKey(), and let the OS handle the necessary recursion.
  7. Correct. There is no Win32 API to enumerate and query existing tray icons. In the old days, the Tray was a simple toolbar that you could enumerate with standard Toolbar messages, but that would not get you any details about the app/window associated with each icon. With the redesign of the Taskbar and Tray in Windows 7 onward, I don't think that is doable anymore, or at least not 100%, due to the user's ability to hide icons.
  8. Remy Lebeau

    Close a TIdTCPClient connection

    No, they are not. All you really need is Disconnect(), or at least Socket.Close() if closing the socket from another thread. That is not an Indy error message, or any OS error message I have ever seen. So I am assuming you mean it is coming from the Barcoder Reader or Ethernet base (what is that supposed to be?) instead. Does the reader/base only allow 1 connection at a time? If you just yank out the network cable, it won't matter what you do on the client side, the connection will be lost on the server side and it will need time to process that loss, which may take awhile, depending on the server's implementation. Disconnect()/Close() will perform a graceful disconnect (send a FIN packet to notify the peer that the connection is being closed intentionally). That should allow the reader/base to free up the used slot immediately. However, it won't matter what you do in the case of the connection being lost abnormally, like from a network outage. All you can do in that case is wait for the reader/base to handle the loss on its end in its own time to make the slot available again.
  9. Maybe possible, but not easily. Once upon a time, you could use a WH_CALLWNDPROC hook to intercept WM_COPYDATA messages being sent to the Taskbar's "Shell_TrayWnd" window, and then extract the NOTIFYICONDATA info from those messages. But I'm not sure if that still applies anymore, what with all of the changes Microsoft has made to the Taskbar's system tray icon handling in the past decade.
  10. Remy Lebeau

    Install recent Delphi versions on Windows XP

    In that case, I don't recall offhand the last version that officially supported XP as a target platform. In the current DocWiki, versions prior to 10.1 Berlin do not say the specific Windows versions they target. 10.1 says Windows 7 SP1+, Windows 8-10, and Windows Server 2008-2012. I do know that there are a few areas of the modern RTL/VCL that make use of newer APIs that don't exist on XP, so 10.x-compiled executables are not likely to run as-is on XP.
  11. Remy Lebeau

    Thread Issues: using resume and start

    If the sole purpose of the thread is just to delay a UI notification, then TThread.ForceQueue() would be better, no thread needed at all: procedure THeaderFooterForm.Button1Click(Sender: TObject); begin TThread.ForceQueue(nil, procedure begin HeaderLabel.Text := 'My Job'; end ); end;
  12. Remy Lebeau

    Thread Issues: using resume and start

    The device should not matter, no. This is strictly an RTL error message that TThread.Start() raises if it can't resume a suspended thread, either because the thread is not allowed to resume (e, it is already finished), or the OS failed to resume the thread properly. Hard to say for sure what is going on without seeing the latest source code for TThread.
  13. Remy Lebeau

    Thread Issues: using resume and start

    I don't have the source for the latest version to look at, but in XE3 (the last version I do have source for), that specific error message only occurs under these conditions: - (Windows only) calling Start() on a running thread, or a thread that has had Suspend() called on it more than once before Start(). - calling Start() on a thread that has already finished, but not been destroyed yet - calling Start() on a thread created by reading TThread.CurrentThread in a thread context that is not owned by a TThread. None of those conditions apply to your TThread.CreateAnonynousThread() example. Calling Start() on such a thread is absolutely the correct thing to do. So this has to be a bug that Embarcadero has introduced in a recent version and will have to fix.
  14. Remy Lebeau

    Can't load LivePreview270.bpl

    They DO use a private copy, actually. It is hidden behind an abstraction layer that their technologies use internally. No need to rename units (I hate how IntraWeb does that for its private copy of Indy). Users are supposed to be free to update the public bundled copy of Indy without breaking the private copy. That is why the abstraction layer was created. Well, that is the theory anyway, but there are a few cracks where not all pieces are using the abstraction layer correctly/at all. DataSnap, LiveTiles, and now LivePreview it seems, depend on the shipped copy of Indy rather than the private copy. I have just filed a ticket with Embarcadero: RSP-33397: Can't load LivePreview270.bpl after updating Indy Same here. It is a goal to eventually get Indy added to GetIt, I just haven't had any time to work on it. Indy's complicated install steps for C++Builder need to be refined a bit first.
  15. Remy Lebeau

    Using Events when creating a component??

    First off, I would suggest getting rid of TempStream completely. You did not show what it actually is, but I'm assuming it is a TMemoryStream. You are using it only to determine the email's total byte size for progress tracking. Indy has a TIdCalculateSizeStream class you can use for that purpose instead. No need to hold on to a TStream object for the lifetime of the transmission. For example: private EmailSize: Int64; ... procedure TForm1.btnSendClick(Sender: TObject); var Attachmentfile: TIdAttachmentFile; sSendReportTo, sSendReportCC: string; CalcStream: TIdCalculateSizeStream; begin // IdSMTP1 := TIdSMTP.Create(nil); // try // IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP1); IdMessage1 := TIdMessage.Create(IdSMTP1); // // IO HANDLER SETTINGS // with IdSSLIOHandlerSocketOpenSSL1 do begin MaxLineAction := maException; SSLOptions.Method := sslvTLSv1; SSLOptions.Mode := sslmUnassigned; SSLOptions.VerifyMode := []; SSLOptions.VerifyDepth := 0; SSLOptions.Mode := sslmClient; end; // // SETTING SMTP COMPONENT DATA // IdSMTP1.Host := 'smtp-server.somewhere.com'; IdSMTP1.Port := 587; IdSMTP1.Username := 'MyName@somewhere.com'; // please change to your gmail address // IdSMTP1.Password := 'Abc123456'; IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1; IdSMTP1.AuthType := satDefault; IdSMTP1.UseTLS := utUseExplicitTLS; // IdSMTP1.OnWork := IdSMTP1Work; IdSMTP1.OnWorkBegin := IdSMTP1WorkBegin; IdSMTP1.OnWorkEnd := IdSMTP1WorkEnd; // // SETTING email MESSAGE DATA // IdMessage1.Recipients.EMailAddresses := 'ToAddress@somewhere.com'; IdMessage1.CCList.EMailAddresses := 'CCAddress@somewhere.com'; // add Attachment to mail // Attachmentfile := TIdAttachmentFile.Create(IdMessage1.MessageParts, 'E:\IndySMTPEmailTest\ReadMe.txt'); // IdMessage1.From.Address := 'myname@somewhere.com'; IdMessage1.Subject := 'Test Email Subject'; IdMessage1.Body.Text := 'Test Email Body'; IdMessage1.Priority := mpHigh; // with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := '<p style="color: #5e9ca0;">This is a test <strong>message</strong> for <span style="color: #ff0000;"><strong>emailing</strong></span>.</p><h1 style="color: #5e9ca0;"> </h1>'; ContentType := 'text/html'; end; // IdMessage1.ContentType := 'multipart/mixed'; // CalcStream := TIdCalculateSizeStream.Create; try IdMessage1.SaveToStream(CalcStream, False); EmailSize := CalcStream.Size; finally CalcStream.Free; end; // try IdSMTP1.Connect; except on E: Exception do begin MessageDlg('Connection to Mail Server unsuccessful! The following information was returned..: ' + E.Message, mtWarning, [mbOK], 0); Exit; end; end; try try IdSMTP1.Send(IdMessage1); finally IdSMTP1.Disconnect(); end; except on e: Exception do begin MessageDlg('Mail send unsuccessful! The following information was returned..: ' + E.Message, mtWarning, [mbOK], 0); Exit; end; end; // finally IdSMTP1.Free; end // ShowMessage('Email sent'); end; procedure TForm1.IdSMTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64); var nPercent: Integer; begin if AWorkMode <> wmWrite then Exit; // if EmailSize > 0 then begin nPercent := Trunc((Double(AWorkCount) / EmailSize) * 100); // ProgressBar1.Position := nPercent; Label1.Caption := IntToStr(nPercent) + ' %'; end else begin ProgressBar1.Position := 0; Label1.Caption := IntToStr(AWorkCount) + ' b'; end; Update; end; procedure TForm1.IdSMTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64); begin if AWorkMode <> wmWrite then Exit; Label1.Caption := '0 %'; ProgressBar1.Position := 0; ProgressBar1.Max := 100; ShowMessage('Stream Size = ' + EmailSize.ToString); Update; end; procedure TForm1.IdSMTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode); begin if AWorkMode <> wmWrite then Exit; ProgressBar1.Position := 100; Label1.Caption := '100 %'; Update; end; Your failure is happening inside of TIdMessage.SaveToStream() itself, so 99% of the code you have shown is irrelevant since it is not actually being used. That is because the code is failing before TIdSMTP.Send() is reached, so there is no progress to report. Since the crash is happening inside of TIdMessage.SaveToStream(), the events are not going to be fired at all, since there is no SMTP transmission in progress. As for why the crash is occurring in the first place, given the call stack shown, there are only 2 possibilities: - TIdIOHandler.ClosedGracefully is True when it should not be. This gets set when a read operation returns 0 bytes, a write operation fails with a non-timeout error, or TIdIOHandler.CloseGracefully() is called. - TIdIOHandlerStream.StreamingAvailable() is returning False when it should not be. This happens when there are no TStream objects assigned to the IOHandler. TIdMessage.SaveToStream() uses a write-only TIdIOHandlerStream, writing to the specified output TStream. So TIdIOHandlerStream should not be trying to read from a non-existent input TStream at all, thus TIdIOHandlerStream.StreamingAvailable() should always return True, unless the IOHandler has been closed prematurely. And TIdIOHandler.ClosedGracefully should never be False unless the target TStream fails to write, which would be an indication of a larger issue. And Indy never calls TIdIOHandler.CloseGracefully(). So, you are just going to have to do some debugging, and figure out which of the above conditions is actually causing TIdIOHandlerStream.CheckForDisconnect() to think it needs to raise the exception. It should not be happening under normal conditions.
  16. Remy Lebeau

    [FMX][Android]How get control name under the click?

    Why are you simply not using the Sender of the click event? procedure TMyForm.MyControlClick(Sender: TObject); begin ShowMessage(TControl(Sender).Name); end;
  17. Remy Lebeau

    INDY UDP broadcast to a specific Network

    If the OS can broadcast to multiple subnets using a single socket bound to local IP 0.0.0.0, then so be it. I just know that hasn't always worked that way. But maybe things are better in recent years. If there are multiple adapters installed, and you know what IP they are assigned, you can bind a separate socket to each one directly, eg: FUDPServer.Active := False; FUDPServer.Bindings.Clear; ... for I := 0 to FNetworksList.Count - 1 do begin with FUDPServer.Bindings.Add do begin IP := FNetworksList[I].LocalIP; Port := 5001; end; end; ... FUDPServer.BroadcastEnabled := True; FUDPServer.Active := True; This way, if you then Send...()/Broadcast() on any given Binding, it will send out only to that specific adapter/subnet directly, rather than the OS having to hunt around the routing tables to figure out which adapter/subnet to send out to, as is the case when calling Send...()/Broadcast() on a single Binding that is bound to 0.0.0.0. Operating Systems are pretty good at maintaining good routing tables, but they are not infallible. Sometimes routes are not configured properly, or get corrupted over time. So sometimes it may be easier/better to just be more direct and cut out the middle man.
  18. Remy Lebeau

    community.embarcadero.com's forums

    There is some info in this discussion:
  19. Remy Lebeau

    INDY UDP broadcast to a specific Network

    You can't bind a socket to a broadcast IP, you can only send data to a broadcast IP as the destination. You must bind the socket to the adapter's local network IP instead, eg; // inits and starts searching phase FUDPServer.Active := False; FUDPServer.Bindings.Clear; with FUDPServer.Bindings.Add do begin IP := '192.168.0.27'; Port := 5001; end; ... FUDPServer.BroadcastEnabled := True; FUDPServer.Active := True; And you can't bind a socket to an IP that does not belong to the local machine. In your screenshots, there is no local adapter present that has a local IP on the '192.168.120.x' subnet (unless you are filtering the adapters and we just can't see them all).
  20. Remy Lebeau

    INDY UDP broadcast to a specific Network

    Yes, you could specify the broadcast IP of the desired network, and let Windows figure out which adapter to use. Alternatively, rather than creating only 1 Binding that is bound to '0.0.0.0', you can create multiple Bindings, one for each network adapter (looks like you are already enumerating the adapters anyway), and then you can call Broadcast() on each adapter directly. That will allow you to search multiple networks at a time.
  21. Interfaces can't have 'class' methods, either. What is the actual GOAL that you are trying to accomplish? Can you provide a use-case example of what you WANT that is not working for you?
  22. Remy Lebeau

    Install recent Delphi versions on Windows XP

    Even if you could get it INSTALLED on XP, it won't RUN on XP. The IDE uses APIs and libraries that simply don't exist on XP.
  23. Remy Lebeau

    Adressing IP with System.Net.HttpClient

    In general, I could see this working if you connect the underlying TCP socket to the desired IP address, and then have the TLS handshake use the SNI extension to specify the desired domain name as the target for the certificate, and also have HTTP send a "Host" header specifying the same domain name. But I don't know if/how this can be done with THTTPClient, though. It is not doable with Indy's TIdHTTP (without hacking its source code) since everything uses the same hostname/IP specified in the URL.
  24. Remy Lebeau

    Does 10.4.2 overwrite 10.4.1

    This is covered in the documentation: http://docwiki.embarcadero.com/RADStudio/Sydney/en/10.4_Sydney_-_Release_2
  25. Remy Lebeau

    IdAntiFreeze vs VCL.IdAntiFreeze

    Indy should definitely NOT be in the VCL unit scope. It is not setup that way in Indy's official repo, so that is something extra that Embarcadero must have setup on their end. Why, I could not answer that. Indy is available to both VCL and FMX without using separate unit scopes.
×