IIS hosted WCF service is not able to start a process - c#

I have a WCF service on a server,when I send a request from client application, the service will run a process to communicate with network nodes,this process is critical in my service and if it doesn't run the entire service is useless. the problem is this process never runs :(
I have been reading solutions for about two days but none of them helped me , I have give the service administrator privileges and check if the .exe file path is correct here is my code any help would be appreciate.
try
{
myprocess.StartInfo.UseShellExecute = false;
myprocess.StartInfo.CreateNoWindow = true;
myprocess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
myprocess.StartInfo.RedirectStandardOutput = true;
myprocess.StartInfo.FileName = myprocessPathAndName;
myprocess.StartInfo.WorkingDirectory =
Path.GetDirectoryName(myprocessPathAndName);
myprocess.StartInfo.Arguments = ConfigName;
myprocess.Start();
Log("myprocess Runnig " , sw);
Log(myprocessPathAndName, sw);
Log(myprocess.StartInfo.WorkingDirectory, sw);
}
catch (Exception e)
{
Log("Failed to run myprocess : " + e.Message, sw);
}
here is the log
7/26/2017 4:05:15 AM : myprocessRunnig
7/26/2017 4:05:15 AM : C:\inetpub\wwwroot\Station\COM\Dn\myprocess.exe
7/26/2017 4:05:15 AM : C:\inetpub\wwwroot\Station\COM\Dn

First:
Check the return value of your myprocess.Start() method call. If the process has started successfully, it would return true. Log the return value.
Process.Start()
Second: (you may be already doing this)
After the process has started, you should have to have a wait call for the process to run and complete.
Process.WaitForExit()
Third:
How do you determine that the process has not started ? Are you able to check the process in Task Manager ? It is possible that the process is starting and failing. Is there any log created by your process ? Have you checked the event log ?
Fourth:
Does your process have any UI component ? Do note that when running as a Service (in Windows Vista and later), the service cannot show a UI. It would just hang.
Fifth:
Are you able to manually run your process with the same user ID as your Service ? You can use RunAs or PsExec to run your process under the appropriate user ID.
Sixth:
You can redirect the standard error as well and read from it to see whether your process has written any exception
e.g.,
process.StartInfo.RedirectStandardError = true;
string errResult = process.StandardError.ReadToEnd();
You can log the result and check it.
Seventh:
You should also log the exit code of your process
process.WaitForExit();
var exitCode = process.ExitCode;

Related

Launching user program on Windows Server from C# Web Service

I am working on a ASP.NET web service that'll run on a AWS EC2 Windows Server instance. What it will do is receive some files and start a process (Marmoset Toolbag, a 3D tool) with some arguments. This program converts files to another format and closes afterwards. The code that runs the process:
using (Process p = new Process())
{
p.StartInfo.FileName = path;
p.StartInfo.Arguments = _args;
bool result = p.Start();
int timeOut = 15000;
int intInterval = 100;
while (!p.HasExited)
{
System.Threading.Thread.Sleep(intInterval);
timeOut -= intInterval;
if (timeOut <= 0) break;
}
if (timeOut <= 0)
{
//timeout happened
p.Kill();
return false;
}
else
{
return true;
}
}
}
catch (Exception e)
{
AddToRespondBody(CustomResponse.Conversion_failed, false, e.ToString());
return false;
}
This all works fine locally in debug mode.
But when I run this on IIS on the server instance, the process does open but is in background and stays idle.
After some research I found some information that this doesn't really work on server because of permission problems:
ASP.NET Web page and server control code executes in the context of the ASP.NET worker process on the Web server. If you use the Start method in an ASP.NET Web page or server control, the new process executes on the Web server with restricted permissions. The process does not start in the same context as the client browser, and does not have access to the user desktop.
I also tried a way with ProcessStartInfo but again without success. If I understand this problem correctly I need to run the process with higher priviliges, but even this didn't help. Is there even a way to pull this off with running a user program from a process?
Any help is appreciated!

C# Elevate Current Running Process as SYSTEM

How can I elevate current running process as system, not administrator.
try
{
var ps = new ProcessStartInfo();
ps.FileName = Process.GetCurrentProcess().ProcessName.ToString() + ".exe";
ps.Verb = "runas";
this.Close();
var process = new Process();
process.StartInfo = ps;
process.Start();
}
catch (Exception re)
{
this.TopMost = true;
MessageBox.Show(re.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
finally
{
Application.Exit();
}
above code restarts current running program to administrator privilege, like wise how can I get SYSTEM privilege?
c# 4.5
Any chance to create a new process as SYSTEM ? cause I see some apps(RunAsSystem) can make a file start as SYSTEM process.
Thanks.
PsExec from Microsoft SysInternals PsTools can start cmd as SYSTEM and from there you can do almost anything.
I am also searching for another way to do it.
There is no way starting a process as system. This can be achieved only for boot time/kernel level scenarios, drivers, services etc.
It would be a security risk if that could be done. Create windows service if it is cruicial to you to run your logic as system.

Why would Process.WaitForExit throw a "no process" exception even when a process does exist?

I have a windows service containing this code:
public static void ExtractTextInner(string source, string destination)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = EXTRACTOR_EXE_FILEPATH
startInfo.Arguments = "\"" + source + "\" \"" + destination + "\"";
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
int exitCode = process.ExitCode;
process.Close();
if (exitCode != 0)
{
switch (exitCode)
{
case 1:
throw new ApplicationException("IFilter Extraction Failed");
default:
throw new ApplicationException("Unknown Exit Code:" + exitCode.ToString());
}
}
}
The purpose of this code is run an IFilter extract on a document, we use a seperate process because some IFilters are notoriously flaky.
Now this code runs perfectly fine on Windows 7 and Server 2008 R2 boxes but on a Windows Server 2003 the WaitForExit immediately throws a "There is no process associated with this Process object" exception. The process does exist and completes its task without a problem.
Anyone seen this? Can anyone shed any light on why WaitForExit would thow this error?
Additional Info
If I place this code in a Console App and run it works fine on the Windws Server 2003 box as well, hence it would appear to be a specific problem running this in a Service on a Windows Server 2003 box.
When starting processes, with the System.Diagnostics.Process class, the system can either use CreateProcess or ShellExecuteEx Win32 function. When using CreateProcess only executable files can be started. When using ShellExecuteEx, any file which can be started using the "Start->Run" command from the shell.
However these are completely different ways of starting processes. ShellExecuteEx involves the shell, and can, for example, re-use an existing instance of Word or Excel to open a document, by using the information stored under the HKCR\<progid>\shell\<verb> registry key. This may involve for example using DDE to search for and then activate an existing Excel instance.
See documentation on ShellExecuteEx's SHELLEXECUTEINFO:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb759784(v=vs.85).aspx
Note that ShellExecuteEx may or may not return an hProcess depending on whether a new process was started. This is the behavior which you are seeing.
CreateProcess is a lower-level function and creates a process directly, and simply passes the equivalent arguments. It always returns a process handle.
Note: Since you seem to be starting an executable file, it is a bit surprising that no hProcess is returned by ShellExecuteEx. Nevertheless, if you want to ensure you get a process handle, using UseShellExecute = false is the correct thing to do.

How to NOT wait for exit using Impersonataion.RunProcess In c#/ASP.NET

What I want to know is if there is a way to NOT wait for a process when using impersonation. There's no overloads so I'm not sure how to do this.
// always waits for exit to continue
Impersonation.RunProcess(someProcessPath);
The reason I want to do this is that I have a long executing application that processes large files, but I want to deliver a success response to the client that the process has began before directing them to a status page. I cannot run the process with a normal process.Start() because the IUSER needs to impersonate an elevated user account.
I've even tried using process.StartInfo after Impersonation.Login() and supplying a un/pass, but I think the "logged in" status is part of the static Impersonation class only.
if (Impersonation.Logon(LoginCredentials.UserName, LoginCredentials.Password))
{
// this fails with an invalid privileges exit code
process.StartInfo.FileName = path;
process.StartInfo.UseShellExecute = false;
process.StartInfo.UserName = "Administrator";
SecureString secString = new SecureString();
foreach( char c in "mypassword" )
secString.AppendChar( c );
process.StartInfo.Password = secString;
process.StartInfo.Verb = "runas";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
}
I've found a zillion posts on how to wait for a normally invoked process to end before continuing using Process.WaitForExit(). I've also successfully ignored the exit by using process.start() by itself inside console apps (already authenticated).
You could fork it of to a different thread:
// using ThreadPool for long running tasks is discouraged so create a new thread
var t = new Thread(() => Impersonation.RunProcess(someProcessPath)) { IsBackground = true };
t.Start();
You could set some flags inside the thread method to indicate when it was called and when it has finished.
Impersonation.RunProcess("/path/to/cmd.exe /C start "+someProcessPath);
This will return when cmd.exe ends, which is after starting someProcessPath

Why won't "cmd.exe /C command" end when called via Process.Start()?

I'm trying to run a command via command prompt from an ASP.Net web application. I can see the process start in task manager on the web server, however the process just sits there and never exits nor does it run the commands I specified.
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " +command;
startInfo.UserName = "myuser";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Domain = "mydomain";
startInfo.CreateNoWindow = true;
String pass = "mypass";
System.Security.SecureString secPass = new System.Security.SecureString();
foreach (char c in pass.ToCharArray())
{
secPass.AppendChar(c);
}
secPass.MakeReadOnly();
startInfo.Password = secPass;
process.StartInfo = startInfo;
process.Start();
//output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
I've tried both with and without reading the standard output.
The application will hang on process.WaitForExit(); until I kill the process via task manager.
I think we need to understand what commands you are actually trying to process in order to determine what's going on. Also we need to know what OS the server is running.
For example, I did see in your comments where you tried "echo test > C:\test.txt" Under Windows Server 2008 (and Windows 7) the root directory requires administrator permissions in order to create files. If this is executing under IIS, my guess is that your IIS user isn't an administrator and you are getting security exceptions.
Also, a number of commands may require elevated priviledges due to UAC. I don't remember exactly, but I'm guessing that if those commands are being caught by UAC then the process is waiting for UAC confirmation... Which I believe you cannot supply via a command line.
This type of problem won't be seen if you log into the machine and execute it directly... unless you are logging in with the worker process user account.
So, the very first thing you need to do is figure out what it is you are trying to run and see if the user the worker process is executing under can even perform those actions. Security is there to protect you, so be careful about granting additional permissions to the user.
The reason why it might work on one machine versus another again depends on the OS's those machines are running and the configuration of the user the commands are executing under.
If this is truly a security issue, as I suspect, then you should post a question on serverfault.com to ask what permission sets you need to execute various commands under your worker process user.
You might look at the machines event logs to see if there were any warnings or errors thrown about the command. Sometimes things like this can show up there to give you a bit more information as to what happened.
Once passed to CMD, the control has passed to the shell. It's better to add a close it like this:
private void closeSubProcess()
{
Process[] currentProcesses = Process.GetProcesses();
foreach (Process p in currentProcesses)
{
string s = p.ProcessName;
s = s.ToLower();
if (s.CompareTo("YOURPROGRAMNAMEHERE") == 0)
{
p.CloseMainWindow();
p.Close();
}
}
}
I am calling cmd.exe to start a node module in Windows. npm obviously must be installed first, along with the node module I need, and then I can call the module with args in C#. Problem was, the cmd.exe would not shut off, I'd have to use Task Mgr (just like this question!).
//This requires npm, and the module installed by npm...
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = true; //closes command window
psi.Arguments = "/c <nodemodulename>" + file1 + ".txt " + file2 + ".log";
Process p = Process.Start(psi);
p.Close();
The /c argument was key to closing down cmd.exe. When I started out, I had put in the /K argument, which keeps the darned thing running. Solved. Hope this helps. (This is like ancient, but we always forget)

Categories

Resources