Starting and tracking a process from c# - c#

I'm running into some strange stuff, hopefully someone can shed some light here...
I have my main app, app A, and I need to launch another app (app B) from App A. App A also needs to know when app B has exited. The code I've been using to do this looks like this:
_applicationProcess.StartInfo =
new ProcessStartInfo { FileName = _currentExecutablePath, WorkingDirectory = dir };
_applicationProcess.Start();
And I subscribe to the Exited event on the Process (_applicationProcess) to detect when it finishes.
Here's the kicker though. Both app A and app B share a library that sends a notification when a service is initialized (this is hooking up to the kinect service, as both apps are Kinect apps).
The bizarre thing is that when app B is launched using the code above, app A gets notified that the service is initialized. Yuck!
I don't want this. I want app B to be totally isolated from app A, yet I need to know when it has ended.
How can I do this?

Related

Start new UI process from Windows Service

I have two applications:
UpdaterService.exe (Windows Service)
Updater.exe (UI application)
I want to achieve, that my Windows Service calls my UI application. I tried:
Process p = new Process();
p.StartInfo.FileName = completePath;
p.StartInfo.WorkingDirectory = workingDirectory;
p.Start();
This works, but when I calls a UI element (e.g. MessageBox) I get an InvalidOperationException.
I can do:
p.StartInfo.UserName = userName;
p.StartInfo.Password = password;
but I don't have credentials for every user so that's out of the question.
Since Windows Vista and the Session 0 Isolation, I understand that every process, which is called by a Windows Service also runs in Session 0 and can't have a UI.
I read all articles to this theme I found, and I found this article, which describes my problem. It uses the Win32-API, get the actual user ID from winlogon.exe and opens the exe. I didn't tried it yet, but I guess it works (even in Win 7/10).
My Service and UI application don't need any kind of communication, it just should call the exe with the actual user account which is logged in.
I think it's not so uncommon to open a UI-exe from a service, because other companies (like Adobe) does the updates in the same way.
My questions are: Is it a 'clean way' to use the Win32 and subverting the Session 0 security (the updater will run only on Windows OS)? Is there meanwhile a better way to achieve this with .Net framework?

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

Invoke console app from windows service

I have a simple windows service which i need to use to invoke a console application.The console app generates pdf to print by opening the adobe reader window.Running the console app works fine to print pdf.But invoking it from service not successful.It doesnt even show up the console window where i log events.
Process pdfprocess = new Process();
pdfprocess.StartInfo.FileName = #"C:\Documents and Settings\xyz\Desktop\dgdfg\PdfReportGeneration\bin\Debug\PdfReportGeneration.exe";
pdfprocess.StartInfo.UseShellExecute = false;
pdfprocess.StartInfo.RedirectStandardOutput = true;
pdfprocess.Start();
But invoking other application like
pdfprocess.StartInfo.FileName = #"C:\Program Files\Adobe\Reader 11.0\Reader\AcroRd32.exe";
works fine.
What will be the reason?
There is probably some permissions issue there (PdfReportGeneration.exe inaccessible under service account or maybe something that it uses...)
I would advise to capture Process Monitor log to see where exactly it fails.
Windows services run in a different window station and cannot interact with the desktop, unless you're using an older version of Windows and tick a checkbox in the service properties in the service manager.

Keep application running all the time

Basically I need my application to run from system start until system shutdown. I figured out the following approach:
create MyApp.exe and MyService.exe
MyApp should install MyService as a service
MyService is supposed to run at startup and periodically check if MyApp is running. If it's not than start it.
That's the code I wrote for my service:
protected override void OnStart(string[] args)
{
while(true)
{
int processesCount =
Process.GetProcessesByName(Settings.Default.MyAppName).Count() +
Process.GetProcessesByName(Settings.Default.MyAppName + ".vshost").Count() +
Process.GetProcessesByName(Settings.Default.MyAppUpdaterName).Count();
if(processesCount==0)
{
//restore
var p = new Process { StartInfo = { FileName = Settings.Default.MyAppName, Arguments = "" } };
p.Start();
}
else
{
}
System.Threading.Thread.Sleep(3000);
}
}
How can I install this process so that it starts on windows start?
I'm not sure if this infinite loop in OnStart method is a good idea. Is it?
Is the general idea ok?
What I've done is have a windows service that runs the logic and main application code. Then if you need a GUI for it, have the windows service expose a web service via WCF and create a windows app that calls to the web service. On install, put you windows app in the windows startup.
This model will have the main application code running all the time, but the GUI is only up when a user is logged in.
Is the general idea ok?
As Hans points out in comments this is hostile to the user and fortunately won't work on Vista or later because services run in their own windows station. Put whatever logic you need to run all the time in the service and use an IPC mechanism such as WCF to communicate with an (optionally) running UI. If the user disables the service or exits the GUI respect their wishes...
How can I install this process so that it starts on windows start?
Add an entry to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run or HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Runthat points to your GUI application.
I'm not sure if this infinite loop in OnStart method is a good idea.
Is it?
No. You need to return from OnStart if you need to do work after OnStart returns create a Thread to do that work.

Windows Services for Console application in C#.net

I have made one console application for email notification in c#.
Can i convert this console application in to window service?
Thanks.
In visual studio, create a "Windows Service" project instead of a "Console Application". Look in the code that gets generated for you. There will be an OnStart() and OnStop() method. Those are the methods that will be called when your service is started and stopped. Put your code in those methods and you will have a Windows Service.
Contrary to some of the suggestions made by other answers, you probably can't do what you want using a Windows Service. It can't display the "notification" you expect because services can't display any kind of user interface.
The appropriate solution is to create a regular application that runs in the background without showing any windows. You can't do this with a console application (well, you can, but let's not overcomplicate things) because each time you run it, the console window will be displayed. But if you create a standard Windows application (either a Windows Forms or WPF application) then just don't create a window, everything will work out just fine.
You'll probably want to create and place an icon into the taskbar's notification area, which will handle displaying the notification upon the arrival of email. If you're creating a WinForms application, this can be done easily by using the NotifyIcon component.
Something like (warning, written without the aid of a compiler!):
static class Program
{
[STAThread]
static void Main()
{
// Standard infrastructure code
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Create a context menu and add item(s) to it
ContextMenu mnu = new ContextMenu();
MenuItem mnuExit = new MenuItem("E&xit");
mnu.MenuItems.Add(mnuExit);
mnuExit.Click += mnuExit_Click);
// Create the NotifyIcon
NotifyIcon ni = new NotifyIcon();
ni.Icon = new Icon(GetType(), "icon.ico");
ni.Text = "Email Notifier";
ni.ContextMenu = mnu;
ni.Visible = true;
// Run the application
Application.Run();
// Before exiting, remove the NotifyIcon from the taskbar
ni.Visible = false;
}
private static void mnuExit_Click(object Sender, EventArgs e)
{
Application.Exit();
}
}
When I go about this, I write the application in a class that does not consider its self a console application. By that I mean I dont write to the Console. I use log4net to write everything to... just log to Info. Use the console app to call the application class and in the app.config you can have an appender for console logging... so you get the console output. In the windows service this will just write to a file or not at all for the Info level logging. Its important to note the differences between a console app and a service... a service is not interactive and you can not input anything, so you app must consider this. For the windows service use the same class, but use the windows service project to start it.
ApplicationLogic: Has all the logic to run the application. Can take the arguments to make the app run the way it needs to, but does not interact with the console (can, but it would be bad design). Writes everything to logging (log4net maybe).
ConsoleApp: Is a wrapper around ApplicationLogic that can prompt the user for what ever it needs, can prompt for input and send it to ApplicationLogic. Has a log4net console appender if you need to see the output from ApplicationLogic.
WindowsService: Is a wrapper around ApplicationLogic. Has predetermined logic to keep it looping and running the Application logic. Logs to a file, no console output.

Categories