I am trying to use Plink to access information on a machine. I followed this tutorial:
http://www.mindfiresolutions.com/Creating-a-SSH-connection-using-plink-PuTTY-via-C-application-1760.ph
So far I am only using my program to just open up Plink, and I will be adding in the login information and such once I can at least get Plink to be openable in my program. I have this based on the tutorial:
ProcessStartInfo psi = new ProcessStartInfo(#"C:\Windows\System32\cmd");
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
psi.UseShellExecute = false;
psi.CreateNoWindow = false;
Process process = Process.Start(psi);
Thread.Sleep(3000);
string cmdForTunnel = "plink";
process.StandardInput.WriteLine(cmdForTunnel);
process.WaitForExit();
Thread.Sleep(10000);
//DoBusinessLogic();
process.StandardInput.WriteLine("logout");
Thread.Sleep(10000);
if (process.HasExited)
{
process.Close();
process.Dispose();
}
But nothing is displayed, which bothers me. The command plink is supposed to display the help information on how to use the program (I will be replacing the command with something more useful later), but the command prompt remains empty. I also experimented by replacing plink with ipconfig, which also displayed nothing.
I know how to open up cmd myself and type in plink to access it. I want to replicate this action in my program.
You have many faults in your code:
You are redirecting an output, and you are not reading/processing/printing it (that's why "nothing is displayed")
Running plink by "typing" plink to cmd.exe is insane. You can run plink directly, avoiding cmd.exe completely (and even if you needed to use the cmd.exe, you should pass plink.exe to it on a command-line: /c path\plink.exe). And no, running it directly would not cause Plink to close instantly.
Calling WaitForExit() without reading the redirected output will deadlock your code once an output buffer fills. See Remarks section for ProcessStartInfo.RedirectStandardOutput. Alternatively, use process.StandardOutput.ReadToEnd() (it's like WaitForExit, but also reads the output). It's actually what the MSDN recommends in the previous link.
If you are going to execute one command only, using Plink, it's also better to pass the command on Plink command-line, rather than "typing" it to its (redirected) input:
plink.exe -ssh user#host command
See also answer to Testing using Plink.exe to connect to SSH in C#
Related
So I am having issues with the "net use" command in C#. Basically, I am using the code written here. The code works great, however I have multiple ids that need to be used sequentially. Unfortunately, when trying to connect to another ID, the connection remains in "net use " in Windows, so this exception is thrown:
Win32Exception: Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed.
Now to me, the obvious thing would be to execute the command prompt programmatically to delete the connection when I am done using it. Here is the code that I am running to delete the connection:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/K net use delete \\IPAddrofserver";
process.StartInfo = startInfo;
process.Start();
I only use /k so I can see if the command works. After this code executes, it says "The network connection cannot be found." However, if I manually open the start menu, and type net use, I can see and delete the connection. I think this may be related to the fact that when running the command prompt programmatically, I notice its being given administrative privilege as opposed to running it under my user token, but I cannot be sure. Any help regarding this would be greatly appreciated.
EDIT: Adding in the command prompt deletion code during the WnetCancelConnection2 actually operates correctly, and deletes the connection from net use. However, checking net use manually outside of the program reveals that the history of the connection still exists and is open. Whoami command reveals the same user. Any reason why there is a discrepancy between what happens programmatically and what happens when I check manually?
You probably need to start your process with elevated privileges. See the accepted answer here for how to do this. You could also choose to call the relevant Windows API directly, to avoid spawning other processes and dealing with those complications.
I am attempting to verify the security of an application. The scenario is this:
A C# WinForms application is run by a limited user via Terminal Services (no desktop, just the app). One of the things this C# app can do is execute a batch file that runs a lengthy process with elevated privileges. I am afraid that the limited user may be able to interrupt the batch script (vua Ctrl+C or some other method) and gain access to the underlying elevated shell.
I have tried to do this myself with various combos of Ctrl+C and Ctrl+Break, etc. All I can get is the "Teminate batch job? (Y/N)" prompt, and if you choose terminate, then control is immediately returned to the C# app (which is good). I have not found a way to break this but it seems dangerous to me.
Does anyone know of a way to break out of a C# instantiated batch script and access the underlying shell without returning to the C# app?
No, don't think there is one. But if you're really worried, why not set the CreateNoWindow property on the ProcessStartInfo object you are presumably using to true to prevent user interaction at all?
Not quite an answer to your described scenario but a different way to look at it.
If possible, I would have a "jobs server" who sole responsibility is to run the jobs your Terminal Services-run apps create. Then you would communicate the job (or just it parameters) via WCF to the server. The users would have no access to the server and very little control of the jobs (possibly just a cancel option and success/failure status reports).
You could do something like this (with a Textbox on your app)
ProcessStartInfo info = new ProcessStartInfo();
info.Arguments = "/C ping 127.0.0.1";
info.WindowStyle = ProcessWindowStyle.Hidden;
info.CreateNoWindow = true;
info.FileName = "cmd.exe";
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
using (Process process = Process.Start(info))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
textBox1.Text += result;
}
}
Then you can see the results of the batch without the users being able to actually see the window at all, that way it's only visible as a process so they can't interupt it.
I have a custom console command, which if executed in command prompt just displays some text in the command window (similar to 'dir' command).
I'm trying to execute the command 'myCommand' from a windows service and it is always returning blank string values. However, if run the same command in a command prompt, the result is displayed in the command window. Also, if I run the below code in a windows forms application, it works fine and I get the same data which is displayed in the command screen to a string variable.
Where am I going wrong? Why is the code returning a blank string when I execute it from a windows service, where as it works in a forms application. Is there any other method to capture the result of a command to a string variable in a windows service? Please advise. Thank you.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c myCommand");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
Attach the Visual Studio debugger to your running service (Debug menu, Attach to Process), put a breakpoint in the code where you execute the the command, and then execute the comand. This will enable you to debug the problem. If necessary, you can call the System.Diagnostics.Debugger.Break method in your service to force it to break into the debugger at the appropriate point, without having to attach the debugger first.
Edit:
I suggest you also capture the standard error stream:
procStartInfo.RedirectStandardError = true;
...
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
Check what you get in the error string. I use WaitForExit to wait until the command exits too.
You are not setting the working Directory (ie procStartInfo.WorkingDirectory), so if the system can not find 'myCommand' , you will get this result.
Even if 'myCommand' is in the same directory as your service exe file, that does not normally work as the working directory for a service is normally windows\system32.
I preferred this Easier way to debug a C# Windows Service
I added the conditional If to launch the debugger from the OnStart method, then put a breakpoint in my OnCustomCommand(int command) method.
In my current project, i need to call a Unix shell script from the C# application. I also need to get the response back whether the script has been execute successfully or any error has occurred.
The C# program is running on a Windows machine. I need to connect to a Unix machine and execute the script.
Can anyone let me know how this can be done using C#?
Will this solve your problem?
sharpSsh - A Secure Shell (SSH) library for .NET
Update
Refer to the developer's site for SharpSSH for more information on how to use the tool.
Update 2
change link of developer site to archived link.
A straight forward way of preforming this using System.Diagnostics.Process
// Start the child process.
Process p = new Process();
// Redirect the error stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected error stream.
// p.WaitForExit();
// Read the error stream first and then wait.
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
Even i had the same problem, i have googled for solution for around 1 month.
Finally, i have decided to use plink.exe (command line version of putty.exe) to connect to unix box and execute a script there.
You have to use plink through c# process, i have tried it and this works amazingly.
But rite now the problem i am facing is when i am running a script from c# process i am unable to pass arguments to that script. Probably it would be rite to say that i do not know how to do that.
Regards
-Aakash
In my local network ,I have more than 10 pc.I need to take care all of the pc.I want to know all pc’s hardware informations.I also want to control those pc,Suppose ,at this moment I want to restart one of my client pc.Is it possible in C#.if have any question plz ask.Thanks in advance
I use bellow syntax to execute command.
try
{
// create the ProcessStartInfo using "cmd" as the program to be run,
// and "/c " as the parameters.
// Incidentally, /c tells cmd that we want it to execute the command that follows,
// and then exit.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + "shutdown /r /m \\172.16.1.3 /t 1 /");
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
Console.WriteLine(result);
}
catch (Exception objException)
{
// Log the exception
}
Using the above code I get the message "The network path was not found."
Pls check the url.
http://support.microsoft.com/kb/317371
If you want to make a program which u can able to get the remote system information. You have to use Microsoft's Remoting.Here we can able to create an object in the remote system and we can able to control it.
It is possible to get System's information by executing the System.Diagnostics.ProcessStartInfo.
It is possible to get system information using "systeminfo" .It is possible to take the output using C#
Pls chk the this.
I hope this will be useful for you.
I don't think this is a C# question, cause this can be done much more elegant with things like Group Policy Editor, System Management Server, System Center Operations Manager, etc.
To do some simple tasks on a remote machine you can take a look into the PsTools.
With those requirements my first stop would be WMI. There's for example the Win32_OperatingSystem class with its Reboot and Shutdown methods and the Win32_Processor with all kinds of information about the CPU.
This MSDN section shows you how to use it from .Net: Getting Started Accessing WMI Data
This MSDN section has quite a lot of short VBScript samples for doing various things using WMI, and even if the code is different, at least you can see which WMI classes/methods/properties you should be looking at: WMI Tasks for Scripts and Applications
Please note RB's comment though, you'll need to have the correct permissions for it to work.
Edit: Forgot that since you'll want to connect to other computers, this sample will be useful: How To: Connect to a Remote Computer