[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1122
  • Last Modified:

Problems with serial port service

I am trying to implement an service app to send serial port string to a TCPIP port. Although I can install and start the service as soon as I send data to it I get a windows error message 1073 'The specified service already exists'. After that I can not restart the service and have great difficulty in removing it. I am using

synaser package for the serial port app.

Any Ideas?
This is the code for the offending unit

Code-------------------------------------

unit SerialCollexServiceUnit2;

interface

uses
  synaser, sysutils,BlckSock, synsock, Classes, inifiles;

type
  TSerialModule1 = class(TDataModule)
    procedure DataModuleCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  SerialModule1: TSerialModule1;
  ser:TBlockSerial;
  IniFile : TIniFile;
  SerialSock:TTCPBlockSocket;
  par,LCMD,PortNo,ipaddress,ipport:String;
  Baud,databits,stopbits:integer;
  parity:char;
  hardwarefl,softwarefl:boolean;


   procedure sendcallstring(input:string);


implementation

{$R *.dfm}

 procedure sendcallstring(input:string);  Begin  SerialSock:=TTCPBlockSocket.Create;
 try
 SerialSock.RaiseExcept :=false;
 SerialSock.Connect(ipaddress,ipport);
 if SerialSock.lastError<>0 then exit;
 if SerialSock.CanWrite(1000) then
 SerialSock.SendString(input+CRLF);
 finally
 SerialSock.Free
 end;
 End;

procedure TSerialModule1.DataModuleCreate(Sender: TObject); begin

    IniFile := TIniFile.Create('serialcollex.ini');
    PortNo := IniFile.ReadString('serial','PortNo','COM1');
   Baud := IniFile.Readinteger('serial','baud',9600);
   databits := IniFile.ReadInteger('serial','databits',8);
   stopbits := IniFile.ReadInteger('serial','stopbits',0);
   par := IniFile.ReadString('serial','parity','N');
   parity := par[1];
   hardwarefl := IniFile.Readbool('serial','hardwarefl',false);
   softwarefl := IniFile.Readbool('serial','softwarefl',false);
   ipaddress := IniFile.ReadString('tcpip','ipaddress','127.0.0.1');
   ipport := IniFile.ReadString('tcpip','ipport','4515');
   ser:=TBlockserial.Create;
   try

     ser.RaiseExcept:=false;
     ser.Connect(PortNo);
     ser.Config(Baud,databits,parity,stopbits ,softwarefl,hardwarefl);

     while not (ser.LastError <> 0) do begin
            if ser.lastError<>0 then break;
              if ser.canread(1000) then  begin
              LCMD := ser.Recvstring(1000);
              writeLn(LCMD);
              sendcallstring(LCMD);
              end;

     end;
   finally
     ser.Free;
end;

end;

end.

End of code------------------------------------------------------

and the rest---------------------------------------------
unit serialcollexservice;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,serialcollexserviceunit2;

type
  TSerialCollexV2 = class(TService)
  procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  procedure ServiceStart(Sender: TService; var Started: Boolean);
  private
    { Private declarations }
  public
  FDataModule: TSerialModule1;
    function GetServiceController: TServiceController; override;
    { Public declarations }

  end;

var
  SerialCollexV2: TSerialCollexV2;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  SerialCollexV2.Controller(CtrlCode);
end;

function TSerialCollexV2.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;


procedure TSerialCollexV2.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  FDataModule := TSerialModule1.Create(nil);
  Started := true;
end;

procedure TSerialCollexV2.ServiceStop(Sender: TService;
  var Stopped: Boolean);
begin
  FreeAndNil(FDataModule);
  Stopped := true;
end;
end.
end of code---------------------------------------------------
0
lloydie-t
Asked:
lloydie-t
  • 4
  • 4
1 Solution
 
MerijnBSr. Software EngineerCommented:
what line in your code generates this message?
0
 
lloydie-tAuthor Commented:
It is a bit difficult to tell. As I compile and install the service. I am not sure how to run and debug a service.
0
 
MerijnBSr. Software EngineerCommented:
it's hard to debug a service,
maybe you can pinpoint it by showing some messageboxes from code, move them around to determine what line is causing this.

If you instantiate this datamodule from a normal application, can you reproduce anything then? (would make debugging a lot easier)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
JohnjcesCommented:
The error is (I think) that IP port 4515 is already in use on your computer, or that you are trying to send data and receive data on the same IP port.

1). Check and see if anything else is using that TCP/IP port

2). I am not familiar with the TCP/IP component you are using, but if you send data to the ipport try 4516 and 4515 to recieve the data from the ipport or vice-versa

Just a thought.

John
0
 
lloydie-tAuthor Commented:
HI I have alredy written a console app version to test and it seems to work fine. I have not included the ini settings.

code-------------------
program serialcollex;

{$APPTYPE CONSOLE}

 uses
  synaser,
  sysutils,BlckSock, synsock;

var
   ser:TBlockSerial;
   Sock:TTCPBlockSocket;
   LCMD:String;

 procedure sendcallstring(input:string);
 Begin
 Sock:=TTCPBlockSocket.Create;
 try
 sock.RaiseExcept :=false;
 sock.Connect('127.0.0.1','4515');
 if sock.lastError<>0 then exit;
 if sock.CanWrite(1000) then
 sock.SendString(input+CRLF);
 finally
 sock.Free
 end;
 End;


 begin
   ser:=TBlockserial.Create;
   try
     ser.RaiseExcept:=false;
     ser.Connect('COM1');
     ser.Config(9600,8,'N',0,false,false);

     while not (ser.LastError <> 0) do begin
            if ser.lastError<>0 then break;
              if ser.canread(1000) then  begin
              LCMD := ser.Recvstring(1000);
              writeLn(LCMD);
              sendcallstring(LCMD);
              end;

     end;
   finally
     ser.Free;
   end;
 end.
-----------------------------------------------------

0
 
MerijnBSr. Software EngineerCommented:
you should try to make a piece of code which works in a (console) app, and then use that exact piece of code in your service app.

So in your case you'd want to use the DataModule you have in your service app in a loose application, exactly as you use it in your service app.
0
 
lloydie-tAuthor Commented:
revised the console app to be similar to the service app, but I can not get the dos box to stay open.

---------------------------------
program serialProject1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  serialUnit1 in 'serialUnit1.pas' {DataModule1: TDataModule};

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    TDataModule1.Create(nil);
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

---------------------------------------------

unit serialUnit1;

interface

uses
  synaser, sysutils,BlckSock, synsock, Classes, inifiles;

type
  TDataModule1 = class(TDataModule)
  procedure DataModuleCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DataModule1: TDataModule1;
  ser:TBlockSerial;
  IniFile : TIniFile;
  SerialSock:TTCPBlockSocket;
  par,LCMD,PortNo,ipaddress,ipport:String;
  Baud,databits,stopbits:integer;
  parity:char;
  hardwarefl,softwarefl:boolean;

implementation

{$R *.dfm}

 procedure sendcallstring(input:string);
 Begin
 SerialSock:=TTCPBlockSocket.Create;
 try
 SerialSock.RaiseExcept :=false;
 SerialSock.Connect(ipaddress,ipport);
 if SerialSock.lastError<>0 then exit;
 if SerialSock.CanWrite(1000) then
 SerialSock.SendString(input+CRLF);
 finally
 SerialSock.Free
 end;
 End;

 procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
    IniFile := TIniFile.Create('serialcollex.ini');
    PortNo := IniFile.ReadString('serial','PortNo','COM1');
   Baud := IniFile.Readinteger('serial','baud',9600);
   databits := IniFile.ReadInteger('serial','databits',8);
   stopbits := IniFile.ReadInteger('serial','stopbits',0);
   par := IniFile.ReadString('serial','parity','N');
   parity := par[1];
   hardwarefl := IniFile.Readbool('serial','hardwarefl',false);
   softwarefl := IniFile.Readbool('serial','softwarefl',false);
   ipaddress := IniFile.ReadString('tcpip','ipaddress','127.0.0.1');
   ipport := IniFile.ReadString('tcpip','ipport','4515');
   ser:=TBlockserial.Create;
   try

     ser.RaiseExcept:=false;
     ser.Connect(PortNo);
     ser.Config(Baud,databits,parity,stopbits ,softwarefl,hardwarefl);

     while not (ser.LastError <> 0) do begin
            if ser.lastError<>0 then break;
              if ser.canread(1000) then  begin
              LCMD := ser.Recvstring(1000);
              writeLn(LCMD);
              sendcallstring(LCMD);
              end;

     end;
   finally
     ser.Free;
end;

end;

end.
-----------------------------------------
0
 
MerijnBSr. Software EngineerCommented:
don't test it in a console app.
Easiest is just to make a 'normal' app, create your datamodule in form1.create, and free it in form1.destroy
0
 
lloydie-tAuthor Commented:
MerijnB,
            I have obviously got something wrong with my basic code but not sure what. I tried to create a simple app using a datamodule and even that compiled with access violations and I can't work out why. SO first I need to sort out my understanding of what I am doing wrong. any help with the following appreciated.

first unit code-------------------------------------------------
unit serialcollex;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,unit1, StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  FDataModule: TSerialModule1;
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
FDataModule := SerialModule1.Create(nil);

end;

end.
end of code------------------------------------------------



datamodule code-------------------------------------------
unit Unit1;

interface

uses
  sysutils, Classes, dialogs;

type
  TSerialModule1 = class(TDataModule)
  procedure DataModuleCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  SerialModule1: TSerialModule1;

implementation

{$R *.dfm}

procedure TSerialModule1.DataModuleCreate(Sender: TObject);
 begin
    showmessage('help me pleeeeeeease');
end;


end.
end of code-----------------------------------------------------
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now