ScSSHShell executeCommand doesn't work
ScSSHShell executeCommand doesn't work
I've just purched SecureBridge and I'm trying to issue a command to an SSH Server using TScSSHShell.
I want to connect to the server, issue a command, and then return a result to the user. I want to do this in the background, rather than displaying the shell on screen (which is how the TScSSHShell works in the SecureBridge demo application). I have been running invalid commands to make sure an error message is written to the shell, and hence I have something to display (as far as I can work out, this is what should happen).
If I try using the executeCommand method, a blank string is returned (if the connection is set to be non blocking). If I set the connection to be blocking, the function doesn't return anything and the application hangs.
What am I doing wrong?
I'm using Delphi XE Professional, if that helps.
The code that I'm writing needs to run in the background, so I can't display a shell input screen to the user. The user enters some parameters on screen and clicks a button to run a command. For this reason, using writeString with non-blocking set to true is very inconvenient, because the onAsyncReceive event triggers several times (connecting to the server retrieves a welcome screen, as well as the command string and response). I'd have to do a lot of processing to check to see if the command has been run, so I know when I can disconnect the instance of TScSSHShell and return a result to the user.
I want to connect to the server, issue a command, and then return a result to the user. I want to do this in the background, rather than displaying the shell on screen (which is how the TScSSHShell works in the SecureBridge demo application). I have been running invalid commands to make sure an error message is written to the shell, and hence I have something to display (as far as I can work out, this is what should happen).
If I try using the executeCommand method, a blank string is returned (if the connection is set to be non blocking). If I set the connection to be blocking, the function doesn't return anything and the application hangs.
What am I doing wrong?
I'm using Delphi XE Professional, if that helps.
The code that I'm writing needs to run in the background, so I can't display a shell input screen to the user. The user enters some parameters on screen and clicks a button to run a command. For this reason, using writeString with non-blocking set to true is very inconvenient, because the onAsyncReceive event triggers several times (connecting to the server retrieves a welcome screen, as well as the command string and response). I'd have to do a lot of processing to check to see if the command has been run, so I know when I can disconnect the instance of TScSSHShell and return a result to the user.
This works for me, I execute the pwgen program on a ubuntu server:
procedure Tresetpass.gen_btnClick(Sender: TObject);
var
result:string;
begin
datamod.sshshell.Connect;
if datamod.sshshell.Connected then
begin
try
result:=datamod.sshshell.ExecuteCommand('pwgen -c -n -1');
result:= trim(result);
pf.password_edit.Text:=result;
pf.passwordconfirm_edit.Text:=result;
//copy the generated password to the clipboard
Clipboard.AsText:=pf.password_edit.Text;
finally
datamod.sshshell.Disconnect;
end;
end;
end;
procedure Tresetpass.gen_btnClick(Sender: TObject);
var
result:string;
begin
datamod.sshshell.Connect;
if datamod.sshshell.Connected then
begin
try
result:=datamod.sshshell.ExecuteCommand('pwgen -c -n -1');
result:= trim(result);
pf.password_edit.Text:=result;
pf.passwordconfirm_edit.Text:=result;
//copy the generated password to the clipboard
Clipboard.AsText:=pf.password_edit.Text;
finally
datamod.sshshell.Disconnect;
end;
end;
end;
Thanks for the advice. Using a thread is a good idea. However, I still have one big problem:snorkel wrote:I actually would use the blocking mode, and if takes a long time simply run it in a thread and use postmessage to return the string to the main app.
The code snippet I posted is using blocking mode and the pwgen executes very fast so there is no delay for the user.
What do I do when the command fails to return anything? I would need to terminate the thread, but if the thread is stuck waiting for the shell command to return, the terminate request would never get processed.
There are cases where this actually happens at the moment. I run a command, and nothing happens. I have a test application that doesn't use threads, and it just hangs.
A normal Windows socket, when used in blocking mode, uses TWinSocketStream to ensure that this situation never arises, but there's nothing here (as far as I can see) that does the same thing here. You just call executeCommand and hope that it works.
How can I prevent my application locking up if the executeCommand method doesn't ever return?
1. I'm created at Linux PC directory - Test.
Created connection, and now I want execute command: "cd Test".
But not want work.
If I try execute another command, such as "ls", "ls -la", "cat" ... it works.
"cd Test" and "cd .." - not work.
ScSSHShell1->ExecuteCommand("cd Test");
2. I'm created empty file - test.txt executed this command - "touch test.txt"
Then deleted it - "rm test.txt".
But not see standart warning message - "rm: remove regular empty file test.txt'?" and file deleted, without message.
If I'm use another ssh-client or console - all work good.
ScSSHShell1->ExecuteCommand("rm test.txt");
Emb. C++ Builder XE, SB 4.1.2
Created connection, and now I want execute command: "cd Test".
But not want work.
If I try execute another command, such as "ls", "ls -la", "cat" ... it works.
"cd Test" and "cd .." - not work.
ScSSHShell1->ExecuteCommand("cd Test");
2. I'm created empty file - test.txt executed this command - "touch test.txt"
Then deleted it - "rm test.txt".
But not see standart warning message - "rm: remove regular empty file test.txt'?" and file deleted, without message.
If I'm use another ssh-client or console - all work good.
ScSSHShell1->ExecuteCommand("rm test.txt");
Emb. C++ Builder XE, SB 4.1.2
The thing is that ExecuteCommand executes command in special 'Shell' mode. ExecuteCommand only sends one command to SSH server, SSH server executes this command, returns a result and closes the connection.
To solve the problem try to use the WriteString method instead of ExecuteCommand to send a command to the server. To get data from the stdout stream you can use the TScSSHShell.ReadString or TScSSHShell.ReadBuffer methods.
You can look at the example of using command line in the Shell tab of the SSHClientApp demo.
To solve the problem try to use the WriteString method instead of ExecuteCommand to send a command to the server. To get data from the stdout stream you can use the TScSSHShell.ReadString or TScSSHShell.ReadBuffer methods.
You can look at the example of using command line in the Shell tab of the SSHClientApp demo.
Please view the following topic: http://www.devart.com/forums/viewtopic. ... 7095#77095