No problem to help you, but you need to share some more info with me about what your app should do etc.
2nd question - why did you put the part of the code into a separate component? I am referring to the other thread here on the forum.
I would go for a separate component if I have a GUI widget, or if there is a lot of reusable code to make sense for a separate component, unit or class.
If you are doing it for a learning experience - I can understand that, and I will help you.
I would begin with redesigning your component TLSB:
- chose a better name, LSB normally stays for Less Significant Bit. It can lead to some confusion.
- make it more universal, with published properties like Command and Arguments. This way you expand the usability of your component - run any terminal command with arguments and catch the output.
This is how I would do it:
unit TerminalRun;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Controls, StdCtrls, Process;
type
TTerminalRun = class(TCustomControl)
private
FCommand: string;
FArguments: string;
FMemo: TMemo;
function DoRunCommand: boolean;
protected
procedure CreateWnd; override;
public
constructor Create(AOwner: TComponent); override;
function Run: boolean;
published
property Command: string read FCommand write FCommand;
property Arguments: string read FArguments write FArguments;
property Align;
property Anchors;
property Font;
property ParentFont;
property ParentShowHint;
property ShowHint;
property TabOrder;
property TabStop;
property Visible;
end;
procedure Register;
implementation
constructor TTerminalRun.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
with GetControlClassDefaultSize do
SetInitialBounds(0, 0, 688, 150);
// Initialize the memo
FMemo := TMemo.Create(Self);
FMemo.Parent := Self;
FMemo.Align := alClient;
FMemo.Font.Name := 'Monospace';
// Initialize the variables
FCommand := '';
FArguments := '';
end;
procedure TTerminalRun.CreateWnd;
begin
// Do we really need this?
inherited CreateWnd;
// Additional initialization if necessary
end;
function TTerminalRun.Run: boolean;
begin
Result := False;
if FCommand <> '' then
Result := DoRunCommand;
end;
function TTerminalRun.DoRunCommand: boolean;
var
outstr: string;
begin
Result := RunCommand(FCommand, [FArguments], outstr); // @TRon's
if Result then
FMemo.Lines.Add(outstr)
else
FMemo.Lines.Add('Error executing command ' + FCommand + ' ' + FArguments);
end;
procedure Register;
begin
RegisterComponents('Linux Sysinfo', [TTerminalRun]);
end;
end.
So, I've added two properties - Command and Arguments. I've added a function Run with feedback as boolean. I've converted your DoRunCommand to a function to get feedback. See, the RunCommand is also a function, so you can get a feedback if successfully run or not. We add some checks in Run function and also include this in final feedback. There are better ways to get the error info if the function did not succeed, but let leave it at this simple method for now.
Don't put DoRunCommand in Create method - this is a bad idea because it is also executed in the IDE, at design time. If your DoRunCommand triggers an exception, you will lock your IDE. With my new organization of the code, where you need to set the Command and the Arguments before Run, it won't work anyway. You need to take care about the code that it is executed also in the IDE at the design time, to not lock your IDE.
To use the component, one must set the command and the arguments, and execute the Run function after that. You do this from your main unit/form.