I am using a Prism UnityExtensions bootstrapper class to start my WPF application. How do I shutdown the application while the unityextensions bootstrapper is still running?
See my bootstrapper class below. The SomeClass object may throw a custom exception (fatal). If the custom exception is thrown, I need to close the application. I am using Application.Current.Shutdown() to shutdown the application.
However, the bootstrapper code continues running, and I get a "ResolutionFailedException was unhandled" exception error when setting the datacontext in the CreateShell() method. Obviously, the SomeClass method and interface were not registered with the container due to the catch block.
It appears that the bootstrapper code continues running after a call to Application.Current.Shutdown() was called. I need to stop the bootstrapper code immediately following the call to shutdown.
Any ideas how to shutdown the application without creating the ResolutionFailedException?
ResolutionFailedException exception details -->
Resolution of the dependency failed, type = "SomeClass", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, SomeClass, is an interface and cannot be constructed. Are you missing a type mapping?
public class AgentBootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
var eventRepository = new EventRepository();
Container.RegisterInstance(typeof(IEventRepository), eventRepository);
var dialog = new DialogService();
Container.RegisterInstance(typeof(IDialogService), dialog);
try
{
var someClass = new SomeClass();
Container.RegisterInstance(typeof(ISomeClass), SomeClass);
}
catch (ConfigurationErrorsException e)
{
dialog.ShowException(e.Message + " Application shutting down.");
**Application.Current.Shutdown();**
}
}
protected override System.Windows.DependencyObject CreateShell()
{
var main = new MainWindow
{
DataContext = new MainWindowViewModel(Container.Resolve<IEventRepository>(),
Container.Resolve<IDialogService>(),
Container.Resolve<ISomeClass>())
};
return main;
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)Shell;
Application.Current.MainWindow.Show();
}
}
This behaviour occurs, because you´re executing the OnStartup of your Application at this time. I suppose you do it like that:
protected override void OnStartup(StartupEventArgs e)
{
new AgentBootstrapper().Run();
}
The OnStartup has to be completed, before the App can shutdown, so the bootstrapper continues execution. You might throw another exception to get out of the Run():
... catch (ConfigurationErrorsException e)
{
dialog.ShowException(e.Message + " Application shutting down.");
throw new ApplicationException("shutdown");
}
And then catch it in the StartUp():
protected override void OnStartup(StartupEventArgs e)
{
try
{
new AgentBootstrapper().Run();
}
catch(ApplicationException)
{
this.Shutdown();
}
}
Related
I have developed a C# Windows service to get some datas from DB and process them in an infinite loop. The service was working fine with nothing but loop in it yesterday but today I have finished the development and tried to test it as a Windows service but it keep says Starting and when the green bar is complete it gives me "1053" error. I have checked if there are any logs and my service is inserting logs and even processing Datas but somehow I still get this error.
I have installed the service from my release folder. There is no error on Event Viewer regarding the service. And my service looks like below.
*UPDATE: When I check event viewer I see below messages in a sequence; "Session 1 started", "Ending Session 1" "Machine restart required". I have tried restarting but it didn't make any difference
Program.cs
static class Program
{
static void Main()
{
try
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new spService()
};
ServiceBase.Run(ServicesToRun);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
}
Service1.cs
public partial class spService: ServiceBase
{
public spService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
SpPushOperation spo = new SpPushOperation();
spo.StartSpPushOperation();
}
protected override void OnStop()
{
SpPushOperation spo = new SpPushOperation();
spo.StopSpPushOperation();
}
}
SpPushOperation.cs
class SpPushOperation
{
public readonly NLog.ILogger Logger = NLog.LogManager.GetCurrentClassLogger();
public void StartSpPushOperation()
{
try
{
Logger.Info("-------------");
Logger.Info("SpPushOperation Started..");
Logger.Info("-------------");
while(true)
{
//some process in here
}
}
catch(Exception e)
{
Logger.Info("!!!!!!!!!!!!!!");
Logger.Info("Error on getting StartSpPushOperation Error: " + e);
Logger.Info("!!!!!!!!!!!!!!");
}
}
}
Any help would be appreciated. Thanks.
Issue was caused due to using infinite loop in service. To fix this issue instead of using infinite loop start the service with a thread and run for every 60 seconds.
I can't close my WPF application because the NamedPipeClientStream endlessly runs. I tried using ConnectAsync, I tried disposing it, but no matter what it prevents the process from ending.
I use the pipe to listen for messages so it needs to run until the application quits.
This is my current attempt:
public MainWindow()
{
namedPipeClient = new(System.Configuration.ConfigurationManager.AppSettings["AppGUID"]!);
Thread PipeThread = new(() =>
{
while (true)
{
try
{
PipeReceive();
}
catch (TimeoutException) { }
catch (ObjectDisposedException) { break; }
}
});
PipeThread.Start();
}
// Called when window is closed
protected override void OnClosed(EventArgs e)
{
namedPipeClient.Close();
namedPipeClient.Dispose();
base.OnClosed(e);
}
private void PipeReceive()
{
namedPipeClient.Connect(1000);
if (namedPipeClient.IsConnected)
{
// Retrieve message
}
}
The issue didn't have anything to do with named pipes. I was under the impression it did because in Visual Studio's "Running Tasks" it showed a reference to the named pipe methods and listed them as active.
The real issue was the I had changed the application ShutdownMode to OnExplicitShutdown so even after the main window was closed the application would remain running unless the Shutdown() method is called. My fix was to override the OnClosed event.
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
System.Windows.Application.Current.Shutdown();
}
I created a windows service project with Visual Studio. This service should run in the background and poll data every X seconds. The polling is achieved with a timer and a tick event. So whenever the tick event is raised the service should do something.
Unfortunately the service closes itself because it does not wait for the timer to tick. The OnStart method gets executed and runs but after that the service closes itself.
I added a debug mode to my program file
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
#else
ServiceBase.Run(new RuntimeService());
#endif
}
and use this code for my service application
public partial class RuntimeService : ServiceBase
{
private const int BATCH_POLLING_INTERVAL = 3000;
private Timer batchPollingTimer;
public RuntimeService()
{
InitializeComponent();
}
public void RunDebugMode()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
try
{
// ...
batchPollingTimer = new Timer(BATCH_POLLING_INTERVAL);
batchPollingTimer.Elapsed += OnTimer;
batchPollingTimer.Enabled = true;
}
catch (Exception exception)
{
throw exception;
}
}
protected override void OnStop()
{
batchPollingTimer.Enabled = false;
try
{
// ...
}
catch (Exception exception)
{
throw exception;
}
}
private void OnTimer(object sender, ElapsedEventArgs e)
{
batchPollingTimer.Enabled = false;
// ...
batchPollingTimer.Enabled = true;
}
}
How can I run the service without closing it and waiting for the timer ticks? By "closing itself" I mean executing the Main method and ignoring the timer. Please let me know if you need more information.
It will only do this in debug mode, because there is nothing stopping it from ending. Ordinarily ServiceBase.Run will not return unless the service is shutting down. Add a sleep for a long time so that after your main thread has kicked off your timer, it will go to sleep rather than exiting the Main
Something like:
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
System.Threading.Thread.Sleep(TimeSpan.FromDays(1));
#else
ServiceBase.Run(new RuntimeService());
#endif
}
As an aside, consider putting your timer stop/start in a try/finally - at the moment if something happens in your OnTimer, your stopped timer will never restart and your service will cease doing anything (but may not crash entirely)
private void OnTimer(object sender, ElapsedEventArgs e)
{
try{
batchPollingTimer.Enabled = false;
// ...
} finally {
batchPollingTimer.Enabled = true;
}
}
}
I have a Prism WPF application which failed to load one of its modules when I deployed it (due to a database problem). On my development machine, I can see the relevant exceptions being thrown (and apparently caught and handled by Prism) in the Output window of Visual Studio.
I was able to solve the immediate problem by doing this:
public MyModuleViewConstructor()
{
try
{
// some startup work here
// ...
InitializeComponent();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "A System Error Occurred.");
}
}
Which surfaces the error in production so that I can take action on it. But I would still like to obtain the messages from any exceptions that are thrown during normal operations, So, in the spirit of Prism's way of doing things, I did this:
public class Logger : ILoggerFacade
{
public void Log(string message, Category category, Priority priority)
{
using (StreamWriter s = File.AppendText("Log.txt"))
{
s.WriteLine(string.Format("{0}-{1}: {2}", DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss.ffff"), priority.ToString(), message));
s.Close();
}
}
}
And registered it in the Bootstrapper:
class Bootstrapper : DryIocBootstrapper
{
private readonly Logger _logger = new Logger();
protected override ILoggerFacade CreateLogger()
{
return _logger;
}
}
This works splendidly for normal log entries such as debug logging. But it still does not log any exceptions thrown within my application.
How do I get Prism to log thrown exceptions in my application?
When navigating, all exceptions that occur during view and/or view model creation are caught by the region manager. Those are not logged by default (although this would be a cool feature).
You can, however, be notified about the exception and log it yourself or react otherwise.
To do that, navigate through one of the IRegionManager.RequestNavigate( ..., Action<NavigationResult> navigationCallback ) overloads. The navigationCallback will be passed a result object that contains any exception in the NavigationResult.Error property.
The Prism logging mechanism is used mostly to log messages related to Prism events.
To use it for your events you could create and extension method like this
public static class LoggerExtensions
{
public static void Warn(this ILoggerFacade loger, string message)
{
using (StreamWriter s = File.AppendText("Log.txt"))
{
s.WriteLine(string.Format(" {0}-{1}: {2}", DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss.ffff"), Category.Warn, message));
s.Close();
}
}
}
And to use it inside your code, you could do the following
var logger = _container.Resolve<ILoggerFacade>(); //If you use IoC
LoggerExtensions.Warn(logger, "Some exception...");
But it still does not log any exceptions thrown within my application
I would suggest to add Dispatcher.UnhandledException inside App.xaml.cs, so where ever there is any exception who is not handled, it will finish there.
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
}
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//Your code
}
}
Update #2
I have created a small example, where to button click will throw DivideByZeroException. The Prism logging mechanism isn't aware of this exception at all. The only solution would be to use extension method, extend Exception class or other libraries.
I just don't see any other solution.
public partial class ViewA : UserControl
{
ILoggerFacade logger;
public ViewA(ILoggerFacade _logger)
{
InitializeComponent();
logger = _logger;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
try
{
var val = 0;
var result = 1500 / val;
}
catch (Exception ex)
{
LoggerExtensions.Warn(logger, ex.Message);
}
}
}
I have created a custom event log and would like all my applications to write to the same event log. As you can see below in the image attached, DistributedCOM and Svc Ctrl Mgr are 2 sources writing to the same event log System.
Similarly, I have 2 services that I want to write to the same eventLog.
I tried doing that by creating one event log and passing different source names from the 2 Windows Services that I have created. But I find only one Service writing to the log while the other doesn't.
Below is the class library that I created for Event Log.
public class EventLogger
{
private EventLog eventLog1 = new System.Diagnostics.EventLog();
public EventLogger(string logSource)
{
if (!System.Diagnostics.EventLog.SourceExists(logSource))
{
System.Diagnostics.EventLog.CreateEventSource(logSource, "SampleLog");
}
eventLog1.Source = logSource;
eventLog1.Log = "SampleLog";
}
public void WriteLog(string message)
{
eventLog1.WriteEntry(message);
}
Created 1st Windows Service
public partial class Service1 : ServiceBase
{
private EventLogger.EventLogger eventLog;
public Service1()
{
InitializeComponent();
eventLog = new EventLogger.EventLogger("WinService1");
}
protected override void OnStart(string[] args)
{
try
{
eventLog.WriteLog("Service started in 1st");
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.ToString());
}
}
protected override void OnStop()
{
eventLog.WriteLog("Service stopped");
}
}
Created the 2nd windows Service as well, as above.
public partial class Service2 : ServiceBase
{
private EventLogger.EventLogger eventLog;
public Service2()
{
InitializeComponent();
eventLog = new EventLogger.EventLogger("WinService2");
}
protected override void OnStart(string[] args)
{
try
{
eventLog.WriteLog("Service started in 2nd");
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.ToString());
}
}
protected override void OnStop()
{
eventLog.WriteLog("Service stopped");
}
}
Service1 doesn't seem to log anything, whereas, I can see the logs for Service2. I might be doing a lot of things incorrectly here. Please help me in finding a solution to this. Also, if this can be achieved by using log4Net then solutions with respect to that are welcome as well. thanks in advance.
EDIT: Also, when I try to stop the services, Service 1 fails to stop and throws an error. Image given below.
EDIT 2: Just changed the constructor of the EventLogger class as below and then it worked!! I am not entirely sure if this was the actual cause for the improper functioning. And I'm not quite sure if it had anything to do with the setting of the Log property either. Any light thrown on this by any one of you would be appreciated. I would like to understand better as to what exactly happened here. Thanks.
string logName = "NewLog";
public EventLogger(string logSource)
{
if (!System.Diagnostics.EventLog.SourceExists(logSource))
{
System.Diagnostics.EventLog.CreateEventSource(logSource, logName);
}
eventLog1.Source = logSource;
}