Automatical initialisation lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- T3mp0 · 2025-09-09 14:30 It's my first post, so hello to everyone. I'm completely new to Lazarus (literally started today). I created a project and can't make it do two simple things: Start my server automatically.Give access to the procedure Log() to my second unit.If I put the code in a button and press it after the form is shown, everything works fine. But I want it to start automatically with my program without the need to press a button. The project has two units: Unit1 and Commands. The first unit has a form, the second had code only. Here is a part of both of them: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,  IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdContext,  Commands, IdGlobal; type   { TForm1 }   TForm1 = class(TForm)    btnStart: TButton;    btnStop: TButton;    MemoLog: TMemo;    TcpServer: TIdTCPServer;    procedure btnStartClick(Sender: TObject);    procedure btnStopClick(Sender: TObject);    procedure FormCreate(Sender: TObject);    procedure TcpServerConnect(AContext: TIdContext);    procedure TcpServerDisconnect(AContext: TIdContext);    procedure TcpServerExecute(AContext: TIdContext);  private    procedure Log(const S: string);  public   end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject);begin  // This doesn't work. Nothing is initiated.  TcpServer.DefaultPort := 5000;  TcpServer.Active := True;  Log('Server started on port ' + IntToStr(TcpServer.DefaultPort));  Commands.LogProc := @Log;  Log('Commands.LogProc created');end; procedure TForm1.btnStartClick(Sender: TObject);begin  // This works perfectly fine.  TcpServer.DefaultPort := 5000;  TcpServer.Active := True;  Log('Server started on port ' + IntToStr(TcpServer.DefaultPort));  Commands.LogProc := @Log;  Log('Commands.LogProc created'); end;                                          procedure TForm1.Log(const S: string);begin  MemoLog.Lines.Add(FormatDateTime('hh:nn:ss', Now) + ' ' + S);end;  Second unit: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Commands; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, IdContext, IdGlobal; type  TLogProc = procedure(const S: string) of object; var  LogProc: TLogProc; // <-- set from Unit1 procedure HandleCommand(AContext: TIdContext; const Cmd: string; const Data: TBytes); implementation procedure Test(AContext: TIdContext; const Data: TBytes);var  ClientVersion, UserID: LongInt;  DataToSend: TIdBytes;begin    LogProc('We are in the Test procedure');end;   Why do neither the server nor the Log procedure work without pressing the button? What's more, if I try to connect from the client, the program crashes. But not after I press the Start button. The exact same code that’s in btnStart is also in FormCreate (I also tried FormShow with the same result), but it seems like the program is ignoring what’s in FormCreate. I'll be grateful for an explanation and a solution. Cheers I forgot to mention. Calling Log from Unit1 works fine, no need to press the Start button. ---------------------------------------------------------------------- Thaddy · 2025-09-11 04:18 You can bypass the messaging/event based code by overriding the form's afterconstruction procedure:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.AfterConstruction;// also in the form's interface section as protected overridebegin  inherited AfterConstruction; // <--- don't forget!  TcpServer.DefaultPort := 5000;  TcpServer.Active := True;  Log('Server started on port ' + IntToStr(TcpServer.DefaultPort));  Commands.LogProc := @Log;  Log('Commands.LogProc created');end;The afterconstruction is called after the form and all its children are created and initialized but before the message loop starts. The difference with FormCreate is that it completely bypasses the messaging/event system. That means it is not interfered by the message loop. Why this should work? Especially with complex forms the message queue can be clogged with messages at start. This bypasses the message queue altogether. I have not tested the code, because I do not have Indy components installed, but I have used it in similar scenario's. ---------------------------------------------------------------------- Lutz Mändle · 2025-09-11 04:48 What is your operating system and what is in the lpr-file (I guess you have one)? ---------------------------------------------------------------------- Thaddy · 2025-09-11 05:22 I have tested your code with my afterconstruction suggestion and that works. Just added missing execute code and renamed test() to HandleCommand proc implementation in command.pas. (also works) Removed the buttons and unnecessary stuff altogether for the benefit of this demo. Used the Indy TidTCPServer as you did.Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, fphttpserver, Forms, Controls, Graphics, Dialogs, StdCtrls,  IdTCPServer, IdCustomTCPServer, IdContext,commands; type   { TForm1 }   TForm1 = class(TForm)    tcpserver: TIdTCPServer;    Memo1: TMemo;    procedure tcpserverExecute(AContext: TIdContext);  private   procedure AfterConstruction;override;     procedure Log(const s:string);  public   end; var  Form1: TForm1; implementation{$R *.lfm} { TForm1 } procedure TForm1.tcpserverExecute(AContext: TIdContext);begin  //end; procedure TForm1.AfterConstruction;begin  inherited AfterConstruction;  TcpServer.DefaultPort := 5000;  TcpServer.Active := True;  Log('Server started on port ' + IntToStr(TcpServer.DefaultPort));  Commands.LogProc := @Log;  Log('Commands.LogProc created');end; procedure TForm1.Log(const s: string);begin  memo1.lines.add(s);end; end.Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Commands; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, IdContext, IdGlobal; type  TLogProc = procedure(const S: string) of object; var  LogProc: TLogProc; // <-- set from Unit1 procedure HandleCommand(AContext: TIdContext; const Cmd: string; const Data: TBytes); implementation procedure HandleCommand(AContext: TIdContext;const Cmd: string; const Data: TBytes);var  ClientVersion, UserID: LongInt;  DataToSend: TIdBytes;begin    LogProc('We are in the Test procedure');end; end.If it still does not work the only place where you could make a mistake is in tcpserverExecute but you did not show code for that.