I am using C# with SSH.NET.
I want to issue a PWD command but could not find any documentation or help. I do not know how to use 'SshClient' class.
Update:
I also tried experimenting with SshClient class using the below code but it does nothing, neither any error nor any exception.
ConnectionInfo ConnNfo = new ConnectionInfo("FTPHost", 22, "FTPUser",
new AuthenticationMethod[]{
// Pasword based Authentication
new PasswordAuthenticationMethod("FTPUser","FTPPass")
}
);
using (var ssh = new SshClient(ConnNfo))
{
ssh.Connect();
if (ssh.IsConnected)
{
string comm = "pwd";
using (var cmd = ssh.CreateCommand(comm))
{
var returned = cmd.Execute();
var output = cmd.Result;
var err = cmd.Error;
var stat = cmd.ExitStatus;
}
}
ssh.Disconnect();
}
Nothing happens. Neither an error nor an exception. On Visual Studio console, i get the below output.
*SshNet.Logging Verbose: 1 : SendMessage to server 'ChannelRequestMessage': 'SSH_MSG_CHANNEL_REQUEST : #152199'.
SshNet.Logging Verbose: 1 : ReceiveMessage from server:
'ChannelFailureMessage': 'SSH_MSG_CHANNEL_FAILURE : #0'.*
At ssh.RunCommand method call the program goes in some sleep state (or waits for around 1 minute). sshCommand.Result and sshCommand.Error variables are empty.
Here's a quick example - one way to do it.
string host = "myhost";
string user = "root";
string pwd = "#secret#!"; // Don't use hardcoded plain-text passwords if possible - for demonstration only.
using (PasswordAuthenticationMethod auth = new PasswordAuthenticationMethod(user, pwd))
{
ConnectionInfo connection = new ConnectionInfo(host, user, auth);
using (var ssh = new SshClient(connection))
{
ssh.Connect();
SshCommand sshCommand = ssh.RunCommand("pwd");
Console.WriteLine("Command execution result: {0}", sshCommand.Result);
}
}
Note that if you specify an invalid command (e.g. "pwdxxxx"), you won't get an exception, but an error that will be stored in the SshCommand.Error string.
Note also that this uses SSH PasswordAuthentication, which may not be enabled in your SSH config.
Try looking into the documentation of SSH.NET:
SSH.NET at CodePlex
Code sample for executing a command (recommended)
Help file.CHM
Related
I'm using SSH.NET in order to get some informations of an external tape drive. Connecting and executing some basic commands works perfectly fine for me:
ConnectionInfo connNfo = new ConnectionInfo("10.12.2.97", 22, "loginuser",
new AuthenticationMethod[]
{
// Password based Authentication
new PasswordAuthenticationMethod("loginuser","password")
}
);
using (var client = new SshClient(connNfo))
{
client.Connect();
//This command works fine
using (var cmd = client.CreateCommand("ls"))
{
string result = cmd.Execute();
}
}
But now i have to switch to root user in order to execute extended commands i need. Initially logging in with root user is not possible because of security restrictions. Referring to this post How to run commands by sudo and enter password by ssh .net c# i tried this code block:
using (var cmd = ssh.RunCommand("echo 'rootpassword' | sudo -u root -S fsstate"))
{
if (cmd.ExitStatus == 0)
Console.WriteLine(cmd.Result);
else
Console.WriteLine(cmd.Error);
}
But then i always receive this error message:
sudo: unknown user: root
sudo: unable to initialize policy plugin
Update 1:
Working PuTTY commands
What i'm doing wrong here?
I need to execute this action using a C# code:
open putty.exe in the background (this is like a cmd window)
login to a remote host using its IP address
enter a user name and password
execute several commands one after the other.
run another command that gets a response telling me that the commands I ran before that where executed successfully
So I'm trying to do it like this:
ProcessStartInfo proc = new ProcessStartInfo()
{
FileName = #"C:\putty.exe",
UseShellExecute = true, //I think I need to use shell execute ?
RedirectStandardInput = false,
RedirectStandardOutput = false,
Arguments = string.Format("-ssh {0}#{1} 22 -pw {2}", userName, hostIP, password)
... //How do I send commands to be executed here ?
};
Process.Start(proc);
You could try https://github.com/sshnet/SSH.NET.
With this you wouldn't need putty or a window at all.
You can get the responses too.
It would look sth. like this.
SshClient sshclient = new SshClient("172.0.0.1", userName, password);
sshclient.Connect();
SshCommand sc= sshclient .CreateCommand("Your Commands here");
sc.Execute();
string answer = sc.Result;
Edit: Another approach would be to use a shellstream.
Create a ShellStream once like:
ShellStream stream = sshclient.CreateShellStream("customCommand", 80, 24, 800, 600, 1024);
Then you can use a command like this:
public StringBuilder sendCommand(string customCMD)
{
StringBuilder answer;
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
writer.AutoFlush = true;
WriteStream(customCMD, writer, stream);
answer = ReadStream(reader);
return answer;
}
private void WriteStream(string cmd, StreamWriter writer, ShellStream stream)
{
writer.WriteLine(cmd);
while (stream.Length == 0)
{
Thread.Sleep(500);
}
}
private StringBuilder ReadStream(StreamReader reader)
{
StringBuilder result = new StringBuilder();
string line;
while ((line = reader.ReadLine()) != null)
{
result.AppendLine(line);
}
return result;
}
While the answer by #LzyPanda works, using an SSH "shell" channel (SshClient.CreateShellStream), let alone an interactive terminal, is not a good idea for automating commands execution. You get lot of side-effects from that, like command prompts, ANSI sequences, interactive behavior of some commands, etc.
For automation, use an SSH "exec" channel (SshClient.CreateCommand):
using (var command = ssh.CreateCommand("command"))
{
Console.Write(command.Execute());
}
If you need to execute multiple commands, repeat the above code. You can create any number of "exec" channels for one SSH connection.
Though if the commands depend on each other (first command modified the environment, e.g. variables, that are used by the latter commands), you have execute them within one channel. Use a shell syntax for that, like && or ;:
using (var command = ssh.CreateCommand("command1 && command2"))
{
Console.Write(command.Execute());
}
If you need to continuously read the commands output use:
using (var command = ssh.CreateCommand("command"))
{
var asyncExecute = command.BeginExecute();
command.OutputStream.CopyTo(Console.OpenStandardOutput());
command.EndExecute(asyncExecute);
}
You can also use ExtendedOutputStream, which contains stderr. See SSH.NET real-time command output monitoring.
Unfortunately implementation of "exec" channel in SSH.NET does not allow providing an input to the command. For that use case, you will need to resort to the "shell" channel, until this limitation is solved.
For the past month I've been getting data with a C# program in tandem with a company's API. Just yesterday all the sudden it would no longer work, even though I haven't changed the code at all. Here's the code:
public string GetMatchCode()
{
//this could be loaded from config file or other source
string connectString = "Server=123.123.1.23;Database=blah_users;Uid=blah_data;Pwd=blahblah;";
string sql = "SELECT MAX(match_id) FROM `data_blah`";
using (var connect = new MySqlConnection(connectString))
using (var command = new MySqlCommand(sql, connect))
{
connect.Open();
return command.ExecuteScalar().ToString();
}
}
And I get this error:
An unhandled exception of type 'MySql.Data.MySqlClient.MySqlException' occurred in MySql.Data.dll
Additional information: Access denied for user 'blah_data'#'cpe-86-80-21-54.san.res.rr.com' (using password: YES)
Any idea what could have happened and how to fix it? The only thing I think could've happened is that my support ticket dealing with node.js compatibility was executed wrong by support employees. Thanks!
Your db user's permission has failed. The user may have been removed; the permissions may have been modified. Contact the db owner.
So it looks like you are not authenticating: Either incorrect credentials or server needs a different method. Try disabling "sslmode" like below:
public string GetMatchCode()
{
//this could be loaded from config file or other source
string connectString = "Server=123.123.1.23;Database=blah_users;Uid=blah_data;Pwd=blahblah;sslmode=none;";
string sql = "SELECT MAX(match_id) FROM `data_blah`";
using (var connect = new MySqlConnection(connectString))
using (var command = new MySqlCommand(sql, connect))
{
connect.Open();
return command.ExecuteScalar().ToString();
}
}
That should do it
string sql = "SELECT MAX(match_id) FROM `data_blah`";
Isn't it supposed to be " ' " instead of " ` " surrounding "data_blah"?
I want to run a command in command prompt on a remote computer using C#. Per this link How to execute a command in a remote computer?, I am trying to do this using the following code:
public static void RunRemoteCommand(string command, string RemoteMachineName)
{
ManagementScope WMIscope = new ManagementScope(
String.Format("\\\\{0}\\root\\cimv2", RemoteMachineName));
WMIscope.Connect();
ManagementClass WMIprocess = new ManagementClass(
WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
object[] process = { command };
object result = WMIprocess.InvokeMethod("Create", process);
Log.Comment("Creation of process returned: " + result);
}
This returns an exit code of 0 and no errors are thrown, yet nothing is executed. Please help.
Hope this will help
http://www.petri.co.il/command-line-wmi-part-2.htm
Have a look into "Alternate Credentials" section. i believe you are able to do the little modification yourself.
If you are willing to try it out, psexec is great for this sort of thing.
I know the post is old but for others who come across this page and also completeness:
RRUZ's comment is correct , but there is also one more thing you might need in order to run on the remote machine, credentials.
To do that you need to add connection options:
public static void RunRemoteCommand(string command, string RemoteMachineName,
string username,string password)
{
var connection = new ConnectionOptions();
connection.Username = username;
connection.Password = password;
ManagementScope WMIscope = new ManagementScope(
String.Format("\\\\{0}\\root\\cimv2", RemoteMachineName), connection);
WMIscope.Connect();
ManagementClass WMIprocess = new ManagementClass(
WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
object[] process = { command };
object result = WMIprocess.InvokeMethod("Create", process);
Log.Comment("Creation of process returned: " + result);
}
If I run this from my command prompt it works fine.
psexec \ServerName cscript.exe iisapp.vbs /a AppName /r
I'm trying to do the same thing with C# console app. I'm using the below code but most of the time the application hangs and doesn't complete, and the few times it does it throws an error code. Am I doing this wrong? Does anyone know where I can look up the error or error code?
static void RecycleAppPool(string sServer)
{
Console.Clear();
ProcessStartInfo p = new ProcessStartInfo("psexec.exe", "\\\\" + sServer + " cscript.exe iisapp.vbs /a <AppName> /r");
p.RedirectStandardInput = true;
p.UseShellExecute = false;
Process.Start(p);
}
When it completes with an error, looks like this
"cscript.exe exited with error code -2147024664"
EDIT
Below code working well
static void RecycleAppPool(string sServer)
{
Console.Clear();
ProcessStartInfo p = new ProcessStartInfo("psexec.exe");
p.Arguments = #"\\" + sServer + #" cscript.exe iisapp.vbs /a AppName /r";
p.UseShellExecute = false;
Process.Start(p);
}
VS2003/8/10: Tools->Error Lookup. Paste in the error code in hex. 800700E8. It's "The pipe is being closed." Not very helpful - some issue with redirection i guess.
Do you really have in the ProcessStartInfo parameter, or is that being used to replace what your actual app name is?
Have you tried recycling using appcmd instead of iisapp.vbs?
And, in this thread they recycled a remote application pool using WMI.
If it's IIS7 then you can you the web admin namespace from C#:
using System;
using System.Xml.Serialization;
using Microsoft.Web.Administration;
using System.Linq;
using System.Runtime.InteropServices;
///...
var serverManager = ServerManager.OpenRemote(#"\\myiisserver");
var appPool = serverManager.ApplicationPools["my app pool name"];
appPool.Recycle();
You can learn more about the Web Admin Namespace here. So far it has worked very well for us. BUT must be installed on the client and remote machines.
I struggled with this a lot for the last 2 days trying every solution I found online. I'm trying to recycle an application pool on remote machines on a different domain. The first method I tried with PsExec returned error 3. I tried DirectoryEntry and failed on permissions as well and then tried using ServerManager but the same issue.
Finally, I moved to WMI and it worked:
public static void RecycleIis4(string user, string password, string serverName = "LOCALHOST", string appPoolName = "DefaultAppPool")
{
var processToRun = new[] { #"c:\Windows\system32\inetsrv\appcmd recycle APPPOOL " + appPoolName };
var connection = new ConnectionOptions { Username = user, Password = password };
var wmiScope = new ManagementScope(string.Format(#"\\{0}\root\cimv2", serverName), connection);
var wmiProcess = new ManagementClass(wmiScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
wmiProcess.InvokeMethod("Create", processToRun);
}
Hope this helps.