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!
Related
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;
I am programming for a software company.
Our company has an Application called (common component command) ccc.exe. This application is for Sending command to Microsoft IIS server.
Now, and during my program, I want to detect running this process (ccc.exe).
After this I use this method:
private bool IsProcessRunning(string processName)
{
Process[] pname = Process.GetProcessesByName(processName);
if (pname.Length == 0)
return false;
else
return true;
}
But unfortunately their computers running a System process Called CCC.EXE (It is from ATI Technologies).
It is running on start up. And if I use this method It will return a wrong value, cause they have the same name.
So, How can I recognize CCC.EXE (system file) from ccc.exe *32?
You could try looking at the Process.MainModule property:
Process[] pname = Process.GetProcessesByName(processName);
if (pname.Any(x => x.MainModule.FileName == "the path to the ccc.exe"))
{
return true;
}
return false;
Note: Be warned I have found sometimes while groking the Process object that things which work in DEV do not always work in production due to security permissions.
I have a windows service that is intended to do the following:
Monitor a folder on the server for PDF files
When file arrives, run a third party exe to convert the PDF to Excel. No text output is generated. The third party tool simply uses the input file path and generates an output excel file. No need for a window launch. No need to track sessions.
Windows service then reads the data from the Excel, processes it, and outputs an xml into a folder.
All this works fine in debug mode. However, when I try to run the windows service on my local machine in release mode (using installutil) as a service (as opposed to in visual studio), it does not work. When I attach-to-process, I notice the cursor just hangs on waitforexit and no excel is generated. Since it works in debug but not in release mode, I suspect it's a permissions issue. Any feedback will be appreciated.
Already tried checking "Allow service to interact with desktop". Didn't help.
EDIT: correction - cursor actually hangs on exeProcess.WaitForExit()
ProcessStartInfo sInfo = new ProcessStartInfo();
sInfo.FileName = ConfigurationManager.AppSettings["FileName"];
sInfo.Arguments = GetArguments();
sInfo.UseShellExecute = false;
sInfo.CreateNoWindow = true;
sInfo.ErrorDialog = false;
sInfo.WindowStyle = ProcessWindowStyle.Hidden;
//sInfo.RedirectStandardError = true; //didn't work
//sInfo.RedirectStandardInput = true; //didn't work
//sInfo.RedirectStandardOutput = true; //didn't work
using (Process exeProcess = Process.Start(sInfo))
{
//StreamWriter inputWriter = exeProcess.StandardInput;
//StreamReader outputReader = exeProcess.StandardOutput;
//StreamReader errorReader = exeProcess.StandardError;
exeProcess.WaitForExit();
}
The problem is almost certainly that steps 2 and 3 do not work in the non-interactive session 0. The big difference is not between debug and release builds. But between running on the interactive desktop, and the service running in session 0.
To get out of this, and continue using a service, you need to make sure that all steps can operate in session 0. Step 2 we know nothing about. Step 3 looks like it involves automating Excel. That is officially not supported and known not to work under session 0. You'll need to read the Excel file using something other than Excel. As for step 2, that depends on the third party tool that converts from PDF to Excel.
I would put into the code proper exception handling and logging to e.g. event log to find out if there is anything different than expected.
Next step may be to configure the service with credentials which you know will have access to executable you try to run, to the directories where you export the files generated etc.
If possible / available then try to use assembly which you can reference instead of running another executable from your code. This way you will have it more under control;)
EDIT:
In general it is possible to run command line tool by windows service. There just need to be clear how the tool expects to get the data, if it is from command line and tool is not waiting for user to enter anything. Do you have problem just with this command line utility or in general?
Service:
private FileSystemWatcher watcher;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
watcher = new FileSystemWatcher();
watcher.Path = #"c:\temp\service";
watcher.Created += watcher_Created;
watcher.EnableRaisingEvents = true;
}
protected override void OnStop()
{
}
private void watcher_Created(object sender, FileSystemEventArgs e)
{
try
{
ProcessStartInfo startInfo = new ProcessStartInfo(pathToExe, e.Name);
EventLog.WriteEntry(e.Name);
Process process = Process.Start(startInfo);
process.EnableRaisingEvents = true;
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.ToString());
}
}
Command line tool - expects to get name of the file as parameter
public class Program
{
public static void Main(string[] args)
{
File.AppendAllText(pathToLog, string.Format("{0} - File got created in watched folder - doing conversion of {1}\n", DateTime.Now, args[0]));
}
}
In my asp.net application, iam using windows forms.dll to use some of the windows controls by creating a thread.This works fine in my system but is giving a session timeout when hosted on IIS.
Creating a thread gives me session time out on IIS.
How do i create threads that can work fine on IIS?
Below is the code where iam created the thread.
public string[] DisplayFileDialog()
{
string[] result = null;
try
{
Thread objThread = new Thread(state =>{
result = FnOpenFileDialog();
// TODO: do something with the returned result
});
objThread.IsBackground = false;
objThread.SetApartmentState(ApartmentState.STA);
objThread.Start();
objThread.Join();
return result;
}
catch (Exception ex)
{
return result;
}
protected string[] FnOpenFileDialog()
{
IntPtr hdlr = GetForegroundWindow();
WindowWrapper Mockwindow = new WindowWrapper(hdlr);
OpenFileDialog fDialog = new OpenFileDialog();
fDialog.Title = "Select Files";
fDialog.Multiselect = true;
fDialog.CheckFileExists = true;
fDialog.CheckPathExists = true;
System.Windows.Forms.DialogResult dr = fDialog.ShowDialog(Mockwindow);
string[] filenames = fDialog.FileNames;
return filenames;
}
Thanks in advance.
Your code is executed server side, which is why your stalled by a time out response. Your main thread waits (objThread.Join) for the response of a dialog box opened on the server as you can't see it on the client side you never get a response.
If you want to open the dialog file on the client side you can do it in a similar way as was ActiveX objects.
You can find a msdn tutorial of how to do it at the following address but it only work in IE:
http://msdn.microsoft.com/fr-fr/magazine/cc301932(en-us).aspx
If I'm understanding your question correctly, the answer is simply: You can't do that.
Windows forms controls don't work in a browser. It works on your machine because the browser window is local, so the thread can attach to it and use it as a parent.
The IIS process doesn't have a window, it only serves up text, images, and video files. You're essentially asking an IIS thread, running on some machine in a server room somewhere else, to connect to a browser's window on someone else's machine, and then start displaying Windows Forms controls on it.
What if they are on a Linux box, or a Mac?
ASP.NET was created to solve this problem of creating interactive forms for IIS.
Hope this helps.
I have a webservice with a couple of methods that attempt to run or message another .EXE on the system to do a specific task.
Either we can start the .EXE process with certain parameters or send it a WndProc message to make it do the desired operation. This works fine locally on my system calling the exe with parameters in cmd or sending a WndProc message from the webservice when debugging it in Visual Studio.
None of this works over a real environment however. I had the run .Exe with parameters method (DoSomething) write the exception to a file:
System.ComponentModel.Win32Exception (0x80004005): No Access
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at Someprogram.ProgramService.DoSomething(String text)
The other method for wndproc sendmessage I wrapped in a try/catch as well but no exception thrown. It actually locates the process though as I had it print a file:
public static void SendMessageToSomeProgram(string message) {
Process[] processes = Process.GetProcessesByName("SomeProgram");
if (processes.Length >= 1) {
//iterate through all running target applications
foreach (Process p in processes) {
//test write if process found
TextWriter tw = new StreamWriter(#"c:\wndprocfile.txt"); //this file is printed
tw.WriteLine(DateTime.Now.ToString());
tw.Close();
//do stuff
try {
byte[] sarr = System.Text.Encoding.Default.GetBytes(message);
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = message;
cds.cbData = len + 1;
SendMessage(p.MainWindowHandle, WM_COPYDATA, 0, ref cds);
} catch (Exception ex) {
TextWriter tw2 = new StreamWriter(#"c:\wndProc_errorfile.txt"); //not printed
tw2.WriteLine(DateTime.Now.ToString() + "Exception: " + ex.ToString());
tw2.Close();
}
}
}
Now I see why it's nice to have security like this in place but is there an easy way around this? Maybe just some settings in IIS?
UPDATED INFO: The server is running IIS 5.1 so no Application Pool feature.
The service inside IIS runs as the user connected to the app pool it's running as. So try to change the user of the app pool to a user that have access to start the application you want to start up.
To do this, check the applications app pool and then go to the app pool and change the user. To change the user you have to turn pass-through authentication off.