Talking to Cisco Routers, Switches, Firewalls with Renci.SshNet

I went through a LOT of libraries and packages, each claiming to be the bee’s knees when it came to communicating via SSH. I eventually landed on Renci.SshNet because:

1. It is current.

2. It has extreme flexibility for SCP, keys, sessions, you name it.

3. I could get my hands on the source and compile it in Visual Studio successfully.

4. It did not rely on 3rd party libraries. That is, the code only imported System libraries.

5. I could compile to a DLL, then reference it from several of my projects in my VS solutions.

6. It was the one other libraries imported, or tried unsuccessfully to emulate.

[Note: You will find the source well marked up, but very few working examples available. You will find lots of code that folks have posted that didn’t work, which is why I am writing this article]

The problems started when I wanted to just find an example, and go for it. All the examples were VERY simple “log in, do one command, log out”.

OK. Enough background. Lets get right to it.

My solution (evolving, but as of the time of this writing) involves the creation of 4 worker functions, differing only in how they treat the end of the text (string) sent to the remote device via SSH. This makes much more sense if you see the 4 functions (only 3 of which I have found use for, but they are there if needed for other devices/debugging/etc.):

They are not flashy, or even efficient, but they are great for this early stage of getting things right. And after 2 weeks of a few hours/day banging my head against a wall, I thought it might be important to someone else-important enough to write about.

Now calling any of these functions involved sending a command (the part you’d enter in the SSH terminal if you were typing), and the SshShellStream (using the function scoped variable s). The function returns all the text/string given BACK to the software by the device after the command is processed. I say it in italics, as anyone familiar with Cisco devices knows that the use of the question mark (“?”) to get results can be done without having to press the “Enter” key.

So with those seemingly insignificant disclaimers/qualifiers out of the way, here is the stand-alone sub that will use these functions constructively:

Really kind of easy to follow. The output (mercifully truncated) on Debug Output in Visual Studio looks like this:

So as you can see, by taking hints from previous posters, and reading a lot of the source code, this seems to keep each command separate, returning only the string that has to do with the most recently returned string.

So lets do something practical with all of this. In order for me to be able to control this ASA (in this case), I want to create a List(of String) of all the interfaces. The easiest way to do this is to enter the command “show interfaces ?”, which displays a tidy summary like this:

Just like we did in command #6 above in the test/sample/example subroutine. But this is hardly in a programmatically convenient format if we wanted to verify a good interface was given to the program, or as would be needed if we wanted to do something to each interface-not needing to know them ahead of time, from config [file], etc.

Using the above, here is how I accomplished this. Firstly, I modified my test module & subroutine to look like this:



So it was just a matter of writing a GetInterfaceNames() function that uses the existing ShellStream:

Note the use of function SendCommandW, as like we said earlier, the “?”, once entered, will immediately process on Cisco IOS without hitting Return/Enter. So what does the output look like? Pretty good, actually:

So there you have it. Let me know if you have improvements on this code, or if this gets you out of the rut I was in, and back to writing business logic instead of shaving the yak.


…another example, using the SendCommand* functions above:

There is always more (and usually a LOT more) than one way to do it… :)


  1. I am connecting to a Cisco 3750 switch. how to I process a command that returns more results than the screen displays and shows “–more–“


    1. Dino, I usually issue the command “terminal length 0” when I don’t want those to appear. Then issue the command you were getting the page breaks with.


  2. This helped me a lot. But I’m unable to get past “press any key to continue..” phase when using show arp switch command. Any ideas? (I realize expecting a reply from this old of an article is a longshot).

    Simpy submitting an empty returns no results.


  3. This method is work for me.

    My question is how long to make the sleep time.

    Thread.Sleep(50) // if sleep time too short, some result will cut off

    ThreadSleep(2000) // if sleep time too long, will take a long time in multiple command job


Leave a Reply

Your email address will not be published. Required fields are marked *