-
Content Count
169 -
Joined
-
Last visited
-
Days Won
3
Everything posted by rvk
-
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Only start the timer during the start service sequence. But that's besides the point for this problem. BTW. The reason-phrase is optional in the http-protocol. See https://datatracker.ietf.org/doc/html/rfc9112#name-status-line Also it says that you should ignore it. -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Fun part is that if you do "project /install" (from an admin console) it momentarily runs as administrator. It then also runs the TTimer function and does give the OK correctly. (running in a user console also gives OK but then the service doesn't get installed obviously) You didn't put the TTimer.Enabled only for running the service but for every run, so also for the /install and /uninstall runs. After actually starting the service, it'll run as limited local system account, the TTimer function runs again but now the OK is not shown 😉 So I can confirm this on Windows 10, Delphi 10.2 (object pascal). So it's really the local system account in a service that's the problem here. Might limit the search. -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Oops. Hadn't noticed this was C++. Because this was posted in "RTL and Delphi Object Pascal" But I'm sure someone can test and confirm this. But am I understanding it correctly that it now always runs correctly as App and only fails as Service? Does the service run as user or admin? Did you test it the other way around? -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Could be that it's only a problem in service. Try to create a simple test project. If you can consistently let it fail, we can test it too. And if it's only in service that's also an indicator for which you can search. -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Have you tried a smaller (or simpler) POST to that page? Have you tried other URLs? Do you only have this (no OK) with that URL? Do you also have this only with POST or also with GET to that URL? -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Without knowing what it actually returns, this is hard to diagnose. You said the LSize was 274. So what's in Buf when the second call to WinHttpQueryHeaders returns? -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Because the resulting string only needs (LSize div 2) - 1 characters. LSize is the size in bytes. Result is an array of widechars/unicodechars which contain 2 bytes. So if LSize is 6 bytes (OK#0#0 in unicode) you only need 2 character string. 6 div 2 = 3 - 1 is 2 for OK. https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpqueryheaders -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
But what is the result of that call? Is it ERROR_WINHTTP_HEADER_NOT_FOUND or something else? -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
So, what happens if you (debug)trace into that ReadHeader? On what line does it 'crap' out? Do you get a ERROR_WINHTTP_HEADER_NOT_FOUND in that function? Do your response-headers contain a Content-Length? If not... is your input/response chunked? (that could be the cause of HEADER_NOT_FOUND) Is this happening with one certain URL or with all/more URLs? -
Well... Type in Oauth 2.0 communication in Google (or similar search terms), then select Images... and there you go... Lots of flow diagrams
-
BTW. You can still use app-passwords with Google. So if you are only doing this for you own account, creating an app password is easiest. If you need to allow your users to use their own account, then you need OAuth2.
-
No no, because you want to catch that URL it's easiest to create your own listening thread. I have an example for OAuth2 in combination with Lazarus/FPC and Synpase. (You can also use Synapse on Delphi but you could also use Indy) https://github.com/rvk01/google-oauth2 Relevant snippet: This is a minimalistic http server which server a string saying your program now has access and you can close the window. type THTTPServerThread = class(TThread) private ListenerSocket: TTCPBlockSocket; ConnectionSocket: TTCPBlockSocket; public Authorize_token: string; procedure Execute; override; procedure CancelThread(Sender: TObject; var CanClose: boolean); end; procedure THTTPServerThread.CancelThread(Sender: TObject; var CanClose: boolean); begin Terminate; end; procedure THTTPServerThread.Execute; var S: string; method, uri, protocol: string; OutputDataString: string; SendDataString: string; begin Authorize_token := ''; FreeOnTerminate := False; ListenerSocket := TTCPBlockSocket.Create; ConnectionSocket := TTCPBlockSocket.Create; try ListenerSocket.CreateSocket; ListenerSocket.setLinger(True, 10); ListenerSocket.Bind('localhost', '1500'); ListenerSocket.Listen; while not terminated do begin Sleep(1000); // Application.ProcessMessages; if ListenerSocket.CanRead(1000) and not terminated then begin ConnectionSocket.Socket := ListenerSocket.Accept; // read request line S := string(ConnectionSocket.RecvString(1000)); method := fetch(S, ' '); uri := fetch(S, ' '); protocol := fetch(S, ' '); // read request headers repeat S := string(ConnectionSocket.RecvString(1000)); until S = ''; // /?code=4/fegArZQDUJqFdoCw-1DU16ohYsoA5116feRuCW0LiuQ // /?error=access_denied Authorize_token := ''; if Pos('code=', uri) > 0 then begin Authorize_token := Copy(uri, Pos('code=', uri) + 5); end; if Authorize_token = '' then begin SendDataString := '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF + '<html><center><h1>Something went wrong.<br><br>Application does not have access.<br><br>You can close this page.</h1></center></html>' + CRLF; end else begin SendDataString := '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF + '<html><center><h1>Application now has access.<br><br>You can close this page.</h1></center></html>' + CRLF; end; OutputDataString := 'HTTP/1.0 200' + CRLF; OutputDataString := OutputDataString + 'Content-type: Text/Html' + CRLF; OutputDataString := OutputDataString + 'Content-length: ' + IntToStr(Length(SendDataString)) + CRLF; OutputDataString := OutputDataString + 'Connection: close' + CRLF; OutputDataString := OutputDataString + 'Date: ' + Rfc822DateTime(now) + CRLF; OutputDataString := OutputDataString + 'Server: Synapse' + CRLF; OutputDataString := OutputDataString + '' + CRLF; ConnectionSocket.SendString(ansistring(OutputDataString)); ConnectionSocket.SendString(ansistring(SendDataString)); ConnectionSocket.CloseSocket; Terminate; end; end; finally ConnectionSocket.Free; ListenerSocket.Free; end; end;
-
This error page seems to be a step further in the normal OAuth2 process. You accepted the non-verified app, accepted the terms and now you end up on localhost with the desired code for getting the access token in the url parameters. You need to catch that url with a small http server. After getting that code from the url you can go ahead with the process of getting the access and refresh token.
-
O, now I see what you are doing. But if the TPanel is below the TDBGrid then this line is wrong: RecPanel.Parent:=TDBGrid(AOwner); Because the parent isn't TDBGrid but the owner of TDBGrid (which is TForm or TPanel or something). So the AOwner parameter in the create call isn't the TDBGrid itself. You probably get away with it because casting TForm to TDBGrid will point to the same TWinControl object which is stored in TPanel.Parent. But the cast like this is not correct. You probably want to do something like: RecPanel.Parent:=TWinControl(AOwner); But then you need to create TEnhDBGrid with the Form as Owner !! (which is default but not always guaranteed). You might want to do RecPanel.Parent:=Self.Parent; // this would be the same parent as the TDBGrid But that goes wrong because if you create the component dynamically (like I tried) you don't have a parent yet (because that's assigned after TEnhDBGrid.Create(Formx) call). Anyway... you also can't do TEnhDBGrid.Align := alClient now because the dangling panel below it would be out of view That's why it might be more stable if a complete container is created with a TDBGrid and TPanel inside it. Just a thought BTW. You could also do it like TJvDBGridFooter does. (just a inherited TStatusbar where you can define columns which get summed up). But there the TJvDBGridFooter and TDBGrid are really separated from each other (component wise) and it's up to the programmer to place the TJvDBGridFooter.
-
Do you want that panel over the TDBGrid? That would mean interference when using scrollbar and last record etc. It might be better to do a complete TPanel and create the lower TPanel (alBottom aligned) with recordcount and a TDBGrid with alClient aligned. You could even use a sort of TStatusbar. With correct alignment (or correct anchors) all your sub-components should resize automatically with the container. I used my own statusbar for showing recordcount. I also implemented a OnScroll event to check if the TDataset has already reached the EOF. If it didn't, then you can't be certain of the recordcount and you can indicate that with a + after the count. Once TDataset.EOF has been reached, the TDataset.Recordcount is accurate (and the + can be dropped). At least... that's how I do it.
-
So, you have an underlying dataset where RecordCount is always accurate when there are more records then in view? Because often TDataset.RecordCount isn't the actual count of records in the final result. In that case you would need to show something like: 1/4+ or 1/>4 (Or do a TDataset.Last + TDataset.First after opening to get the correct RecordCount)
-
If you need IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY flag (which seems to be required in some cases) then you do need it. For example Windows kernel drivers (??). https://learn.microsoft.com/en-us/archive/technet-wiki/255.forced-integrity-signing-of-portable-executable-pe-files
-
XE3 was the first to support Windows 8. Delphi 2009 was the first to support Windows 7. see https://nl.wikipedia.org/wiki/Delphi_(software) So finding the highest versions supported is not difficult. But are you more interested in the lowest version? For Windows XP it was always advised to upgrade to at least SP2 from very early on. Do you still have machines with SP1 or even without SP ?? From an old Delphi XE PDF (at the bottom): http://www.embarcadero.com.pl/produkty/starter-tools/xe/delphi-data-sheet.pdf
-
No, unfortunately TWebBrowser.Document isn't available for FMX. https://stackoverflow.com/a/41853823/1037511
-
Ah, ok. I thought the default for DoubleBuffered was true. But I am probably mistaken (it is true in Lazarus unless in a remote session but apparently not in Delphi).
-
You didn't set DoubleBuffering to false for the TFrame itself (at least not in the code I saw). So if there (for TFrame) it is still true, then SingleBufferingInRemoteSessions = false would make the difference.
-
Woops, sorry. The Application.SingleBufferingInRemoteSessions is true as default. You should try to set it to false so the RDP acts the same as without RDP regarding doublebuffering. http://docwiki.embarcadero.com/Libraries/Alexandria/en/Vcl.Forms.TApplication.SingleBufferingInRemoteSessions
-
Yes. So you could set SingleBufferingInRemoteSessions to true to test if enabling DoubleBuffering in RDP would help. (turning on DoubleBuffering manually doesn't have effect if SingleBufferingInRemoteSessions is still set to false) If it doesn't help, then it must be something else.
-
https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Double-buffering_and_Remote_Connections
-
PS. You testproject in your openingspost works for me (Compiled on Delphi 10.2, Windows 10 and RDP'ing to a Windows 10 Hyper-V). Panel show solid (without memo1 bleeding through).