views:

336

answers:

6

Note that this has to be on a windows box as I am using c# to access information about windows

(I need information from both a windows box and a linux box, plus I think that making a program/script that runs without gui and accesses windows from a linux box without user intervention would be more difficult, if this is not true please tell me, I would love to do get this running on *nix with only the part that access windows info running on windows).

There is a nice c# api to get this information from windows, on *nix its simple enough to run a command and parse the output to my needs.

There doesn't seem to much decent advice about using ssh from c# out there, sharpSSH and Granados seem to have not been updated for years, are they decent? should I be possible worried about security issues?

(the info I'm retrieving isn't sensitive but if the ssh implementation might have unpatched security flaws(if they haven't been updated for years) I'm worried about someone stealing my credentials.

Are there any other decent c# ssh libraries. If the command output is simple should I just run plink/putty(is it difficult to run a windows cmd shell for plink, and capture output(and is there a way to do it without the shell popping up)?

P.S. while the commercial library seems nice I prefer something free (as in cost and free in source if possible).

+1  A: 

If you're not averse to interop with C libs, I believe OpenSSH is one of the best libraries available for the job.

Jani Hartikainen
A: 

I used SharpSSH in the past to execute commands on a Linux box. There are quite a few bugs, and I had to modify the code to fix some of them, but eventually it kinda worked...

Thomas Levesque
"eventually" and "kinda" don't inspire much confidence :)
Joel Etherton
+6  A: 

Sample Code

There are several commercial SSH client libraries for C#. Following code shows how to connect to a *nix box, run a command and read the response using our Rebex SSH Shell.

// create client, connect and log in  
Ssh client = new Ssh();
client.Connect(hostname);
client.Login(username, password);

// run the 'uname' command to retrieve OS info 
string systemName = client.RunCommand("uname -a");
// display the output 
Console.WriteLine("OS info: {0}", systemName);

client.Disconnect();

For advanced scenarios (such as interactive commands) see SSH Shell Tutorial.

References & Stability

You might be already using Rebex SSH core library without knowing about it. The Rebex SFTP (which uses this SSH lib as a transport layer) is used by Microsoft in several products including Expression Web and Visual Studio 2010. The Rebex SSH Shell is 'just' another layer on top of it (most notable addition is a terminal emulator).

You can download a trial from http://www.rebex.net/ssh-shell.net/download.aspx. Support forum uses engine very similar to this site and runs on http://forum.rebex.net/

Disclaimer: I am involved in development of Rebex SSH

Martin Vobr
+1  A: 

It is quite easy to call plink without the shell popping up.

The trick to not show a window is to set ProcessStartInfo.CreateNoWindow = true.
Add some error handling to this and you're done.

--- PlinkWrapper.cs ---

using System.Collections.Generic;
using System.Diagnostics;

namespace Stackoverflow_Test
{
    public class PlinkWrapper
    {
        private string host { get; set; }
        /// <summary>
        /// Initializes the <see cref="PlinkWrapper"/>
        /// Assumes the key for the user is already loaded in PageAnt.
        /// </summary>
        /// <param name="host">The host, on format user@host</param>
        public PlinkWrapper(string host)
        {
            this.host = host;
        }

        /// <summary>
        /// Runs a command and returns the output lines in a List&lt;string&gt;.
        /// </summary>
        /// <param name="command">The command to execute</param>
        /// <returns></returns>
        public List<string> RunCommand(string command)
        {
            List<string> result = new List<string>();

            ProcessStartInfo startInfo = new ProcessStartInfo("plink.exe");
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.CreateNoWindow = true;
            startInfo.Arguments = host + " " + command;
            using (Process p = new Process())
            {
                p.StartInfo = startInfo;
                p.Start();
                while (p.StandardOutput.Peek() >= 0)
                {
                    result.Add(p.StandardOutput.ReadLine());
                }
                p.WaitForExit();
            }

            return result;
        }
    }
}

--- END PlinkWrapper.cs ---

Call it like

PlinkWrapper plink = new PlinkWrapper("albin@mazarin");
foreach (var str in plink.RunCommand("pwd"))
    Console.WriteLine("> " + str);

and the output will be like

> /home/albin

The nice thing with plink is that it is well proven and integrates well with pageant.

Albin Sunnanbo
+2  A: 

I used SharpSsh lib to make an asynchronous directory sync program between linux and windows boxes (i choosed sftp for secure file tranfer). Remained unchanged for years doesn't mean it is unsecure.

it is really easy to use:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tamir.SharpSsh;

namespace sftpex
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                SshExec exec = new SshExec(ipAddress, username, password);
                Console.Write("Connecting...");
                exec.Connect();
                Console.WriteLine("OK");
                if (exec.Connected)
                    Console.WriteLine(exec.Cipher);

                while (true)
                {
                    Console.Write("Enter a command to execute ['Enter' to cancel]: ");
                    string command = Console.ReadLine();
                    if (command == "") break;
                    string output = exec.RunCommand(command);
                    string[] m = output.Split('\n');
                    for(int i=0; i<m.Length; i++)
                        Console.WriteLine(m[i]);
                }
                Console.Write("Disconnecting...");
                exec.Close();
                Console.WriteLine("OK");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
Onatm
A: 

There is a commercial software IP*Works SSH which can do the job.

PerlDev