I wrote a little WinForms app which reads settings from a file located in %APPDATA% on startup. If the settings file doesn't exist or is invalid, the program uses hard-coded defaults. And it all works fine, until I copy my app to another PC via network share or try to start it from a network share directly. Then the program silently terminates, and I keep getting a FileNotFoundException in the event log although I have a try/catch block and although the file even exists!
It feels like it's some sort of permission thing since it only happens when the app was distributed over a network share, even after I copied everything to a local folder (without any complaints from Windows). However, the program manages to create the folder for the settings file and crashes when trying to read the file afterwards.
When I copy the program to another PC using a USB drive, everything works fine. But that's a workaround I don't like, and it doesn't actually solve the problem.
So why does it throw a FileNotFoundException no matter whether or not the file exists? And why doesn't the exception get caught but terminates the program instead? How can I fix this?
The event log shows something like this:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
at MyNamespace.Settings.Load()
at MyNamespace.Program.Main()
And here is some code snippets:
Program.cs
public static Settings Settings { get; private set; }
static void Main()
{
Settings = Settings.Load();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
Settings.cs
public static readonly string FileName;
static Settings()
{
string directoryName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyProgram");
FileName = Path.Combine(directoryName, "Settings.json");
Directory.CreateDirectory(directoryName);
}
public static Settings Load()
{
try
{
string json = File.ReadAllText(FileName);
return JsonConvert.DeserializeObject<Settings>(json);
}
catch
{
return new Settings();
}
}
All PCs are running on Windows 10 v1909. I'm using VS2019 Enterprise 16.6.5.
Well, this is kind of embarassing, but I thought I post the answer anyway.
I was just missing a referenced library, in this case Newtonsoft.Json.dll which was first used and therefore tried to be loaded during Settings.Load(). This caused the FileNotFoundException to be thrown and not be caught - because it wasn't my code throwing it.
When using network share distribution, I simply forgot to include this file for whatever reason. On the USB drive, I didn't. Thanks to Thomas Weller who pointed out that it could be a file other than my Settings.json, which I just didn't think about.
Related
For a Windows Store app: how can I detect if a StorageFile was renamed or deleted outside of my application while it is open in my app?
I have a Windows 10 UWP app running on the desktop. The app lets the user open and edit documents.
Things I've tried:
Checking DateModified:
I tried checking storageFile.GetBasicPropertiesAsync().DateModified, but even it I delete the file and empty the trash, the call returns successfully with the (old) DateModified. (I assume it uses an in-memory version and does not check the file on disk)
Re-Open the StorageFile:
I then tried to "re-open" the file using StorageFile.GetFileFromPathAsync(file.Path). This correctly threw a FileNotFoundException the first time.
However, later this failed with an Unauthorized access/permission denied exception. It kind of makes sense, because I need the user to pick the file in a FileOpenPicker to have my app get permission to use it.
Monitor the parent folder:
Did not get far with this one. I tried to use StorageFolder.CreateFileQuery(), but I can't access the parent folder form the StorageFile instance (again, it makes sense, because my app does not have permission to access the parent folder)
Found a nice and short way to check if file was deleted:
public async bool StorageFileExists(StorageFile file)
{
try
{
var stream = await StorageFile.OpenReadAsync();
stream.Dispose();
return true;
}
catch (FileNotFoundException e)
{
return false;
} //Other exceptions are not caught on purpose and should propagate
}
Even in a UWP App you can use System.IO.File.Exists(String).
https://msdn.microsoft.com/de-de/library/system.io.file.exists(v=vs.110).aspx
I have written a console application and a companion class library to export some data from a cloud service. The application is called by SQL Server Integration Services which relies on the exit code returned by the application to determine if it worked correctly or not.
Intermittently the application returns an exit code of -532462766 (0xE0434352) which is the generic error code for a .NET unhandled exception. I'm totally flummoxed as to why this is happening.
The log files generated by the applications do not show any issues and they look like everything has completed successfully.
There are no entries in the Application Event Viewer logs.
The application even has an unhandled exception handler:
AppDomain.CurrentDomain.UnhandledException += UnhandledErrorHandler;
...
private void UnhandledErrorHandler(object sender, UnhandledExceptionEventArgs e) {
logWriter.Write(e.ExceptionObject.ToString(), logLevel.Fatal);
logWriter.Write("Exiting now...", logLevel.Fatal);
Dispose();
}
I've even written a batch file to execute the application and log the exit code before passing it along to SSIS. The exit codes that SSIS are receiving are the ones that seem to be returned by the application. But I cannot see an unhandled exception happening anywhere.
The console application returns the exit code by defining Main() like so:
class Program {
static int Main(string[] args) {
...
return (Success) ? 0 : 1;
}
Because it is intermittent (and the data extraction can take a couple of hours) I can't just run it in Visual Studio and debug it. I have a suspicion it might be related to the fact that the application does run for such a long time but I can't seem to confirm that.
Is there anything else that can cause a .NET application to return that exit code? Am I missing something in my troubleshooting?
quick check: wrap your entire code inside a try catch block and save the exception in a log file.
static int Main(string[] args)
{
try
{
//your existing code....
}
catch(Exception Ex)
{
//write your log results here.
}
}
Check if you are using multiple app domains. I encountered this same issue when an exception X was thrown in AppDomain B and could not cross to AppDomain A because it was not serializable. See also best practices for exceptions (search for 'across app domains'):
When you create user-defined exceptions, you must ensure that the
metadata for the exceptions is available to code that is executing
remotely, including when exceptions occur across app domains. For
example, suppose App Domain A creates App Domain B, which executes
code that throws an exception. For App Domain A to properly catch and
handle the exception, it must be able to find the assembly that
contains the exception thrown by App Domain B. If App Domain B throws
an exception that is contained in an assembly under its application
base, but not under App Domain A's application base, App Domain A will
not be able to find the exception, and the common language runtime
will throw a FileNotFoundException exception. To avoid this situation,
you can deploy the assembly that contains the exception information in
two ways:
Put the assembly into a common application base shared by
both app domains.
or
If the domains do not share a common application base, sign the assembly that contains the exception information with a strong name
and deploy the assembly into the global assembly cache.
My console app checks for the presence of a file on a network drive and logs a message when it does not exist. Today I deployed my app to a QA machine and File.Exists() has been returning false for files that do exist. I am running the app via windows task scheduler. When I ran it from the command line it seems to work fine. But either way I don't trust it now. Has anyone seen this behavior or have any insight?:
Using System.IO;
private static void Main()
{
var fileName = #"x:\folder\file1.txt"; //be a network share
If (!File.Exists(fileName)
{
LogMessage("File is not on disk.");
}
else
{
LogMessage("File is on disk.");
}
}
I suspect that the drives are not mapped when running from task scheduler. Try a UNC path
var fileName = #"\\server\share\folder\file1.txt";
I have a really strange situation.
In our company we develop big web application which consist of several modules. Each module is divided in separate folders on server. There is one module which launches application mapped on users L:\app.exe disk.
My goal is update the invoking method which first will start the switcher.exe file INSIDE the module and after will start L:\app.exe as it was before.
The problem is that when i build this module on my local it works perfectly fine but when i downloading the content from my bin\Debugg on server-including swither.exe (say on Dev environment) the application fails to find "switcher.exe" in folder on server. It throws an exception which says {"The system cannot find the file specified"}.
The code behind is pretty simple:
private void LaunchSwitherExe()
{
string executionPath = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
MessageBox.Show(executionPath);
Process themeSwitchProc = new Process();
themeSwitchProc.StartInfo.FileName = "Switcher.exe";
themeSwitchProc.StartInfo.WorkingDirectory = executionPath;
themeSwitchProc.Start();
}
The messagebox shows(for test purposes) the path to swither.exe. And this path is absolutely correct. It has swither.exe inside.
Do you have any ideas?
---UPDATE---
The problem way in the string to the path. This:
string executionPath = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
Chould be changed to:
string exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Directory.SetCurrentDirectory(exeDir);
Thanks to all folks who answered and especially to "Rick S."
Have you considered it might be permissions issue? What process Id is the code running under and does it have access to that folder?
I also found this:
When the UseShellExecute property is false, gets or sets the working directory for the
process to be started. When UseShellExecute is true, gets or sets the directory that
contains the process to be started.
And maybe try this:
Defining a working directory for executing a program (C#)
Very odd that I am experiencing a occasional errors when calling the GetDirectories() method.
This started happening when our IT dept remotely moved some folders to my local machine. This error only occurs when navigating through these folders using C#.
Error Message: 'Access to the path 'C:\Users\XXXX\XXXXX is denied'
Code:
public static string[] GetDirectoryInfo(string path)
{
if (Directory.Exists(path))
{
//This call is failing on the new folder.
return Directory.GetDirectories(path);
}
return new string[0];
}
Not very complicated, correct?
Navigating with Windows Explorer, the folder isn't present.
In the CMD prompt I can change directory to this folder; following up with the DIR command I get the error 'File not found'.
I am guessing
the problem is a Win32 issue and something didn't get cleaned up when the folder was moved. I have no idea how to correct the issue, except for digging through decompiled System.IO classes; which I will do if I don't get a solution.
Your code is probably trying to access hidden folders that are not accessible to your account/role.
The easiest solution is to catch the UnauthorizedAccessException and just eat it, so it essentially skips the directory, like this:
public static string[] GetDirectoryInfo(string path)
{
if (Directory.Exists(path))
{
try
{
//This call is failing on the new folder.
return Directory.GetDirectories(path);
}
catch(UnauthorizedAccessException unAuthEx)
{
// Do nothing to eat exception
}
}
return new string[0];
}
This occurs when the software tries to access folders which have been restricted by the windows for security reasons like for example :
C:\Users\Default (This path is not accessible by your code)
Another reason would be that your application is trying to access folders which are not really folders like
My Music
My Pictures
If you are trying to read all the folders in a specific drive, then you can make some exception to handle these directories, another thing that MIGHT help you is to run your application as administrator.