Run a DOS command in .NET - c#

I have a set of commands like:
C:
cd Project
testproj.exe
My system gets these commands one by one from a remote system.
I need to execute each command in cmd.exe on receiving the command from the remote system. How to execute these using .NET?
I also need to return the result of testproj.exe to the remote machine. How to take the result after running command?

Process.Start cmd.exe, and hook StandardIn, StandardOut, and StandardError. Then, when a command comes in, just write it to StandardIn and read StandardOut/Error for the return. The whole thing shouldn't be more than 15 LOC.
That being said, just installing the Telnet Server would probably be easier - as it sounds like that's what you're essentially replicating....

var process = System.Diagnostics.Process.Start( "testproj.exe" );
process.WaitForExit();
var result = process.ExitCode;
This won't really honor things like "C:" or "CD path". Instead you'd want to create a batch file in a temporary folder then call the batch file.

Take a look at System.Diagnostics.Process. You can redirect stdout/stderr somewhere to get the output.

The C: and cd Project operations can be done inside the lanching application using the Directory class using the SetCurrentDirectory method.
Then just use the Process class to launch the testproj.exe executable.

Instead of trying to support all the commands of DOS, just have a small subset implemented which will guarantee nothing can go wrong. Like Don't allow DELETE, RD, FORMAT etc.
So, basically you would only have a subset of DOS commands. Once you have the command set, you can code for those specific commands using a extension mechanisms or as pluggable modules.
This will also helps you safe guard your machine from malicious attacks and worst to happen is there could be data sent out but from machine, the data / system can never be harmed.
UPDATE: The implementaion of specific commands is left to you. You could use .NET API or have System.Diagnostics.Process

Related

How to copy efficiently UNC paths in the same remote machine

I'm working on an efficient solution to copy big files in the same remote machine, let's call it FILESERVER. Then, from another server (WEBSERVER) I want to issue copies of these files remotely, so I tried to copy/paste files in the same remote shared folder with Windows Explorer and I noticed it doesn't need to move the file contents through the network, so I thought using shared folders and simply copying files from WEBSERVER could make it.
So, I gave it a try with the following code.
File.Copy("\\FILESERVER\FOLDER\bigfile", "\\FILESERVER\FOLDER2\bigfile");
This works, but I noticed that it is actually moving the file contents through the network and that's exactly what I wanted to avoid. I don't want to have to implement a server in FILESERVER to receive commands to copy files if I can do it with a built-in Windows mechanism. So the behaviour I would like to implement is the same Explorer does, invoking it from my c# code. So, is possible to do this in .NET?
EDIT:
I tried XCOPY command and at first seemed it didn't use the network.
But after some reboots to ensure it wasn't any OS caching involved, I noticed that when I execute XCOPY from cmd it doesn't show any I/O in Process Explorer/taskmgr, but, when I execute this command from my C# code it does. So I think it does use the network to fetch/write the file contents but for a weird reason it's not reported in these diagnostics tools (taskmgr / Process Explorer).
use PSEXEC and run the copy with local folder paths on the remote machine.
Definitely WMI is a good way to do it. I finally managed to do it with the following code and the CopyEx method to copy directories recursively.
var classInstance = new ManagementObject("\\\\FILESERVER\\root\\cimv2", "Win32_Directory.Name='c:\\path\\to\\directory1'", null);
var copyExInParams = classInstance.GetMethodParameters("CopyEx");
// Add the input parameters.
copyExInParams["FileName"] = "c:\\path\\to\\directory2";
copyExInParams["Recursive"] = true;
copyExInParams["StartFileName"] = null;
var copyExOutParams = classInstance.InvokeMethod("CopyEx", copyExInParams, null);
It's important to notice that paths must be in the remote machine format. I can't prove it but maybe Windows Explorer is taking advantage of WMI to copy files in the same remote machine in shared folders to prevent useless network traffic. I haven't found a way to do it directly with UNC. Even though this suits my use case.

How to call "Action Result" ASP.NET MVC at specific time (Daily)

I have a system for sending E-mails to users by a specific time .
built in ASP.NET MVC4 and has an action result "function" for checking the time of messages and send it if the day of the message is today .
how can I call this action result (daily) -like a scheduler- in efficient way ?
Thanks.
Whilst a separate service / application would be better, you could use wget.
GNU Wget is a free software package for retrieving files using HTTP,
HTTPS and FTP, the most widely-used Internet protocols. It is a
non-interactive commandline tool, so it may easily be called from
scripts, cron jobs, terminals without X-Windows support, etc.
You would then do something like:
"C:\Program Files (x86)\GnuWin32\bin\wget.exe" --no-check-certificate https://www.exammple.com/YouController/YourAction -O NUL
in a .bat file and set that to run via a windows Scheduled task at the time you require (assuming you don't need to run it less than every 60 seconds - if you do, let me know as I have another way around this using a windows service to call the bat file instead).
Omitting the -O NUL part would also save the output so you could see if everything ran successfully by doing:
public ActionResult YourAction()
{
//Do your code, get some stats that show it ran properly.
return Content("Return your stats here.");
}
from your controller action.
More efficient will be when you create new application as Windows Service. There u can easy set code to start at specific time. in this solution you will have more flexibility and independent. You can start hire : Windows Service to run a function at specified time
You could create a small console application that just calls the API do send out the emails. You can then schedule the console app to run at a specific time using the Windows Scheduler; you can even have it run without showing the console window. See here or here for details on how to schedule a task.
Use Azure Functions, that's exactly what it was built for. It's really good.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview

Start Node.js server from a C# Application

A requirement has arisen that I need to start a Node.js server from a C# application, this is as simple as running a server.js script within the Node.js console. However, I'm not entirely certain how exactly to achieve that.
Here's what I've looked into so far:
In the Node.js installation, there's a file called C:\Program Files (x86)\nodejs\nodevars.bat, this is the command prompt window for Node.js. To start the server, I could possibly be using the following steps:
Execute the nodevars.bat file.
SendKeys to the new process console window to start the server.
This approach feels a bit fragile. There's no guarantee that the target user will have their Node.js installation in the same place, also sending keys to a process may not be an ideal solution.
Another method could be:
Write a batch file that executes nodevars.bat.
Execute the batch file from the C# application.
This seems like a better approach. However, the only problem here is that the nodevars.bat opens in a new console window.
So to the question(s), is there a way I can start a node.js server script using functionality built into the node.js installation? Perhaps sending arguments to the node.exe?
If it is to serve multiple users, i.e. as a server, then you can use the os-service package, and install a Windows service. You can then start and stop the service using the standard API.
If you are to start the server as a "single purpose" server, i.e. to serve only the current user, then os-service is the wrong approach. (Typically when using this approach you will specify a unique port for the service to use, which will only be used by your application).
To start a batch file or other Console application, from C#, without showing a console window, use the standard method, but be sure to specify:
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false; // This is important
psi.CreateNoWindow = true; // This is what hides the command window.
psi.FileName = #"c:\Path\to\your\batchfile.cmd";
psi.Arguments = #"-any -arguments -go Here"; // Probably you will pass the port number here
using(var process = Process.Start(psi)){
// Do something with process if you want.
}
There are a few different ones but I recommend the os-service package.

Automating IISRESET via remote desktop connection after a TFS build

I want to automate a process, which is invoked after a successful build on TFS. The process will RDP to a test server, then call a C# application on that server, and reset IIS on that server. Each step will return the result so whether or not to call next step is based on the previous step.
There are a few obstacles in implementing it. Below is what I want to know if it is possible, and how to code it.
1) Invoking the process via a build on TFS
There is an option in Build definition to invoke automated test. I assume that the process can be invoked by implementing it as a test.
2) RDP to remote server
I found the links below, which might be a solution
Process rdcProcess = new Process();
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\cmdkey.exe");
rdcProcess.StartInfo.Arguments = "/generic:TERMSRV/192.168.0.217 /user:" + "username" + " /pass:" + "password";
rdcProcess.Start();
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\mstsc.exe");
rdcProcess.StartInfo.Arguments = "/v " + "192.168.0.217"; // ip or name of computer to connect
rdcProcess.Start();
Run mstsc.exe with specified username and password
Automating remote desktop connection
3) IISReset
I think it should be simply invoke "IISRESET" after RDP, but the problem is that, HOW to captrue the result of running IISRESET.
The tools that might be suitable are:
1) Powershell - I don't know much about Powershell but am willing to learn if required
2) C#
My question is that how to implement it, any code example, and idea would be very much appreciated.
Check my answer here which is somewhat related: Answer
If the user which runs the TFSBuild Service on the build server have enough rights on the test server then you can use psexec or powershell to run your commands remotely. Read the below links:
PSEXEC
PowerShell Remote commands
There is no inbuilt activity/process which can help you run scripts on remote machines in TFS build workflow.
Step 1 for you is to identify how you are going to run scripts on the remote machine, as mentioned above you can either use PSEXEC or Powershell (though running PowerShell on remote computers may be a little more complicated to set up).
Step2, write the actual scripts to do the work, stop services, install MSI etc.
Step3, Edit your current build defintion - create a new custom activity or make use of InvokeProcess activity from within your build definition to invoke the script that you have created in Step 2. InvokeProcess Activity
in most cases you do not need to run iisreset
if you want to upgrade an asp.net application, try to put app_offline.htm in the application folder, it will stop an application and application files will be unlocked
after upgrading an application, it will restart automatically, or you can "touch" web.config to force restart
You might be better using the Lab Build to run the scripts as part of an environment ob the target computer. It can run any powershell against that machine as well as deploy and execute applications....
Question: HOW to capture the result of running IISRESET
I believe the old fashioned way, Hope this is what you are looking for
c:> IISRESET >> C:\temp.log
You can use the above either from CMD or powershell
In the past I have used Psexec to run commands against a remote server and where ever we need to control flow on the result of that command, we simply piped the console out to a shared folder and checked for our success flag.
I am not sure if TFS can run commands in this manner but we implemented it on hudson/jenkins.
This won't answer your question directly but it may offer a better way forward
An Example:
psexec.exe \remoteserver "iisreset > h:\iisreset.log"
Then run a grep or similar against the iisreset.log with your success flag as a condition to run the next step.

Best way to run a tool from ASP.Net page

I have a developer tool that I want to run from an internal site. It scans source code of a project and stores the information in a DB. I want user to be able to go to the site, chose their project, and hit run.
I don't want the code to be uploaded to the site because the projects can be large. I want to be able to run my assembly locally on their machine. Is there an easy way to do this?
EDIT: I should note, for the time being, this needs to be accomplished in VS2005.
EDIT 2: I am looking for similar functionality to TrendMicro's Housecall. I want the scan to run locally, but the result to be displayed in the web page
You could use a ClickOnce project (winform/wpf) - essentially a regular client app, deployed via a web-server. At the client, it can do whatever it needs. VS2005/VS2008 have this (for winform/wpf) as "Publish" - and results in a ".application" file that is recognised by the browser (or at least, some browsers ;-p).
You might be able to do the same with Silverlight, but that has a stricter sandbox, etc. It would also need to ask the web-server to do all the db work on its behalf.
I want to be able to run my assembly
locally on their machine
Sounds like you want them to download the tool and run it from their local machine, does that work for you?
Any code can scan files given the location and permissions. For a website to open an exe on a different machine and permit that to run and get access to the files contained on the web server would require a horrifically low level of security that would mean the entire system is practically completely open to attack. If your system is completely behind a firewall and hence protected from outside intererance then you want to look more at the permissions and less at the code.
To run an exe on a machine try following notepad example, though you may have to use a specified directory as well
ProcessStartInfo psi = new ProcessStartInfo("notepad.exe");
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(ExitHandlerToKillProcess);
p.StartInfo = psi;
p.Start();
and when done dont forget to kill the Process. Alternately use javascript. Either way watch the security permissions and remember the risks of doing this.
I would probably write some sort of command line tool or service that does the processing and extraction of project data. Then I would use a page to update/register projects that the web server and the command line tool both have common access to. then at specified times either manually or via cron or similar mechanisms extract the data to your database. once you have this, you just use the website to display last extraction times and the extracted data.
if the projects/end users are on a different subnet etc, then you will need the end users to run the tool and then have it post the data into the database.

Categories

Resources