how to publish website using cmd - c#

is it possible to replicate this using cmd in c#

Yes, if you're just talking about pushing content up to a site, I'm working on such a beast now.
My proof-of-concept used a Process object to simply run a cmd.exe script that used FTP:
using System.Diagnostics;
:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "myUpload.cmd";
p.Start();
p.WaitForExit();
The program published the web site (it wasn't an actual web site but similar enough that the same method can be used) locally and used the browser to open the file (this was static content only so no need for a web server).
Then, once validated by the user, it simply created a script file temp.ftp containing all the relevant commands and used ftp -s:temp.ftp -n test.com within myUpload.cmd to do the file transfer. The -s specifies the script to run and the -n stops automatic login. That's so you can dynamically create a user command in your script to log in.
The final version will actually probably run Python code so I don't have to fight the brain-deadedness of cmd.exe but the theory is the same.

Related

Process on ASP.Net server not running correctly over IIS

I am trying to run an antivirus scan on an uploaded file in an ASP.Net web app. We are using Sophos so have access to their command line API sav32cli. In the code I use:
Process proc = new Process();
proc.StartInfo.FileName = #"C:\Program Files (x86)\Sophos\Sophos Anti-Virus\sav32cli.exe";
proc.StartInfo.Arguments = #"-remove -nc " + SavedFile;
proc.StartInfo.Verb = "runas";
proc.Start();
proc.WaitForExit();
int exitCode = proc.ExitCode;
When stepping through the code, when attached to the w3wp process on dev server, the code just jumps from one line to the next seemingly doing nothing at all. When running from code on dev server, it performs as expected scanning file and deleting if it is seen as a virus.
The server is running IIS 8.0, and the app built in .Net Framework 4. I have changed the machine config to allow the process to run as SYSTEM account, in accordance to these instructions. https://support.microsoft.com/en-us/kb/317012#%2Fen-us%2Fkb%2F317012
<processModel userName="SYSTEM" password="AutoGenerate" />
Is there something I'm missing? What is the best practice for this kind of implementation?
EDIT: When called, the Process returns an ExitCode of 2 (Error stopped execution), rather than the expected 0 (Scan worked, no viruses), or 3 (Scan worked, viruses found).
EDIT 2: As per comment below I changed the code to:
Process proc = new Process();
proc.StartInfo.FileName = #"C:\Program Files (x86)\Sophos\Sophos Anti-Virus\sav32cli.exe";
proc.StartInfo.Arguments = #"-remove -nc " + SavedFile;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
StringBuilder output = new StringBuilder();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
output.AppendLine(line);
}
proc.WaitForExit();
int exitCode = proc.ExitCode;
ASPxMemo2.Text = exitCode.ToString() + Environment.NewLine + output.ToString();
output is always empty when run over IIS, but is populated correctly when running from code.
EDIT 3: Instead of looking at StandardOutput we looked at StandardError and it revealed this error:
Error initialising detection engine [0xa0040200]
(Possible insufficient user Admin rights.)
For the time being we are going to move to another method of virus checking, but would still like to know a possible solution if anyone has it.
You will need to make sure that the application pool that is running your .NET application inside IIS has execute permissions to your file
"C:\Program Files (x86)\Sophos\Sophos Anti-Virus\sav32cli.exe"
You may also need to add this permission to the folder location where the file to be scanned is uploaded (c:\temp) for example
You may also need to have administrator privileges to run the anti virus scan since IIS8 does not run as an administrator. When you are debugging visual studio uses your current logged in windows user(unless you use runas) so this will explain why it would work when debugging.
Have you tried running your web process in elevated trust?
Configuring .NET Trust Levels in IIS 7
<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal"/>
</securityPolicy>
</system.web>
ASP.NET Trust Levels and Policy Files
Most likely the permissions are not configured correctly on the content being scanned (the uploads folder) or the worker process user doesn't have the full permissions it needs to use Sophos. You know the executable itself is accessible by the worker process because you are getting exit codes and error messages that are specific to Sophos.
Because your process will delete files that are perceived as threats you need to grant the user running the process modify or full control permissions on the folders that store the uploaded files.
By default you could use the IIS_IUSRS group for ApplicationPoolIdentity processes, but you can verify (and modify) the user in IIS Manager > App Pools > Advanced.
This answer has more details
Here are some ideas:
Create the process using a different user with elevated privileges on the folder, see for reference start-a-net-process-as-a-different-user
If the previous suggestion fails, login one time on the server using the credentials used in point 1. It will configure registry entries connected to the user profile, some programs requires it.
Develop a simple .net service running on the server and monitoring the upload folder. The service has more probability running the Sophos scan succesfully. Here is a reference on service creation using .net.
The service may also talk to your web page using DB/file system/ etc.. so the operation may seem synchronous.
These are my 4 cents :-)

Starting a process

As part of SharePoint automation testing, I am trying to open Internet Explorer as another user by using the System.Diagnostics.Process . Here is the following C# code
System.Diagnostics.Process p = new System.Diagnostics.Process();
// Domain and User Name:
p.StartInfo.Domain = "MYDOMAIN";
p.StartInfo.UserName = "myusername";
// Command to execute and arguments:
p.StartInfo.FileName = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
p.StartInfo.Arguments = "http://url/AllItems.aspx";
// Build the SecureString password...
System.String rawPassword = "thepassword";
System.Security.SecureString encPassword = new System.Security.SecureString();
foreach (System.Char c in rawPassword)
{
encPassword.AppendChar(c);
}
p.StartInfo.Password = encPassword;
// The UseShellExecute flag must be turned off in order to supply a password:
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = false;
p.Start();
When I run this automated test Visual Studio returns informing me that the test was successful, however Internet Explorer does not open.
Is there something in my code I am missing in order for a window to appear? There is no iexplore process running prior to the test being run.
putting double quotes around the file path (since it contains spaces) may help:
p.StartInfo.FileName = "\"C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe\""
^^ ^^
In addition, if your intention is to start this from a service process or dll running in a service such as "SharePoint", then this code will probably not launch the process in the desktop desired. You'll need to set the desktop to "winsta0\\default" in the startup info.
To run a process the worker process should have high privileges and this is not an ideal case in any web application. If your purpose is to use IE for unit testing then I would consider using something like WaitIN. If your purpose is for application logic to access a URL and do something then consider using HttpWebRequest. If you still need a process to be started then create a Windows Service and then expose a web call so in Share Point you can just make a call and your Windows Service can run on local account or some other high privilege account.
Hope this helps and please provide the scenario why you want to start the IE and that can give you a better answer in the forum.

Why is my application failing when launched remotely?

I have a Windows application that sits on four different servers, its purpose is to look through a directory, find .wav files and copy them to a remote location. It works perfectly when ran from directory it's in on the server, but I don't like going to four different servers to execute the application. So below, I have a console app that is really just telling the user to store the IDs for the wav files in the right location so the four applications can see them, then executes the various programs. The problem is all four apps crash immediately after launch, I think it has something to do with how I'm executing the command, but I can't figure it out. Any ideas?
class Program
{
static void Main()
{
Console.SetWindowSize(90, 35);
Console.WriteLine(#"Place the ID of the interaction(s) you wish to recover in \\SERVER\c$\IDKeys.txt." + Environment.NewLine);
Console.WriteLine("Press Enter to find interactions.");
Console.ReadLine();
exeCmd();
}
static void exeCmd()
{
string[] executable =
{
#"\\Server1\C$\App\findwavs.exe",
#"\\Server2\C$\App\findwavs.exe",
#"\\Server3\C$\App\findwavs.exe",
#"\\Server4\C$\App\findwavs.exe"
};
foreach (string exe in executable)
{
Process proc = new Process();
proc.StartInfo.FileName = exe;
proc.Start();
}
}
}
The code you have executes the executable on the local machine.
Using #"\\Server1\C$\App\findwavs.exe does not mean that the executable will run on Server1, it just means that your local machine will look in this network path to obtain the executable file, but will run it locally.
You can use PsExec to execute an application on a remote machine.
Consider the following code that uses PsExec to run an executable on a remote machine:
string application = "c:\\app\\findwavs.exe";
string arguments = ""; //use this if you want to pass any command line arguments to the findwavs.exe executable
string location_of_psexec = "c:\\pstools\\psexec.exe"; //location of Psexec.exe on local machine
string remote_machine = "Server1"; //name of remote machine
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = location_of_psexec;
process.StartInfo.Arguments = string.Format("\\\\{0} -c \"{1}\" \"{2}\"", remote_machine, application, arguments);
This code assumes that the application path (e.g. "c:\app\findwavs.exe") is relative to your local machine, not the remote machine.
If you want to use a path relative to the remote machine, simply remove the -c from the value of process.StartInfo.Arguments
UPDATE:
Quoting from the above reference:
If you omit a user name, the process will run in the context of your account on the remote system, but will not have access to network resources (because it is impersonating). Specify a valid user name in the Domain\User syntax if the remote process requires access to network resources or to run in a different account. Note that the password and command are encrypted in transit to the remote system.
To make you application able to access network resources, use the -u and -p switches to supply a username and a password.
Running your code would be equivalent to navigating to \\Server1\C$\App\findwavs.exe in Explorer and double clicking on the exe. What I mean by this is that it will run the program on the machine that told it to run, not where the exe is stored.
The easiest way I can see to accomplish the task you want to perform would be to use PsExec.

run shell command (manage-bde) as administrator from C#

I need to run "manage-bde" shell command from C# code.
The main application process is already running as administrator and is Elevated.
I used code from : UAC self-elevation example on MS website for confirming the app process is elevated.
(http://code.msdn.microsoft.com/windowsdesktop/CSUACSelfElevation-644673d3)
However, when I try to run manage-bde from the C# code, I get "System can't find file specified".
Process p = new Process();
p.StartInfo.FileName = "C:\\Windows\\System32\\manage-bde.exe";
p.StartInfo.UseShellExecute = true;
p.Start();
As a workaround, I tried to create a batch file that runs the command.
string batchFileName = DateTime.Now.Ticks + ".bat";
StreamWriter writer = new StreamWriter(batchFileName);
writer.WriteLine("manage-bde");
writer.Flush();
writer.Close();
Process p = new Process();
p.StartInfo.FileName = batchFileName;
p.StartInfo.UseShellExecute = true;
p.Start();
The batch file is written , and executed successfully; However, the command "manage-bde" is not recognized.
I changed the code to use the verb "runas" and use admin password and that works, but I want the batch file to work without the need for providing the admin password. The current logged in user is already administrator on the computer but the batch file is not getting executed with the existing admin privileges . I need the batch file to execute and manage-bde to run successfully.
Your help or advice will be very highly appreciated :)
ps: some commands other than manage-bde work fine without need for admin runas.
The reason of the behavior I encountered was the Windows File System Redirector.
In most cases, whenever a 32-bit application attempts to access %windir%\System32, the access is redirected to %windir%\SysWOW64
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx
My application build was 32 bits. Whenever it tried to access System32 windows automatically redirected it to SysWow64 which does not contain "manage-bde.exe". I changed the build to 64 bits and then the application could access manage-bde.exe from System32
Even if you're running as the Administrator user, you're not fully elevated if UAC is running. Meaning that you'll have either the UAC prompt come up or you'll be prompted for a password.
The only real way you could get around that is to run your application elevated first, or to write a service that runs with elevated permissions to start your new process.
The alternative of course is to disable UAC, but that is undesirable in most situations.

How to run a server-side application via ASP.Net(C# or VB)

I wanted to build a front end web page so that I can start and stop various programs on my server remotely. I know that Shell will open something locally, but how can I make an ASP.Net page which activates programs server-side? Googling got me the "Shell" method, but I don't think that works server-side. Any ideas?
Take a look at the System.Diagnostics.Process class. It can allow you to start and stop an executable on the server.
You would have to impersonate an account that has sufficient privileged to run the application, though. You can use the UserName and Password properties of the System.Diagnostics.ProcessStartInfo object that you pass to Process.Start.
Edit
For an example, you could do the following:
var startInfo = new ProcessStartInfo("C:\MyServerApp.exe", "/A /B /C");
startInfo.UserName = "LocalUser";
// It's a bad idea to hard code the password in the app, this is just an example
startInfo.Password = "SomePass";
var process = Process.Start(startInfo);
// Not a good idea to wait in a web app, but you can until the process completes
process.WaitForExit();

Categories