C#0 net use connection - c#

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.

Related

Capturing Plink output in C#

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#

Process.Start() does nothing

I have to start a VPN connection (Fortinet) by code.
I have a cmd file that establish the connection.
If I call the cmd file on the shell it works pretty fine.
When I call it via Process.Start it does nothing.
It doesn't throw any exception, it seems to execute but VPN does not connect.
On the standard output I can read the echo I put on the cmd file (so it is executing the right file).
I launched a ping -d to see when the vpn goes up, when I call it via shell it goes up in a few seconds, via C# it is not.
I also tried a sleep(30000) but nothing.
My cmd (ConnectFile.cmd):
#echo off
#echo Connecting to VPN
"C:\Program Files (x86)\Fortinet\SslvpnClient\FortiSSLVPNclient.exe" connect -s "vpn myvpn"
My code (connectFile and disconnectFile are strings that contain the full path of the cmd files):
try
{
var startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = connectFile;
startInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(connectFile) ?? "";
System.Diagnostics.Process process = System.Diagnostics.Process.Start(startInfo);
System.Threading.Thread.Sleep(30000);
base.GetFiles(folder);
}
finally
{
System.Diagnostics.Process.Start(disconnectFile);
}
You have to separate the parameters. FileName is for the exe file, not the whole shell command (you're explicitly saying not to use the shell). So put the parameters to the Arguments property in ProcessStartInfo.
In your case, the parameters should be:
FileName - C:\Program Files (x86)\Fortinet\SslvpnClient\FortiSSLVPNclient.exe (no quotes)
Arguments - connect -s "vpn myvpn" (again, no quoting)
Second, you have to read the standard output if you capture it. If the output buffer gets full before you read it, the called process will stop working - it has to wait for the buffer to be emptied. If you're sure the application will actually finish at some point, simply remove the Thread.Sleep and call ReadToEnd right away. Otherwise, use eg. asynchronous reading to get the data.
Also, it's usually a good idea to set WorkingDirectory. Even if the application doesn't need any data from the working directory, it's safer, since only admins can change Program Files - this helps against DLL inject hacks.

Break out of a C# instantiated batch script to get a shell?

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.

How to control network client pc

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

Can I stop an IIS?

In a .NET windows application to to modify a remote machine config file that is used by an ASP.NET application. However, I keep getting the error:
System.IO.IOException: The process cannot access the file '[file name]' because it is being used by another process.
Now, this may not be the problem, but I'm figuring that if I can stop the IIS, then I can modify the machine config file (without getting the exception), and then I can restart the IIS using this code:
Process proc = new Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.FileName = "iisreset";
proc.StartInfo.Arguments = serverName;
try
{
proc.Start();
proc.WaitForExit();
...
1) Is there a way to stop the IIS without restarting it, and 2) Doe this approach to changing the server.config file even make sense?
(note, I am modifying the file with regular expressions search and replace; is this a problem?)
You should be able to do something like this. I don't have windows, so I can't check the exact name of the service, but I think it is "IISADMIN" or "w3svc". Remember this should be the service name and not the display name you see in the service control panel.
ServiceController controller = new ServiceController();
controller.MachineName = "."; // or the remote machine name
controller.ServiceName = "IISADMIN"; // or "w3svc"
string status = controller.Status.ToString();
// Stop the service
controller.Stop();
// Start the service
controller.Start();
You can also use
net stop w3svc
or
net stop IISADMIN
from the commandline or in your process in your code
Strange. A .config file should not be locked exclusively.
But to answer your question, you can also use the net command for this:
net stop w3svc
to stop the www service, and
net start w3svc
to start it again.
You can also do this programmatically as described by #monkeyp
Note that I would advice against this and first try to determine (and resolve) the cause of the lock as described by #RichardOD.
Using System.Diagnostics;
//to stop ISS
ProcessStartInfo startInfo = new ProcessStartInfo("iisreset.exe", " /stop");
System.Diagnostics.Process.Start(startInfo);
//to start ISS
ProcessStartInfo stopInfo = new ProcessStartInfo("iisreset.exe", " /start");
System.Diagnostics.Process.Start(stopInfo);
You can use the IISRESET /STOP command.
If you type IISRESET /? you will get a list of other available options.
[Edit: Pass the "/STOP" switch as the arguments property on the process' startinfo object.]
Should be "iisreset /STOP" to stop the services, then "iisreset /START" to restart them.
Use a tool like wholockme or unlocker to find the root cause of the locking.
Update- another option is to use Process Explorer (thanks fretje)- this is a good option as lots of developers have this utility on their PC.
You can often just recycle or stop/start the Application Pool IIS is running, rather than restarting IIS altogether.

Categories

Resources