-
Content Count
380 -
Joined
-
Last visited
-
Days Won
4
Everything posted by Clément
-
Receiving UDP packet fails 2 times with 10014 and works
Clément posted a topic in ICS - Internet Component Suite
Hi, I'm using 12.1 with ICS 8.69. This code is driving me nuts. procedure TDiscoverClient.event_ServerReply(aSender: TObject; ErrCode: Word); const _BufferSize = 1024; begin if errCode = 0 then begin var lBuffer : Tbytes ; var lFromSock : TSockAddr; var lFromLen : Integer; var lCount : Integer; SetLength( lBuffer, _BufferSize ); lcount := fSender.ReceiveFrom(@lBuffer[0], _BufferSize, lFromSock, lFromLen ); if lCount>0 then begin if Assigned( fOnHostFound ) or Assigned(fOnHostAlive) then begin var lRespParts := SplitString( TEncoding.ANSI.GetString( lBuffer,0,lCount ),':'); var lServerMachineName := ''; var lServerMachineIP : String := String(inet_ntoa(lFromSock.sin_addr)); if lRespParts[0] = 'M' then lServerMachineName := lRespParts[1]; if Assigned(fOnHostFound) then fOnHostFound(Self, lServerMachineIP,lServerMachineName ); if Assigned(fOnHostAlive) then fOnHostAlive(Self, lServerMachineIP,lServerMachineName ); end; end else fErrMsg := Ics_WSAGetLastError; end; end; The code is executed from a child form, from my main VCL application. I need to check if a UDP server is alive ( or found). Anyway, I always get 2 times lCount = -1, and fErrMsg is assigned 10014 both times, the 3rd times it works and shows correctly the expected information. I tried several combinations to allocate lBuffer, and every one fails with 10014 the first 2 times, and the third is goes. The client machine, where this code runs, has only IPv4 active. The UDP server runs both IPv6 and IPv4, but is only bound to Ipv4 at 0.0.0.0 Can someone shed some light? TIA, Clément -
Receiving UDP packet fails 2 times with 10014 and works
Clément replied to Clément's topic in ICS - Internet Component Suite
I'll fix the code and take a look at the component. Thanks -
Service monitoring other services activities
Clément posted a topic in Algorithms, Data Structures and Class Design
Hi, I'm using Delphi 12 for this one. There are several Window Services applications working in a lot of different tasks. For example: A Schedule service, with thread managers and worker threads execute tasks at specific times. A Communication Service, with several thread managers, each with it's own sets of working threads which handles communication with TCP (or UDP) devices. A Batch service with several thread managers, each with a set of working threads which handles batch... Well as the application grew over the years, there are more and more thread managers handling more and more workers.... Sometimes Sht hits the fan, and some threads just stops responding. Sometimes it's a worker, which might be replaced by the manager, but sometimes it's a manager thread that goes bananas. I would like to write another service, a thread monitoring service, where I want to "send somehow" a heartbeat from each worker thread ( from all the other threads ). I want to know when a worker thread went bananas, but mainly when a manager threads goes bazinga. Some of the errors we detected: out of memory, out of disk space, file is used by another process ( usually anti-virus), SQL query Error ( invalid customer data ), SQL Query error ( invalid instruction ), Server Database went in maintenance mode, Database not available (communication lost, disk is full, backup taking to long), Bad Windows Server Patch , Windows update, and the list goes on and on. All the above describes actually problems that leads a worker or a manager to fail. Sometimes we can track what happened and reply our SLA in time. But sometimes it's just a nightmare. Nobody did anything and nobody changed anything... I guess I want the safest IPC in this context. For this to work, the worker thread cannot freeze while sending a heartbeat. For know, just knowing what thread stopped will be enough. I suspect a lot of things, but even with a lot of logs sometimes is very hard to track down what is happening, especially when the customer is eager to blame me. At least, the idea is to detect a "worker strike" or a "manager riot" as early as possible. Any tips? -
Hi, Just upgraded to 12.2, and the installation completed without any errors. All my components are installed, everything is fine. I opened my latest project, and the code editor blinks for every key I press. Seems to be relate to an automated syntax check. Every key I type triggers a syntax checker (that pop's the error in the "Structure" window) blinks the entire code editor. *very* annoying Hopefully there's a checkbox to disable this. Any one experienced this? Is there away to disable it?
-
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
Unfortunately the flicking still exists. I stopped the service and started the IDE. -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
I removed "Smooth fonts" from RDP parameters. And it still blinks. For the sake of testing, I removed every option: And it still blinks. -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
I disable most of new features IDE (one by one, and restarting the IDE after each change). Still blinks. -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
I'll give you it's an old machine/graphic card... the same I used with 12.1, 11.x, 10.x ... where there was no blink. -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
I can access my development machine in three ways. 1) Physically. I have access to the actual machine. 2) Remotely using VPN and RDP. 3) In the office, I use a physical machine with 2 VMs. One of those VM I'm using to open a VPN/RDP to access my development machine. After migrating to 12.2 I noticed some blinking when accessing my machine using the VM (method 3): There was the blinking. Using method 2 : blinking with method 1 no blinking at all. What's happening ( when using method 2 and 3) : As I type my code, some syntax check takes place. The code editor light ups a few areas of the IDE. For example, Red exclamation dots on the margins, the squirrels lines below invalid code, the structure windows displays the errors. During all that action, the lines in the code editor flashes very fast. And as I type the code to "resolve" the errors, the code editor blinks. It didn't happened with 12.1. I tried a few settings to optimize my RDP connection, but the blinking is still there. The optimization helped reducing a little. -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
I just accessed the machine without VM and the code editor doesn't blink. Is there any special new settings for RDP access? -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
Yes. I've tried Remote Desktop using single monitor and dual monitor ( my usual setup ). I have not changed anything in my connectivity. I just upgraded from 12.1 to 12.2 -
Delphi 12.2 code editor blinks for every key I press
Clément replied to Clément's topic in Delphi IDE and APIs
The tools I have right know didn't manage to capture correctly. I have to use my phone. https://www.dhs.com.br/downloads/IDE_12_2_Blink.mp4 Even with the phone, it quite don't show how annoying it is.. but every key blinks -
Using TSslHttpAppSrv to download a Binary file
Clément posted a topic in ICS - Internet Component Suite
Hello, I'm using 8.69, I can't update right now, and Delphi 12.1. I wrote a TUrlHandle child class to handle download of binary files. In this case zrnbw file. I'm unable to figure out how to do it. I'm missing a lot of things. With this code, any client application that connects to my appServer hangs after sending the download request. How would be the right way to handle downloading of binary data? TIA procedure THandler_files_UpdateDownload.Execute; const NO_CACHE: String = 'Pragma: no-cache' + #13#10 + 'Expires: -1' + #13#10; begin inherited; var lBasename : String; var lZrnbwFile := ''; var lParams := TStringList.Create('"', '&', [soStrictDelimiter]); try lParams.DelimitedText := Client.Params; lBaseName := TNetEncoding.URL.Decode( lParams.Values['basename'] ); lZrnbwFile := TPath.Combine( glbServerConfig.DefaultUpdate, lBasename+'.zrnbw'); if FileExists(lZrnbwFile) then begin DocStream := TFileStream.Create( lZrnbwFile, fmOpenRead ); AnswerStream('','application/binary',NO_CACHE); //Client.DocStream.Free; end finally lParams.free; end; end; -
Using TSslHttpAppSrv to download a Binary file
Clément replied to Clément's topic in ICS - Internet Component Suite
That was it! Thank you! -
Looking for Advice on Improving the Performance of Delphi Applications
Clément replied to Andro12's topic in Tips / Blogs / Tutorials / Videos
There are lot's of ways to "slow your application". That's why it's important to have some code sample. I will assume you're already using "beginUpdate / EndUpdate" and/or "DisableControls / EnableControls" as also "LockDrawing / UnLockDrawing". That said, the best way to handle large dataset is to avoid working with large datasets up to the last minute, specially if there's any kind of visual binding. This will slow things down: Be sure to handle you data visualization carefully. It should (almost always) be faster to order your records server side, you should construct your order clause and feed the user with the amount of data required for his/her operation. The same goes to filtering. If you know the table you are querying, you should construct your "where clause" carefully to be sure there's an index backing it up. Managing large amounts of data client side will impact considerably memory. For example, if you need to traverse your dataset backwards and forwards, as most TDBGrid ( and alike ) requires, you will use more memory than Forward Cursor Only. If you require to order your dataset with several "memory created index", you will use more memory. Memory client datasets will require more ( or less ) memory depending on the amount of features implemented. And if things get really complex, you can consider having a local database. -
Hi, I have no idea where to ask for help, but hopefully that post might help other Delphi developers. I'll try not to make an advertise 😁 I've build a program to help Network Administrator to monitor a network with two editions: Community edition (Free) and Professional Edition (Paid). The Community edition has the basic functionality and can be upgraded to Professional Edition. I've build an eStore to control the license and payments ( Delphi / PHP). The application show the modules to purchase and launch a link to the payment service provider (PSP). Once the payment is done, my eStore receives a notification from the PSP, processes it and the license is unlocked. Currently I'm supporting Paypal for international purchase and Paypal and Cielo for local purchase ( Purchase made in Brazil ). Both Paypal and Cielo are working flawlessly, but some friends told me that Paypal is not well seen by companies and will search for other application just because "Paypal is not company friendly". I was wondering if someone has a better experience with some other PSP that can be added/integrated in my store. As I intend to sell oversea what are the options I have that are "company friendly" that can work with Delphi. I will mostly focus on credit card payment. TIA, Clément
-
Ok... This is the final version. tcpPing_test.zip I had to make some changes. Your sample helped a lot @Kas Ob. ! I had to remove TCP_NODELAY. Even in your sample, using this fellow messed up the last ACK leading to the retransmission sequence. I had to change some calls and used "TAddrInfo" instead of "TAddrInfoW". In the final example, I manage to make it work with both, but kept the TaddrInfo call. I remove the call to "bind". I'm no longer using "send" but "select". The class might need some polishing, but I believe it will be an example of using vanilla sockets... (good or bad) 😉 At least I got the sequence right, and I believe the application is not leaking any handles HTH, Clément
-
Still no Joy. For some reason SACK_PERM is still there. I just can't understand whats wrong. It is pinging all right, but that last ACK is missing and TCP Retransmission goes on for a few ms... In case you need to have some sunday fun day no ACK day, I attached a sample project. tcpPing_test.zip
-
This is the shutdown procedure. I'm trying everything, but I'm not able to send that last ACK 🤯 function TdhsTCPping.DoShutdownConnection(aSocket: TSocket): Boolean; const DEFAULT_BUFLEN = 1024; var conResult : integer; lErrorCode : Integer; lBufferRead : Array of byte; lBytesRead : Integer; Done : Boolean; begin Result := false; conResult := shutdown(aSocket, SD_SEND ); // Shutdown connection since no more data will be sent if (conResult = SOCKET_ERROR) then begin lErrorCode := WSAGetLastError(); raise EdhsTCPPing_SocketError.CreateFmt('shutdown SD_SEND failed with error: %d/0x%X', [lErrorCode,lErrorCode]); end; // Receive until the peer closes the connection. { SetLength(lBufferRead, DEFAULT_BUFLEN ); done := false; while (not done) do begin conResult := recv(aSocket,lBufferRead[0],DEFAULT_BUFLEN,0); case conResult of SOCKET_ERROR : begin lErrorCode := WSAGetLastError; if lErrorCode <> WSAEWOULDBLOCK then begin Done := true; DoNotifyPingError('Done!'); end else begin // DoNotifyPingError('Waiting response...'); Sleep(50); // Done := true; end; end; 0 : begin done := true; // Connection closed Result := true; end; else // bytes received!! // Ignore them for now, and keep readinf until the socket closes end; end;} conResult := closesocket(aSocket); if (conResult = SOCKET_ERROR) then begin lErrorCode := WSAGetLastError(); raise EdhsTCPPing_SocketClose.CreateFmt('CloseSocket failed with error: %d/0x%X', [lErrorCode,lErrorCode]); end else Result := true; end; Some say I must read into a buffer while receiving "WSAEWOULDBLOCK", but this is loop never ends as I keep receiving this error all the time. If I set the buffer length to 64k eventually I get a WSAECONNRESET but Wiresharks reports 7 to 10 TCP Retransmission before the [RST,ACK] Is there any option I must when configuring the socket to close that connection gracefully?
-
Using TCP_NODELAY: 192.168.0.5:80 8.1591 (Connected) 192.168.0.5:80 0.3725 (Connected) 192.168.0.5:80 0.3950 (Connected) 192.168.0.5:80 0.5158 (Connected) I made some changes.. but I can send that last ACK. It's driving me nuts. Wire shark is reporting this: But it should show me: I must be messing the connection shutdown / close
-
Hi @Kas Ob. Your insight is always welcome. I'm implementing a "Ping" using TCP protocol. (Don't say it out loud !) I'm spending some time with wireshark, trying to get this sequence of packets: -> [SYN] <- [SYN,ACK] -> [ACK] -> [FIN,ACK] <- [FIN,ACK] -> [ACK] I noticed sending a 0 length packet seem to be a step in the right direction. I really don't know what to send.. Probably a glorious "tcp ping packet sent by dhsPinger" message in the final release The "not done" loop is handling both blocking and non-blocking calls. In this case, blocking makes no sense since the connection might take longer than a specified timeout. But the code is so simple and it makes no difference at this time... The "sleep", well, it's the poor man's way of not hogging the CPU in a loop The class need a lot more polishing, I'm focused on getting the right packet sequence.
-
I while back I was researching "TCP ping" for my application. I ended up encapsulating the calls in a class. I'm using vanilla sockets for this. unit dhs.tcpPing; interface uses WinSock, Winsock2; type TNotifyPingRequest = procedure( aSender : TObject; const apcHost : String; aPort : Integer; aConnected : Boolean; aResponseTime : Double ) of object; TdhsTCPping = class private fWSAStartup : Integer; fWSAData : TWSAData; fHints : TAddrInfoW; fAddrInfo : TAddrinfoW; fCurrentAI : PAddrInfoW; private fOnNotifyPingRequest: TNotifyPingRequest; function EstablishConnection( address : TAddrInfoW; ping_timeout : integer; var errorcode : integer; blocking : Boolean ):TSocket; function CheckAddrInfo( const pcHost : String; port : integer; ipv : integer ) : Boolean; function DoWinsock( const pcHost : String; port : Integer; times_to_ping : integer; ping_interval : double; ping_timeout : integer; blocking : boolean ) : Integer; function DoWinSock_Single( const apcHost : String; aPort : Integer; times_to_ping : integer; ping_interval : double; ping_timeout : integer; blocking : boolean ) : Integer; procedure DoNotifyPingRequest( const apcHost : String; aPort : Integer; aConnected : Boolean; aResponseTime : Double ); public constructor Create; destructor Destroy; override; function ping( const pcHost : String; port : Integer; times_to_ping : integer; ping_interval : double; ping_timeout : integer ) : Integer; property OnPingRequest : TNotifyPingRequest read fOnNotifyPingRequest write fOnNotifyPingRequest ; end; function ioctlsocket(s: TSocket; cmd: u_long; var argp: u_long): Integer; stdcall; implementation uses Winapi.Windows, System.SysUtils; constructor TdhsTCPping.Create; begin fWSAStartup := WSAStartup(MakeWord(1,1), fWSAData);; end; destructor TdhsTCPping.Destroy; begin if fWSAStartup=0 then WSACleanup; inherited; end; const ws2_32 = 'ws2_32.dll'; function ioctlsocket; external ws2_32 name 'ioctlsocket'; function TdhsTCPping.CheckAddrInfo( const pcHost : String; port : integer; ipv : integer ) : Boolean; var lPort : Array[0..5] of Char; lHostName : Array[0..255] of Char; lpAddrInfo : PaddrinfoW; r : integer; begin ZeroMemory(@fHints, sizeof(TAddrInfoW)); fHints.ai_family:= PF_UNSPEC; fHints.ai_socktype := SOCK_STREAM; StrCopy(@lHostName, PCHar( pcHost ) ); StrCopy(@lPort, PChar(Format('%d',[Port]))); lpAddrInfo := @fAddrInfo; r := getaddrinfoW(@lHostName[0],@lPort[0], fHints, lpAddrInfo ); fCurrentAI := lpAddrInfo; result := false; while Assigned(fCurrentAI) do begin if ((fCurrentAI.ai_family = AF_UNSPEC) and (ipv = 0)) or ((fCurrentAI.ai_family = AF_INET) and (ipv <> 6)) or ((fCurrentAI.ai_family = AF_INET6) and (ipv <> 4)) then begin Result := true; break; end; fCurrentAI := fCurrentAI^.ai_next; end; end; procedure TdhsTCPping.DoNotifyPingRequest(const apcHost: String; aPort: Integer; aConnected : Boolean; aResponseTime : Double ); begin if Assigned( fOnNotifyPingRequest ) then fOnNotifyPingRequest( self, apcHost, aPort, aConnected, aResponseTime ); end; function TdhsTCPping.DoWinsock( const pcHost: String; port: Integer; times_to_ping : integer; ping_interval : double; ping_timeout : integer; blocking : boolean ): Integer; var lAI : TAddrInfoW; lErrorCode , lLoopCount : Integer; cpu_frequency : int64; response_timer1 , response_timer2 : int64; response_time : Double; sd : TSocket; begin lLoopCount := 0; if CheckAddrInfo( pcHost, port, 4 ) then begin while (lLoopCount<times_to_ping) or ( times_to_ping = -1) do begin // QueryPerformanceCounter isn't thread safe unless we do this SetThreadAffinityMask(GetCurrentThread(), 1); // start the timer right before we do the connection QueryPerformanceFrequency(cpu_frequency); QueryPerformanceCounter(response_timer1); sd := EstablishConnection( fCurrentAI^, ping_timeout, lErrorCode, blocking ); // grab the timeout as early as possible QueryPerformanceCounter(response_timer2); response_time := (response_timer2 - response_timer1) * 1000.0 / cpu_frequency; inc( lLoopCount ); DoNotifyPingRequest( pcHost, port, sd<>INVALID_SOCKET, response_time ); if sd<>INVALID_SOCKET then begin shutdown( sd, SD_BOTH ); closesocket(sd); end; end; end; end; function TdhsTCPping.DoWinSock_Single( const apcHost : String; aPort : Integer; times_to_ping : integer; ping_interval : double; ping_timeout : integer; blocking : boolean ) : integer ; begin result := DoWinsock( aPCHost, aPort, times_to_ping, ping_interval, ping_timeout, blocking ); end; function TdhsTCPping.EstablishConnection( address : TaddrinfoW; ping_timeout : Integer; var errorcode: integer; blocking: Boolean): TSocket; (*-------------------------------------------------------------------------- Set the socket I/O mode: Blocking -> iMode = 0 !Blocking -> iMode <>0 https://learn.microsoft.com/pt-br/windows/win32/api/winsock/nf-winsock-ioctlsocket //------------------------- // Set the socket I/O mode: In this case FIONBIO // enables or disables the blocking mode for the // socket based on the numerical value of iMode. // If iMode = 0, blocking is enabled; // If iMode != 0, non-blocking mode is enabled. -------------------------------------------------------------------------- *) var timer1 : Int64 ; timer2 : Int64 ; cpu_freq : Int64 ; time_so_far : double; sd : TSocket; iMode : u_long; conResult : integer; sendstatus : integer; done : Boolean; begin // Create a stream socket sd := socket(address.ai_family, address.ai_socktype, address.ai_protocol); iMode := 1; if blocking then iMode := 0; ioctlsocket(sd, DWord( FIONBIO ), iMode); QueryPerformanceCounter( Timer1); QueryPerformanceFrequency( cpu_freq ); conResult := -999; conResult := connect(sd, address.ai_addr^, NativeUint(address.ai_addrlen) ); if (conResult = SOCKET_ERROR) and (iMode = 0) then begin errorcode := WSAGetLastError(); closesocket(sd); exit( INVALID_SOCKET ); end; sendstatus := 1000; done := false; while (not done) do begin sendstatus := send(sd, '', 0, 0); if (sendstatus = 0) then done := true; QueryPerformanceCounter(timer2); time_so_far := ((timer2 - timer1) * 1000.0) / (cpu_freq *1.0) ; if (time_so_far >= ping_timeout) then done := true else begin // Todo: Get rid of this sleep! if (time_so_far < 200) then Sleep(0) else Sleep(1); end; end; closesocket(sd); errorcode := WSAGetLastError(); if sendstatus = 0 then exit( sd ) else exit( INVALID_SOCKET ); end; function TdhsTCPping.ping(const pcHost: String; port, times_to_ping: integer; ping_interval: double; ping_timeout: integer): Integer; begin result := DoWinSock_Single(pcHost,port, times_to_ping, ping_interval,ping_timeout, false); end; end. And the example procedure TForm143.event_PingRequest(aSender: TObject; const apcHost: String; aPort: Integer; aConnected: Boolean; aResponseTime: Double); const _Conn : Array[ Boolean ] of String = ('','Connected'); begin Memo1.lines.add( Format('%s:%d %3.4f (%s)', [apcHost, aPort, aResponseTime, _Conn[aConnected]]) ); end; procedure TForm143.FormCreate(Sender: TObject); begin with TdhsTCPping.create do begin OnPingRequest := event_PingRequest; ping('192.168.0.5',80,5,1000,1000); free; end; end; In a TMemo the output looks like: 192.168.0.5:80 17.2611 (Connected) 192.168.0.5:80 0.5438 (Connected) 192.168.0.5:80 0.5148 (Connected) 192.168.0.5:80 0.3728 (Connected) 192.168.0.5:80 0.4739 (Connected) HTH
-
Trojan:Script/Sabsik.TE.A!ml detected (false positive of course)
Clément posted a topic in RTL and Delphi Object Pascal
Hi, I don't know if I can post here. But.. here it goes. I'm using Delphi 10.4.2 [Context] I built a small application 23MB to query several databases using fireDac (Oracle, SQL Server, MySQL, Interbase, Firebird and PostgreSQL for now, I might add support for other engine). The application checks if there's an update and notifies the users. The first check is done after 5 minutes. No database connection is done at startup. The application is available in 32 and 64bit [The problem] I'm doing some pre-public release with some friends. I'm sending them the 32bit version (compiled with Release, no debug, no madexcept, all default release options). I'm connecting to his computer using remote desktop, and I'm copying form my machine to his (Copy/Paste). Both are running Windows 10 Pro with latest updates. When the application is ran the first time, windows defender pops a screen notifying the user some actions are taken to prevent infection. The program opens, runs ( we can actually connect to database and runs some queries), and closes normally. The application won't run a second time. Windows pops a screen saying the application contains a virus, and shortly after, the application is deleted (quarantined). Well, for the fun I send the 64bit version release, no debug, no madexpects all default features. Copied the same way (via RDP copy/paste ) and the program ran smoothly. Windows defender didn't detect a thing. And my friend connected to the databases he have and tested the program for hours without any problem. Closed and Reopened it several times without any problems. I recompiled the 32bit version in debug mode (over 72MB executable). Copied the same way and windows defender didn't detect anything. Again running for hours, querying against several databases... I start changing some of the default Release options, and after setting [Runtime errors -> I/O checking] = false the 32bit version behaved as expected. I uploaded every version compiled in my machine to virus total and nothing was detected. (even the 32bit version windows defender didn't like) I uploaded every version copied to my friend machine to virus total and nothing was detected. So I can assume is a false positive... but that is a nasty Trojan!! This is why I started this post with the context. Since It connects to databases and checks for updates some antivirus might confuse those connections as "trojan invasion". But, as I said, no communication is done at start-time. Is there anything I can do? Has anyone had a problem like this one. (I'm not using any compressor, just plain vanilla executable generated from the IDE). Thanks, Clément --------------------- Trojan:Script/Sabsik.TE.A!ml Nível de alerta: Grave Status: Active Data: 01/09/2021 20:01 Categoria: Cavalo de Tróia (Trojan Horse) Detalhes: Este programa é perigoso e executa os comandos de um invasor. (This application is dangerous and execute command of an invader). Itens afetados: file: E:\Clement\ckwel.exe -
Trojan:Script/Sabsik.TE.A!ml detected (false positive of course)
Clément replied to Clément's topic in RTL and Delphi Object Pascal
I'm using an OV code signing certificate from Sectigo. Never had any problems with false positive since. -
Hi, I'm compiling a project (Delphi XE) with several millions lines and hundreds of units. Somehow a specific unit got called in that project, and I must discover which unit is dragging it in. It might be a direct reference or indirect reference (Since I'm a very lucky guy, it must be a deep indirect reference). In any case, I have to deal with it. Is there any tool that can help me track a specific unit linkage into a project? TIA, Clément