WPF C# Check if needed files exist on app startup - c#

I want to check if .dll, .png and .exe files exist before first app windows launches, but problem is I cant no matter how I try it just throws error in event viewer, instead my message.
My IsResourceExist Method:
private static bool IsResourceExist(string fileName)
{
var process = Process.GetCurrentProcess();
string path = process.MainModule.FileName.Replace("\\" + process.ProcessName + ".exe", "");
try
{
if (!File.Exists(Path.Combine(path, fileName)))
{
MessageBox.Show("Unable to load " + fileName + " library\nReinstall application and try again", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
return true;
}
catch
{
return false;
}
}
Simple method nothing fancy, in normal situation(when file actually exist works fine)
private static bool CheckLibrarys()
{
if (!IsResourceExist("MyLib.dll")) return false;
//Other resources checking same way
return true;
}
This method checks all apps needed resources, also works on normal situation(when all files exist)
This I think very first code line called by app, works when files exist
public App()
{
if (!CheckLibrarys()) Environment.Exit(0);
}
When I delete MyLib.dll file in event viewer it throws:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException at
myapp.App.CheckLibrarys() at myapp.App..ctor() at
myapp.App.Main()
Like for real is this somekind of .Net Framework joke? What I'm missing here?
EDIT 1:
Same situation even with OnStartup override
protected override void OnStartup(StartupEventArgs e)
{
if (!CheckLibrarys()) Environment.Exit(0);
base.OnStartup(e);
}
EDIT 2 extending #bic answer and still app does not launch and does not throw any error that mylib is misssing
private static bool CheckLibrarys()
{
if (!IsResourceExist("MyLib.dll")) { return false; }
else
{
if (!MyLib.Init.ReturnOnlyTrue())
{
MessageBox.Show("Wrong loaded library, reinstall application and try again", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
//Other resources checking same way
return true;
}
In my MyLib Init class ReturnOnlyTrue() method look like this:
public static bool ReturnOnlyTrue()
{
return true;
}

If the dll is referenced in the project then it cannot be missing otherwise the project references cannot be resolved. If you remove it from the project references and simply load it at runtime then you shouldnt have this problem.
Here is a nice description of how the runtime resolves references. This is ultimately where the FileNotFound exception is coming from.
https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies
In order for you to capture the error when the application starts you can add error handling as follows.
namespace SO_Wpf
{
using System;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Threading;
public partial class App : Application
{
public App()
{
Current.DispatcherUnhandledException += this.AppDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += this.AppDomainUnhandledException;
}
private void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
if (e.Exception.GetType() == typeof(FileNotFoundException))
{
if (!CheckLibrarys())
{
Current.Shutdown();
}
}
else
{
MessageBox.Show(e.Exception.Message);
}
}
private void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject.GetType() == typeof(FileNotFoundException))
{
if (!CheckLibrarys())
{
Current.Shutdown();
}
}
else
{
MessageBox.Show(e.ExceptionObject.ToString());
}
}
private static bool CheckLibrarys()
{
if (!IsResourceExist("MyLib.dll"))
{
return false;
}
//Other resources checking same way
return true;
}
private static bool IsResourceExist(string fileName)
{
var process = Process.GetCurrentProcess();
var path = process.MainModule.FileName.Replace("\\" + process.ProcessName + ".exe", "");
try
{
if (!File.Exists(Path.Combine(path, fileName)))
{
MessageBox.Show("Unable to load " + fileName + " library\nReinstall application and try again", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
return true;
}
catch
{
return false;
}
}
}
}
e.Exception.Message will give you the message or you can change the output altogether by checking the error and if its FileNotFoundException etc. tell the user and exit.

You can override OnStartup method of App.xaml. In this you can add your custom logic.
Maybe exception is coming form somewhere else. You can add a global exception handler and can see from where it is coming form.
public partial class App : Application
{
public App()
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
MessageBox.Show(e.Exception.Message);
Environment.Exit(0);
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (!SomeCondition)
Application.Current.Shutdown();
}
}

Related

How can I activate the previously opened microsoft access instance of an app using C#?

I'm using this code to open an access database :
public partial class Start_Baseet : System.Windows.Forms.Form
{
string MyFile = Environment.CurrentDirectory + "\\Baseet.accde";
Microsoft.Office.Interop.Access.Application AccApp = new Microsoft.Office.Interop.Access.Application();
public Start_Baseet()
{
InitializeComponent();
}
public void OpenDb()
{
AccApp.Visible = true;
AccApp.OpenCurrentDatabase(MyFile, false, "017014a");
AccApp.RunCommand(AcCommand.acCmdAppMaximize);
// AccApp.Activate();
}
}
private void Start_Basset_Load(object sender, EventArgs e)
{
try
{
OpenDb();
}
catch
{
AccApp.Quit();
MessageBox.Show("Something is missing", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
finally
{
this.Close();
System.Windows.Forms.Application.Exit();
System.Windows.Forms.Application.ExitThread();
// Process.GetCurrentProcess().CloseMainWindow();
}
The problem is the MSACCESS process is piling up in the running processes so I tried this :
//var prc = Process.GetProcessesByName("MSACCESS.EXE*32");
var prc = Process.GetProcessesByName("Microsoft Access");
if (prc.Length > 0)
{
MessageBox.Show("Access Found");
SetForegroundWindow(prc[0].MainWindowHandle);
}
else
{
AccApp.Visible = true;
AccApp.OpenCurrentDatabase(MyFile, false, "017014a");
AccApp.RunCommand(AcCommand.acCmdAppMaximize);
// AccApp.Activate();
}
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
But still with every time I use the code another MSACCESS process starts.
How can I fix this ?
Other point if I ran my app second time it will open a new instance of the same database can I activate the database if it is opened otherwise open a new instance of it ?
Thanks
Try this. This should catch users closing out Access as well through error catching. I'm sure it can be improved on but, I don't get a bunch of MSAccess.exe in the background from this code I wrote a while ago.
public partial class Form1 : Form
{
Microsoft.Office.Interop.Access.Application accApp = new Microsoft.Office.Interop.Access.Application();
private bool isFormClosed = false;
public Form1()
{
InitializeComponent();
OpenMicrosoftAccessFile(#"FileName");
Thread t = new Thread(new ThreadStart(CheckIfMSAccessExeIsRunning));
t.Start();
}
/// <summary>
/// The User Closed Out Access Cleanup.
/// </summary>
public void CheckIfMSAccessExeIsRunning()
{
int secondsToWait = 5*1000;
while(!isFormClosed)
{
if (accApp != null &&
accApp.Visible == false)
CloseMicrosoftAccessFile();
Thread.Sleep(secondsToWait);
}
CloseMicrosoftAccessFile();
}
private bool OpenMicrosoftAccessFile(string accessFileName)
{
try
{
if (accApp != null &&
!accApp.Visible)
{
CloseMicrosoftAccessFile();
}
if (accApp == null)
{
accApp = new Microsoft.Office.Interop.Access.Application();
accApp.OpenCurrentDatabase(accessFileName);
accApp.Visible = true;
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine((ex.InnerException != null) ? ex.InnerException : "");
CloseMicrosoftAccessFile();
return false;
}
}
private void CloseMicrosoftAccessFile()
{
try
{
if (accApp != null)
{
accApp.CloseCurrentDatabase();
accApp.Quit();
}
}
catch (Exception ex)
{
//Good chance there never was an Access exe.
Console.WriteLine(ex.Message);
Console.WriteLine((ex.InnerException != null) ? ex.InnerException : "");
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(accApp);
accApp = null;
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
isFormClosed = true;
}
}
Also, if you still have processes running the Debugger or Visual Studio is probably holding onto it still. It would be good to test this from the release exe. If OpenMicrosoftAccessFile returns false you can try opening it up again but, this way ignores the error it caught.

Audio file not played on the call but on local system - Skype for Business (C#)

I have found some code HERE and modified the same to call a phone number using skype, play an audio file and then disconnect. However, there are two issues in this code.
Audio file which is being played can be heard on the local system
but NOT in the phone call (the person receiving the call is not able to hear the audio played).
The call is not getting disconnected after audio file finishes
playing.
using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Conversation;
using Microsoft.Lync.Model.Conversation.AudioVideo;
using Microsoft.Lync.Model.Device;
using Microsoft.Lync.Model.Extensibility;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
namespace LyncTest
{
public partial class frmCaller : Form
{
public frmCaller()
{
InitializeComponent();
}
private void btnCall_Click(object sender, EventArgs e)
{
//if this client is in UISuppressionMode...
if (client.InSuppressedMode && client.State == ClientState.Uninitialized)
{
//...need to initialize it
try
{
client.BeginInitialize(this.ClientInitialized, null);
}
catch (LyncClientException lyncClientException)
{
Console.WriteLine(lyncClientException);
}
catch (SystemException systemException)
{
if (LyncModelExceptionHelper.IsLyncException(systemException))
{
// Log the exception thrown by the Lync Model API.
Console.WriteLine("Error: " + systemException);
}
else
{
// Rethrow the SystemException which did not come from the Lync Model API.
throw;
}
}
}
else //not in UI Suppression, so the client was already initialized
{
//sign-in or contact selection
SignInToLync();
}
SendLyncCall("+6512345678", "Hello, I am calling regarding a pending change request");
}
LyncClient client = LyncClient.GetClient();
private void SignInToLync()
{
try
{
client.BeginSignIn("abc#contoso.com", "abc#contoso.com", "Pass#word99", HandleEndSignIn, null);
}
catch (LyncClientException lyncClientException)
{
Console.WriteLine(lyncClientException);
}
catch (SystemException systemException)
{
if (LyncModelExceptionHelper.IsLyncException(systemException))
{
// Log the exception thrown by the Lync Model API.
Console.WriteLine("Error: " + systemException);
}
else
{
// Rethrow the SystemException which did not come from the Lync Model API.
throw;
}
}
}
Automation _automation = LyncClient.GetAutomation();
ConversationWindow globalConv = null;
public void SendLyncCall(string numberToCall, string textToSpeech)
{
var targetContactUris = new List<string> { numberToCall }; //"tel:+4900000000"
_automation.BeginStartConversation(AutomationModalities.Audio, targetContactUris, null, StartConversationCallback, null);
while (this.globalConv == null)
{
Thread.Sleep(1);
}
if (globalConv != null)
{
//client.DeviceManager.EndPlayAudioFile(
// client.DeviceManager.BeginPlayAudioFile(#"C:\Temp\voice.wav", AudioPlayBackModes.AlertAndCommunication, false, AudioPlayed, null)
// );
}
}
private void StartConversationCallback(IAsyncResult asyncop)
{
// this is called once the dialing completes..
if (asyncop.IsCompleted == true)
{
ConversationWindow newConversationWindow = _automation.EndStartConversation(asyncop);
globalConv = newConversationWindow;
AVModality avModality = newConversationWindow.Conversation.Modalities[ModalityTypes.AudioVideo] as AVModality;
avModality.ModalityStateChanged += ConversationModalityStateChangedCallback;
}
}
/// <summary>
/// Called when the client in done initializing.
/// </summary>
/// <param name="result"></param>
private void ClientInitialized(IAsyncResult result)
{
//registers for conversation related events
//these events will occur when new conversations are created (incoming/outgoing) and removed
//client.ConversationManager.ConversationAdded += ConversationManager_ConversationAdded;
//client.ConversationManager.ConversationRemoved += ConversationManager_ConversationRemoved;
}
private void ConversationModalityStateChangedCallback(object sender, ModalityStateChangedEventArgs e)
{
AVModality avModality = sender as AVModality;
if (avModality != null)
{
switch (e.NewState)
{
case ModalityState.Disconnected:
avModality.ModalityStateChanged -= ConversationModalityStateChangedCallback;
break;
case ModalityState.Connected:
avModality.ModalityStateChanged -= ConversationModalityStateChangedCallback;
//foreach (char c in "SOS")
//{
// avModality.AudioChannel.BeginSendDtmf(c.ToString(), null, null);
// System.Threading.Thread.Sleep(500);
//}
client.DeviceManager.EndPlayAudioFile(client.DeviceManager.BeginPlayAudioFile(#"C:\Temp\voice.wav",
AudioPlayBackModes.Communication, false, AudioPlayed, null));
break;
case ModalityState.Invalid:
break;
case ModalityState.Notified:
break;
}
}
}
private void AudioPlayed(IAsyncResult audioPlayed)
{
if(audioPlayed.IsCompleted == true)
{
client.ConversationManager.Conversations[0].End();
}
}
private void HandleEndSignIn(IAsyncResult ar)
{
try
{
client.EndSignIn(ar);
}
catch (Exception e)
{
Console.Out.WriteLine(e);
}
}
private void frmCaller_FormClosing(object sender, FormClosingEventArgs e)
{
GC.Collect();
}
}
}
Any help would be appreciated. Thank you.
It was confirmed by Microsoft that this is not possible using client side code. I need to use UCMA and develop a server side solution for the same.

C# Form App - stop execution of all code from a helper method that resides in a helper class

I just learned how to pass arguments into methods, so I'm refactoring my code to make it cleaner. I have created a new "ValidateInput" class which holds a ValidateFinancialsInput method which I pass a string into. It then checks the string to see if it is correct, if it's not I want to show a messageBox, then stop execution of ALL of the code. If i use "return;", it just resumes execution of the Parent method. How do I stop execution of all of the code within the ValidateFinancialsInput method? I tried researching this for a while to no avail. Here is my code:
Class Parent
{
private void button2_Click(object sender, EventArgs e)
{ var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
vi.ValidateFinancialsInput(CompanyVar);
//the rest of my code for the application is here
//the rest ...
//the rest...
}
}
class ValidateInput
{
public void ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
MessageBox.Show("You have entered an invalid company.");
//what do I put here to stop all code execution?
}
}
}
You should try and use return values state intent to calling methods
Class Parent
{
private void button2_Click(object sender, EventArgs e)
{ var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
if(!vi.ValidateFinancialsInput(CompanyVar))
{
MessageBox.Show("You have entered an invalid company.");
return;
}
//the rest of my code for the application is here
//the rest ...
//the rest...
}
}
class ValidateInput
{
public bool ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
return false;
}
return true;
}
}
What I'm doing here is returning a true|false value to indicate whether the validation has passed, if it has not passed then I display the MessageBox, else it continues the execution of the "other" code.
Hope this helps
The simplest way is with an exception:
class Parent
{
private void button2_Click(object sender, EventArgs e)
{
try
{
var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
vi.ValidateFinancialsInput(CompanyVar);
//the rest of my code for the application is here
//the rest ...
//the rest...
}
catch (ValidationException ex)
{
MessageBox.Show(ex.Message);
}
}
}
class ValidationException : Exception
{
public ValidationException(string message) : base(message)
{
}
}
class ValidateInput
{
public void ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
throw new ValidationException("You have entered an invalid company.");
}
}
}
This will stop execution of ValidateFinancialsInput and in button2_Click move execution inside the catch (ValidationException ex) where you can decide what to do with the validation error
You have a class that it's whole purpose is to validate, So you could add a public method IsValidated
You could add much more with the class, for example have a list of all business rules it violates and return them through another method or property.
class ValidateInput
{
public bool IsValidated {get; private set}
public bool ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
this.IsValidated = validCompany.Contains(Co)
}
}
This class should only know about the validation process and should do nothing else.
You have a few options. It looks like you have buttons in your program so I would guess this is not a console application. If you want the application to completely stop you can use Application.Exit or check out Environment.Exit https://msdn.microsoft.com/en-us/library/system.environment.exit(v=vs.110).aspx
However, I would suggest using exceptions so you do not terminate your entire program:
try
{
var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
vi.ValidateFinancialsInput(CompanyVar);
//the rest of my code for the application is here
//the rest ...
//the rest...
}
catch (ValidationException ex)
{
MessageBox.Show(ex.Message);
}
}
public void ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
throw new ValidationException("You have entered an invalid company.");
}
}

Eventviewer doesn't show the event log from Application program

.Net4.0, Windows 7(64bit), C# Winform based application.
Here is the method writing event log. However, there isn't shown event log on MS Eventviewer. Do you have any idea ?
private static void WriteEventLogEntry(string message)
{
// Create an instance of EventLog
System.Diagnostics.EventLog eventLog = new System.Diagnostics.EventLog();
// Check if the event source exists. If not create it.
if (!System.Diagnostics.EventLog.SourceExists("TestProgram"))
{
System.Diagnostics.EventLog.CreateEventSource("TestProgram", "Application");
}
// Set the source name for writing log entries.
eventLog.Source = "TestProgram";
// Create an event ID to add to the event log
int eventID = 8;
// Write an entry to the event log.
eventLog.WriteEntry(message,
System.Diagnostics.EventLogEntryType.Information,
eventID);
// Close the Event Log
eventLog.Close();
}
}
EDIT:
I have changed the code below. I can see event log without running as administrator. I have one more question. There are two log such as "Log 1" and "Log 2". I can see "Log 1" on viewer. However, I can't see "Log 2". Do you have any idea ?
using System.Diagnostics;
namespace ImageDelegateSample
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MdiForm mainForm = null;
try
{
bool createdNew;
Mutex dup = new Mutex(true, "ImageDelegateSample", out createdNew);
if (createdNew)
{
// Log 1
WriteEventLogEntry("Loading", EventLogEntryType.Information);
mainForm = new MdiForm();
Application.Run(mainForm);
// Log 2
WriteEventLogEntry("Done Loading", EventLogEntryType.Information);
}
else
{
MessageBox.Show("already running.");
}
}
catch (Exception e)
{
// You probably want something a little more sophisticated than this
MessageBox.Show(e.Message, "An exception occurred:", MessageBoxButtons.OK, MessageBoxIcon.Error);
HandleError(e);
System.Environment.Exit(0);
}
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
HandleError(e.Exception);
}
internal static void HandleError(Exception e)
{
string message = e.Message + "\n\n";
if (e.InnerException != null)
message += "Inner exception:\n" + e.InnerException.Message + "\n\n";
message += e.StackTrace;
MessageBox.Show(message, "An error has occurred:");
}
private static readonly string EventLogName = "Application";
private static readonly string EventLogSource = "ImageDelegateSample.exe";
private static void WriteEventLogEntry(string message, EventLogEntryType type)
{
// In the only function that does something
if (!EventLog.Exists(EventLogName))
{
EventLog.CreateEventSource(EventLogSource, EventLogName);
return;
}
else
{
// This doesn't write anything
EventLog.WriteEntry(EventLogSource,
message,
type);
}
}
}
}

Handling fatal error in a Windows Service

I created a windows service and installer that watches a collection of files for changes and copies any file that changes to a destination directory specified in the WatchlistConfig.xml file.
I have a couple issues with the service:
1. It has stopped running on one occasion. (unacceptable)
2. We sometimes have to attempt to start the service several times before it "takes".
I believe issue #1 is probably due to not handling fatal errors in the application. I found a bit of code that I tried to incorporate into the Main() method, but is written for a console app (Application is not a recognized class) and thus is commented out for now. Any idea which is the right class for implementing this in a service?
Issue #2 is most likely a timeout I'm guessing. The watchlist is currently comprised of 9 different files on different machines on the network. Connecting to these sources is not immediate (not all on a single domain). Is there a way to set a different timeout value for service startup?
Here's the relevant code. Additional classes on request.
Thanks in advance.
Edit: mistakenly posted the Main() from the test harness (console) which I use to debug. I've left it in place and add the Program class from the WinSvc Project
//Console Test harness
class Program
{
[STAThread]
static void Main(string[] args)
{
//AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
//Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
//Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
TimedWatchList twl = new TimedWatchList(new PSU_Config(Helpers.GetConfigFile()));
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
HandleException((Exception)e.ExceptionObject);
}
static void HandleException(Exception e)
{
//Handle/Log Exception Here
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
Logger.Loggit(e.Exception.Message);
}
}
//Actual Service
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Psu()
};
ServiceBase.Run(ServicesToRun);
}
}
public partial class Psu : ServiceBase
{
public Psu()
{
InitializeComponent();
TimedWatchList twl = new TimedWatchList(new PSU_Config(Helpers.GetConfigFile()));
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
public class TimedWatchList
{
public static PSU_Config Config { get; set; }
List<WatchFile> WatchList = new List<WatchFile>();
public TimedWatchList(PSU_Config config)
{
Config = config;
if (Config.PrintDebugMsgs) Logger.Loggit("Attempting to create TimedWatchList object");
WatchList = WatchListFactory.GetWatchList(Helpers.GetWatchListFile());
if (Config.PrintDebugMsgs) Logger.Loggit("TimedWatchList created");
Timer _timer = new Timer();
_timer.Interval += Config.Interval;
_timer.Enabled = true;
// register OnTimedEvent() to fire on each "tick"
_timer.Elapsed += OnTimedEvent;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
foreach (WatchFile file in WatchList)
{
file.PostOnUpdate();
}
}
}//TimedWatchList class
internal class WatchFile
// represents a file that is being watched
{
#region Props
public FileInfo SourceFile { get; set; }
public DirectoryInfo TargetPath { get; set; }
#endregion //Props
#region CTOR
public WatchFile() { }
public WatchFile(string fileName, string sourcePath, string destPath)
{
SourceFile = new FileInfo(Path.Combine(sourcePath, fileName));
TargetPath = new DirectoryInfo(destPath);
}
public WatchFile(FileInfo sourceFile, DirectoryInfo targetDirectory)
{
SourceFile = sourceFile;
TargetPath = targetDirectory;
}
#endregion //CTOR
public void PostOnUpdate()
{
//if (TimedWatchList.Config.PrintDebugMsgs) Logger.Loggit("WatchFile Post Event called for: " + SourceFile.Name);
//if (TimedWatchList.Config.PrintDebugMsgs) Logger.Loggit("Stored LastModified datetime: " + LastModified);
string targetPath = String.Format(#"{0}\{1}", TargetPath.FullName, SourceFile.Name);
{
try
{
//ensure directory exists
if (!Directory.Exists(TargetPath.FullName)) Directory.CreateDirectory(TargetPath.FullName);
//ensure file version is current
if (!File.Exists(targetPath) || (File.GetLastWriteTime(targetPath) != File.GetLastWriteTime(SourceFile.FullName)))
{
Logger.Loggit(String.Empty);
Logger.Loggit("Attempting to copy: " + SourceFile + " (" + File.GetLastWriteTime(SourceFile.FullName) + ")");
SourceFile.CopyTo(targetPath, true);
Logger.Loggit("\tCopy posted.\tLastModified: " + File.GetLastWriteTime(targetPath));
}
}
catch (IOException ioex)
{
Logger.Loggit("Error: " + ioex.Message);
}
catch (Exception ex)
{
Logger.Loggit("Error: " + ex.Message);
}
}
}
}// WatchFile class
There's really no need to guess; as a service you should be logging your errors to the system event log. Set a top level handler (as you've done), but don't expect to be able to handle it.
If the error was unhandled you're not going to be able to do anything about it there. Log it and exit. Catch the errors you can handle as soon as possible, test and design your code to not break otherwise.
You can set your service to restart automatically after a crash, but that should be a last resort. Bust out your debugger and figure out exactly where the errors are occurring and why. I see a lot of "it's probably [something]" and "it may be [something else]" statements here. Again, there is no good reason to guess; you have tools at your disposal which will help you figure out exactly what is going on.
You might want to simply wrap your function in a try / catch block to see what you might find.
try
{
MainAppFunctionality();
}
catch (Exception e)
{
//Not sure what you are going to do here, it's probably too late
}
I suggest you log to the Windows Event Log at various points in your application as a start so you can start to narrow down the location of the error.
I'm also not sure why you are using Console.Read() from a Windows Service context. As of Vista, there isn't a way for the service to interact with the desktop.

Categories

Resources