I'm trying to launch an external updater application for a platform that I've developed. The reason I'd like to launch this updater is because my configuration utility which handles updates and license configuration for the platform has shared dependencies with other assemblies in the folder where the update will be deployed. So, while I can rename the configuration utility and overwrite it when deploying the update, I can't rename or overwrite the DLLs it depends on. Hence, the external updater application.
I'm handling all of the update gathering logic in the configuration utility, then attempting to launch the updater to handle the actual file copy/overwrite operations. Obviously, because of the file in use issues, I need the configuration utility to exit right after the updater begins.
The problem I'm having is that I'm using the standard Process.Start method of launching the updater, and as soon as the configuration utility exits, the updater process gets killed too.
Is there any way that I can create a Process that outlives its parent, or launch an external application that can run beyond the program that launched it?
EDIT:
Apparently, in my updater application, I miscalculated the number of command line arguments which are passed to it. Because of this, the updater would exit immediately. I misinterpreted this to mean that the launcher application was killing the "child" process, when in fact, it wasn't.
The answers below are correct.
It seems that the problem you are seeing has a different reason because the Process class will not kill any processes started using Process.Start when your application exits.
See this simple sample program, the calculator will stay open:
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
Process.Start(#"C:\windows\system32\calc.exe");
}
}
There's no reason why a process started with Process.Start should automatically die when the launcher exits. My guess is that you're doing something odd in the updater.
I've written an updater doing exactly this kind of thing before, and it's been fine.
For example:
Launcher.cs:
using System;
using System.Diagnostics;
class Launcher
{
static void Main()
{
Console.WriteLine("Launching launchee");
Process.Start("Launchee.exe");
Console.WriteLine("Launched. Exiting");
}
}
Launchee.cs:
using System;
using System.Threading;
class Launchee
{
static void Main()
{
Console.WriteLine(" I've been launched!");
Thread.Sleep(5000);
Console.WriteLine(" Exiting...");
}
}
Compile both of them, separately, and run Launcher.exe. The "launchee" process definitely lasts longer than the launcher.
Just a thought from my foggy memory, but I seem to remember having a discussion a while back that when the Process.Start method is called from Form that the spawned process has some sort of dependency (not sure what, why or how, memory is a bit foggy).
To deal with it, a flag was set that was actually called from the Main() method of the application after the main form/app exited and that if the process was launched from the Main() method, eveything worked out just fine.
Just a thought, like I said, this is purely from memory, but some of the examples posted here all being called from the Main() method of a console app seemed to jog something.
Hope all works out well for you.
Related
I have two programs running. Program1.exe and Program2.exe.
Program1 is written in C# .Net4.8 and is used to upload/download transaction from the web, check for updates and handle various other tasks that Program2 cannot.
Program2 is written in VB6. Yeah, VB6... It's set for a rewrite but we aren't at that stage yet due to it's complexities. It is more of a use interface application.
When Program1 checks for updates and determines if there is one available. When Program2 shuts down, Program1 need to prompt the users that there is an update available and attempt to install it.
My issue is, how do I determine that Program2 has shut down to immediately prompt the user before they shut down the computer. I was thinking that Program2 creates a flag file and I watch for it with a filewatcher or I can put up a timer that checks if Program2 is running. I'm assuming I'll have to put the timer on 1 second intervals to catch it correctly.
Which is more efficient or is there a better way to handle this?
Any suggestions would be greatly appreciated.
Consider looking at it from a different perspective.
When Program2 shuts down, you could have it launch Program1 with a command line argument that tells it to check for updates. If no updates are available, Program1 shuts down silently. Otherwise, it prompts to apply the update and does so if allowed to.
Of course, this means adding command line parameter support to Program 1 (unless patching is all that it does).
But this way, you could run the patcher both before and after Program2 runs.
I'm writing a small library to help manage some objects in Excel. I'm testing this DLL using a simple console application that makes calls to the library, then prints the results out. I can then end the program in any of the typical fashions, usually by either hitting return (thus completing the ReadLine call) or hitting the window's close button. However, the reference to the Excel instance behaves differently based on how the program exits.
In my program, if no existing reference to Excel can be found, I use the following line:
_app = new ExcelInterop.Application();
where _app is an instance of Microsoft.Office.Interop.Excel.Application in either a static or singleton class (I've tried both, both have the same results).
Assuming the program creates it's own instance (and doesn't find one already open):
The instance will remain open if the program is exited by clicking the close window button:
The instance is released, and no longer appears in the task manager if the program is exited by reaching the end of the code in the Main block
Is there anyway to make all program ends behave like the latter case? Furthermore, this DLL will go on to be used in a WPF application, are there similar concerns in WPF? Or at large, even?
Perhaps most importantly, what are the technical reasons for this behavior?
A console mode program is a pretty hostile place for the COM interop wrapper objects that are needed for an apartment-threaded out-of-process COM server. This program demonstrates the issue:
using System;
class Program {
static void Main(string[] args) {
var prg = new Program();
Console.ReadLine();
}
~Program() {
Console.WriteLine("Clean-up completed");
System.Threading.Thread.Sleep(1500);
}
}
Try it both ways, by pressing Enter and by clicking the Close button. You'll see that the finalizer never gets executed. The operating system terminates the process before it gets a chance to shut down properly when you click the Close button.
Same problem with the finalizers for the COM wrappers. They cannot execute so IUnknown::Release() doesn't get called and the Office program is completely unaware that the client program is no longer there. Windows has its own cleanup for abandoned out-of-process servers but that doesn't work for Office programs for some otherwise mysterious reason.
That explains it, fixing it isn't so easy. You'll have to register a callback that runs when the Close button is clicked. If necessary, set the app reference to null if it is still in scope and force the finalizer to run with GC.Collect() + GC.WaitForPendingFinalizers(). Do keep in mind that this is just a band-aid, not a fix. It won't work when the user aborts your program while you are busy talking to the Office program. Avoiding a console mode project is best.
Suppose I have a C# WinForms application and it is started by external program simply by using Process.Start(MyModule.exe).
I've tried to debug my code by using My project properties->Debug->Start Action->Start external program (with setting proper Working directory of course).
My enother attempt was Debug->Attach to process
UPDATE: Both my module and external program use one resource. So external program releases it, then calls Process.Start(), waits for my process to exit ans then capture the resource again. So I can't attach when your program is already running.
Both of them failed - breakpoint in Program.cs was never hit.
So, how can I debug my code in such circumstances?
There are two ways I know of to easily solve this problem. The first way is have your program request a debugger attach to it as the first thing it does in Main via Debugger.Launch()
public static void Main(string[] args)
{
Debugger.Launch();
//Rest of your code here
}
This will make a dialog like the following show up
This will allow you to attach to your running visual studio or start a new instance.
The other way to solve this when you can't use the previous method (for example I don't think it works inside services) is put a loop at the start of your code that will loop forever until a debugger is attached, this gives you enough time to do the "Attach to process" method you tried earlier without letting the program progress.
public static void Main(string[] args)
{
while(!Debugger.IsAttached)
{
Thread.Sleep(1000); //Sleep 1 second and then check again.
}
//Rest of your code here
}
There are two different methods you can use System.Diagnostics.Debugger.Launch() or System.Diagnostics.Debugger.Break() The first will attach a debugger (letting you choose which) and then do nothing. In the case where one is already attached nothing will happen.
The latter will do exactly as Launch in the case no debugger is attached and will serve as a break point if one is attached.
So simply write System.Diagnostics.Debugger.Break(); where you want your break point to be.
That will result in a dialog asking you how you wish to debug the program (which of course also means your should remove the line when your done debugging)
In the dialog choose the appropriate instance of VS (or create a new) and the simply continue debugging as usual
I am trying to use AppWinStyle with Process.start but it does not work as i expected.
The below code will open file 1.txt and it will be minimized with no focus to it.
Shell("notepad D:\1.txt", AppWinStyle.MinimizedNoFocus)
But below code will open 1.txt with focus on it.It will not be minimized.
Process.Start("D:\1.txt", AppWinStyle.MinimizedNoFocus)
Why does it happen? Please help me to solve this
A boilerplate example:
using System;
using System.Diagnostics;
class Program {
static void Main(string[] args) {
var psi = new ProcessStartInfo("notepad.exe");
//psi.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(psi);
}
}
Run it once to make sure it works, then remove the comment and observe the outcome. You'll briefly see the Notepad window flash but it immediately terminates again. Might depend on the Windows version, I described what happened for Windows 8.1
A GUI app gets the ProcessWindowStyle you specify through its WinMain() entry point, the nCmdShow argument passes the value you specified. What the app actually does with that value is entirely up to the app. Boilerplate implementation is to pass it to the ShowWindow() call, the one that makes its main window visible.
Using ProcessWindowStyle.Hidden is in general very problematic and a properly written GUI app will ignore it, like Notepad did. Because what you asked it to do is to start the program but not display any window, not even a taskbar button. In other words, you asked it to turn into a zombie, a process that runs without any way for the user to get to it. The only possible thing the user could do is run Task Manager and kill the process.
So sure, definitely expect this to not work. It shouldn't.
No such overload with Process.Start:
Process.Start("D:\1.txt", AppWinStyle.MinimizedNoFocus)
See all overloads here: Process.Start Method
In order to achieve it using the Process.Start, use the ProcessStartInfo.WindowStyle, setting it to ProcessWindowStyle.Minimized.
By the way, the AppWinStyle enumerator is specific for the Shell function:
Indicates the window style to use for the invoked program when calling
the Shell function.
I searched the web and Stackoverflow, I didn't find anything.
I am sorry if this question already exists.
If my C# application is called through the cmd for example:
C:\System32\MyConsoleApplication -parmOne -paramTwo ...
Is there a way to write into the cmd (for example to giving progressinformation?)
Edit: Cause I use a Consoleapplication the solution ist Console.WriteLine It doesnt worked for me cause my application requires adminrights (trough a Manifestfile) and was called with normal userrights. In this case the UAC asks for rights and opens a new Cmd with the application.
better solution : http://www.nerdyhearn.com/blog/157/
here is the code of the site:
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
[STAThread]
static void Main(string[] args)
{
// Enable visual elements just like always
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Attach to the parent process via AttachConsole SDK call
AttachConsole(ATTACH_PARENT_PROCESS); // <-- important point here
Console.WriteLine("This is from the main program");
Application.Run(new Form1());
}
You can use the AttachConsole call at your will in the special conditions you need. This is much better and flexible and does not require you to change your application manifest. if its a win32 app, wll good for your app. if its launched from a cmd then the output will appear as excpected.
My opinion: this is just some useless microsoft complication of some concepts that are so pure and natural in the Unix world. If your application is launched from a visual launcher (icon, nautilus..) then the output is lost. You can launch your app from a console and its gets in the console. you can redirect the output if you need, it all imbricates logically and its powerful. With microsoft... its bloated and gets in the way of everybody.
This all depends on what the exe type is - which is a flag in the PE-header (the "exe" shell):
if it is flagged as a windows app, it doesn't get a console / output to the existing console - regardless of how it is started
if it is flagged as a console app, it does get a console / output to the existing console - regardless of how it is started
It cannot be both. It you want it to work like a windows exe normally, then you will have to compile it as a windows exe, which means no: it won't write to the console normally. Trying to acquire access to the console from a windows exe is tricky, and would require P/Invoke to the OS.
If it is flagged as a console exe, then just Console.WriteLine will work fine.