I have a console application written in C# that is scheduled to run every 15 minutes or so using the built-in Windows Task Scheduler.
Every time it runs, the black console box pops up for the duration of its execution and then closes. I am not writing anything to the console. Is there a way to make this run in the background?
Project > Properties> Application tab > change Output type to "Windows application".
No more console window.
Easy!
It seems hard to believe, but it works as a charm. I have used this for some setup projects, when you want to perform custom tasks with no signs of it.
Create the project as a Windows application project (this is the hard part).
Never make calls to any form. Just keep on in exactly as in your console application
class Program
{
static void Main(string[] args)
{
// Just don't call Application.Run(new frmMain(args));
// ... your code
}
}
This is because windows application projects are no really different than console, except because of the first form and references.
It is totally hidden execution. Try it!
You can use the Windows API to minimize the console box. Otherwise you can make it a Windows EXE file that does not actually load a form and call System.Windows.Forms.Application.Run().
Code to minimize the console:
[DllImport( "user32.dll" )]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public const int SW_SHOWMINIMIZED = 2;
IntPtr winHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
ShowWindow(winHandle, SW_SHOWMINIMIZED);
What about implementing the app into a windows service? You can set the interval to 15 mins and run the operation in the timer_tick.
If you already have a Windows Console app created you can simply change the Output type of your app to Windows Application.
Under your project:
Go to Properties > Application
Select "Windows Application" as the Output type.
This would be the least impact and you can keep your Windows Task Scheduler running the same task.
If it doesn't write anything to the console you could make it a service.
http://msdn.microsoft.com/en-us/library/9k985bc9%28VS.80%29.aspx
It will only show up if it's scheduled to run as the same user that's currently logged in. Create another user on the machine with a ridiculously long password, set it to be an Administrator (only if needed) and schedule the task to run as that user.
This is easy. Set the task to run under an account that is not your login account.
Related
I have a C# GUI application that also supports a command line mode for server-side scripting. My application keys off of the number of input arguments, and if > 0, attaches the parent console.
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
[STAThread]
static void Main(string[] args)
{
bool runningFromConsole = args.Length > 0 && AttachConsole(ATTACH_PARENT_PROCESS);
if(runningFromConsole)
// Handle input arguments
else
// Launch GUI
}
I am able to successfully write text to the console with Console.Out.WriteLine("Text");, but the line is not sent to the console as a STDOUT (or STDERR if I use Console.Error.WriteLine("Text")).
When running my application locally, this is not a big deal, but when running on a build server, the application returns do not register. Right now, I am working around the issue by creating a supplimental log file that I type application.log to the console once my application finishes running.
Is there a way for force text printed to the console to be sent as STDOUT/STDERR?
AttachConsole doesn't quite behave the way you expect, what you need to do often is to AllocConsole and change your stdio handles to use that console.
The accepted answer for this question I can verify works in this scenario because I've used it: No console output when using AllocConsole and target architecture x86
I'm playing with Microsoft's UWP AppServiceBridgeSample (here).
It is working well, but I would like to get rid of the console window of the BackgroundProcess application. The reason for this is that my BackgroundProcess starts another Win32 desktop application and works only as a mediator, so I don't want to disturb users with a console window. (Yes, it can be minimized, but I would rather not show it at all).
I have tried to hide it using the API mentioned here, but with no luck, the console window is still visible. Neither did switching the project's output type from Console Application to Windows Application.work.
Another thing I have tried was to create other BackgroundProcess project as a Windows application. It runs fine until I call AppServiceConnection.OpenAsync(), which causes the BackgroundProcess application to exitstrong text, thus the connection to UWA is not available.
static async void ThreadProc()
{
try
{
AppServiceConnection connection = new AppServiceConnection();
connection.AppServiceName = "CommunicationService";
connection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
connection.RequestReceived += Connection_RequestReceived;
AppServiceConnectionStatus status = await connection.OpenAsync();
//status check etc. ...
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
It seems that opening the AppService connection is only possible from a console app.
So here are my two questions:
Is it, by any chance, even possible to hide the background process' console window?
Can I use the background process as a Windows application, without AppServiceConnection failing during OpenAsync calls?
Re 1: Go into the project settings and change the output type from Console to Windows app. Also make sure the Main() function doesn't exit until you are done with the background process. Here is a better sample that shows this with a Windows Application:
https://stefanwick.com/2017/05/26/uwp-calling-office-interop-apis/
Re 2: AppServiceConnection works the same way from a windowed application as well. Make sure you add the right reference to the Windows.winmd to be able to build. If you have trouble with that, please post a specific question with details of the problem you are seeing
I'm developing an application which has 2 parts:
1) A WPF application which runs from the system tray. It does have a GUI window, which can be brought up by right-clicking the sys-tray icon & choosing an option on the context menu, but it is not needed very frequently & the app will run from the sys-tray most of the time. Moreover, I've changed the Closing() event of the MainWindow, so as to minimize the app, if the user tries to close it.
2) A console application which runs without displaying a console & its purpose is to poll for launch/close of another application. As soon as the other application is launched/closed, the console application launches/closes the WPF application too. (Please don't tell me to do this using a Windows Service. I've already explored the route before. It doesn't work for me due to several reasons, which I won't enlist here).
PROBLEM: I am not able to close the WPF application from the console application. What I'm doing is as follows. First I obtain the process for my WPF application:
Process AppProcess = Process.GetProcessById((int)AppID);
After this I've tried a lot of options as follows:
1) Killing the process: AppProcess.Kill();
This is the only one which worked, but is very unelegant. It also leaves the SysTray icon undisposed, so it is not acceptable.
2) AppProcess.Close();
Doesn't work at all & I don't know why.
3) AppProcess.Dispose();
Doesn't work at all & I don't know why.
4) AppProcess.CloseMainWindow();
This only works if the user has kept the GUI of the WPF app opened, which is very rarely the case as I mentioned before. So, normally this also doesn't work. (You might say that I've hacked the Closing() event to prevent closing the window. Don't worry I've taken appropriate care to handle that. I've provided other measures to close the app. There is a boolean variable which decides whether the Closing action is to be cancelled or not.)
5) Passing custom/standard message to the WPF Application's main window.
This also works only if the main window (GUI) of the WPF app is open, else it doesn't receive the message.
So, all in all, no method is working. I need a reliable method to close the WPF app gracefully from the console app. Please suggest something.
The current way I'm doing it is as follows:
In the Console App:
const uint WM_CUSTOMCLOSE = 0xFE;
IntPtr hWnd = AppProcess.MainWindowHandle;
SendMessage(hWnd, WM_CUSTOMCLOSE, 0, 0);
In the WPF app:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if(msg == 0xFE)
{
ExitFlag = true; //Exitflag is checked later to decide whether closing is to be cancelled.
this.Close();
}
return IntPtr.Zero;
}
Use IPC as JeffRSon suggested. MSMQ is a very easy and effective way when two processes are on the same machine.
Define a queue of your WPF application and when it starts, no matter showing UI or not, let it listen the queue. Console application can send a message to the queue with closing application message. You have to define the data contract. You can refer to:
http://www.codeproject.com/Articles/3944/Programming-MSMQ-in-NET-Part-1
Ok, I found a way to close the WPF app. The reason it wasn't receiving the message was that for some reason, AppProcess.MainWindowHandle was not giving the handle of the main window of the WPF app, when the WPF app ran from the system tray.
So, instead I'm using the user32.dll:FindWindow() method found in the Win32 APIs to find the main window of the WPF app. After that when I pass my custom message to it, the WPF app shuts down gracefully.
I created a winform (monitoring) application using VS 2005 (c#), and now, I have a problem when this application crashes for some reason, I have to be sure that it will be restarted automatically.
How can I resolve this? (maybe by using windows services application?)
Thanks
Yes, a creating a Windows Service would work as you can set it to automatically restart if it crashes but a better way would be to prevent it crashing in the first place! Is there a specific reason it crashes?
With good error handling and reporting you can write it so that it simply reports any errors that occur and carries on, which IMHO would be the best route to go
Consider this:
http://msdn.microsoft.com/en-us/library/cc303699.aspx
[DllImport("kernel32.dll")]
public static extern int RegisterApplicationRestart(
[MarshalAs(UnmanagedType.BStr)] string commandLineArgs,
int flags);
Minimum supported server
Windows Server 2008
http://msdn.microsoft.com/en-us/library/aa373347(VS.85).aspx
Creating a Windows service is a very good idea for any long-running background process for many reasons, however re-starting a crashed application is not one of them!
You should work out why the application is crashing and prevent it from happening.
By all means, also convert your application to a Windows service - you will see many benefits, however the correct way to solve your problem is to fix the application crash in the first place.
For*strong text* a watcher app.
You should create a timer on the windows service and code something like this in the timer tick event:
Process[] procs = Process.GetProcessesByName("you app name");
if (procs.Length == 0)
Process.Start("your app filename");
if you really cant do anything about the crash problem i would recommend a try-catch instead of a watcher. (Dont forget to re-throw handled major exceptions)
[STAThread]
static void Main()
{
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
catch(Exception ex)
{
//log the exception here
Application.Restart();
}
}
Since you say that you use a Windows Forms application you cannot use a Windows Service for that, since a Windows Service is not allowed to have a GUI.
What I would do it that I would create an invisible "watchdog" application which monitors the process and automatically restarts it when it crashes.
Thanks you all, the solution I choose is : in the main program I add an exception events (UnhandledExceptionEventHandler & ThreadExceptionEventHandler see above) in these events I restart the program (also putting log & email to trace errors). And for the reboot problem I add registry key in [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run] with my application path to be sure that my application will be restarted after the windows reboot ;)
You can put a try catch block around the code that is most likely causing the crash. Then write the exception message to a log file. You can also set a debug point in the catch block to see other details like call stack, etc.
currently I’m creating 2 applications (app A and B) for Windows Mobile 5.0 and using Compact Framework 2.0. App A is the main application and B is the sub application.
Below is the flow:
Start app A.
App A will start app B.
App B will do some process.
App B will kill app A.
App B will patch/upgrade app A. (ala update manager)
App B will restart app A.
App B will exit.
Now I’m stuck in killing app A. I did tried using OpenNETCF ProcessEntry Kill() function. When calling Kill(), it made the device crash.
I did tried using the SendMessage(hWnd, WM_CLOSE, 0, 0) funct where WM_CLOSE will have the ProcessEntry.ProcessID value and I didn’t assigned any value to hWnd variable. But it didn’t terminate app A. Did I assign the wrong value?
I also did tried using
Process.GetProcessById(processEntry.ProcessID).CloseMainWindow()
, but failed as GetProcessById only accepts int32 value. Note that processEntry.ProcessID value is larger than int32 value and GetProcessByName() is not supported in Compact Framework.
Could you help me in killing app A through app B?
Thanks.
You may try native code, using the TerminateProcess function:
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
success = TerminateProcess(processHandle, 0);
The above code is from a Task Manager at Code Project.
However if you are writing the code for both the applications, it will be better if you designed a communication mechanism between the two applications. In this way you will send a message from app B to app A and app A will kill itself.
Stormenet, I hardcoded the application's name. Then I generate an object to get all the available process using OpenNETCF.ToolHelp.ProcessEntry[ ] = ProcessEntry.GetProcesses();
then in a foreach loop, if the ProcessEntry object eg: processEntry.ExeFile matches with the "applicationName", i shall use processEntry.Kill().
I think you can get the OpenNETCF.ToolHelp dll from the OpenNETCF site.
Note that if the application you are trying to kill is holding open ports or other system resources then it might hang on exiting. Ensure everything is effectively disposed when the form closes.
This can be acheived by putting stuff in the:
public void Dispose(bool disposing)
{
}
block of code in the designer of your main form, or if you've chosen a less Windows Form centric architecture then just run your dispose calls following Application.Run(new YourForm()) and it will execute after the application has closed.
If you're feeling really lazy then just setup some destructors (otherwise known as finalizers ~) but be careful about navigating through relationships between managed objects at "destruct" time if you do this as there is no guarantee as to which order objects will be destroyed.
ctacke, I think app A crashes due to some of the running threads are not closed properly or still running at the background as app A will run multiple threads during app B executing the Kill( ) function.
If I use the SendMessage(hWnd, WM_CLOSE, 0, 0) function, it will not crash the device (which is a good thing)... it only closes the form. (app A contains multiple forms eg: frmLogin and frmMainMenu). hmmm maybe I need to point hWnd to the right form...
Now I'm taking a different route.
After downloading the patch and put it in a temp folder, I'll do a soft reset using OpenNETCF.WindowsCE.PowerManagement.SoftReset().
App B will be launched upon startup, then it will scan the temp folder and replace app A with the new version.