Assembly.LoadFile() and crash - c#

I use Assembly.LoadFile(string path) to load assembly to C# program. It works perfectly on my PC and two notebooks but... when I tried to send this app to my friend it crashed just after this call without any exceptions. We use same versions of .NET Framework, everything must be fine. I cant understand what happens. No exceptions, no errors, just "silent" return.
I also tried to use LoadFrom but nothing changed.
I use absolute path for dll files
public LoadedType[] LoadFrom(string path)
{
Assembly assembly = Assembly.LoadFile(path);
}
and calling method is
Loader loader = new Loader();
string[] paths = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.TopDirectoryOnly);
List<string> corrupted = new List<string>();
foreach (string path in paths)
{
try
{
LoadedType[] loadedTypes = loader.LoadFrom(path);
MessageBox.Show("loaded");
if (loadedTypes.Length == 0)
{
continue;
}
foreach (LoadedType loadedT in loadedTypes)
{
AvailableTypes.Add(loadedT);
}
}
catch (ReflectionTypeLoadException)
{
corrupted.Add(Path.GetFileName(path));
}
}
MessageBox does not appear.
Could somebody explain me whats wrong and why this code works on three PCs and does not work on another two PCs with the same Framework version?

using the code above you can not know if is there an exception or not, because you catch just exception of type ReflectionTypeLoadException, add another catch(Exception ex).
Check that string[] paths is not empty.
check that these assemblies are not used by another process.
check that you have access to read these assemblies.

You have to consider other types of possible exceptions as well:
try
{
// Ignore assemblies we can't load. They could be native, etc...
Assembly.LoadFrom(assemblyFile);
}
catch (Win32Exception) { }
catch (ArgumentException) { }
catch (FileNotFoundException) { }
catch (PathTooLongException) { }
catch (BadImageFormatException) { }
catch (SecurityException) { }

Related

How to skip files that are in use by another process during programmatic deletion?

I am trying to program a Windows service that automatically deletes the file from a specific folder. But I encountered an error:
Cannot access the file. The file is currently in use by another process/program.
I tried to do the following, but still get the same error.
string[] files = Directory.GetFiles(#"C:\Users\ASIM\AppData\Local\Temp");
// string[] directories = Directory.GetDirectories(#"C:\Users\ASIM\AppData\Local\Temp", "p*", SearchOption.TopDirectoryOnly);
if (files != null || files.Length != 0)
{
{
foreach (string f in files)
{
try
{
File.Delete(f);
}
finally { }
}
}
}
so how to skip deleting a file if it is in use?
There is no point checking if the file is deletable before deleting it because there will be a small window of opportunity between your check and the delete, where another process will open the file. The best idea is to try and delete it and handle the exception if it occurrs.
Your try/finally should be try/catch with the appropriate exception:
try
{
File.Delete(f);
}
catch(IOException ex)
{
// Probably some logging here
}

MEF not listing plugins

Again the topic of MEF not loading plugins correctly..
First of all: I took the last 7 hours searching similar questions and trying to apply the solutions given there, but I couldn't find any solution that worked for me.
Here is the Situation: Main application using 3 classes
Main class with GUI ( Windows forms )
Export class with Interface IMain for the PLugIns being able to give messages to the main window
Import class that loads all available Plugins from a given Directory
All this worked like a charm for one directory, where all the Plugins were stored. Now my superiors wanted me to rework it, so that every Plugin gets its own subdirectory within the main plugin Directory. And that's were the trouble began. I tried modifying my Code to get this Task done but now all the Plugins are loaded into the Catalogs but are missing in the list, from where I can call them through the applications GUI.
Here the code snippet from my Import class:
public class ServiceTool
{
CompositionContainer ComContainer;
[ImportMany(typeof(Interfaces.IPlugIn))]
public List<Interfaces.IPlugIn> Liste = new List<Interfaces.IPlugIn>();
public ServiceTool()
{
ModuleSuchen();
MessageBox.Show(Liste.Count.ToString());
}
void ModuleSuchen()
{
var AggKatalog = new AggregateCatalog();
var Dlls = Directory.GetFiles("D:\\Automation\\TIA\\FER-ServiceTool\\PlugIns", "*.dll", SearchOption.AllDirectories);
foreach(var DllDatei in Dlls)
{
try
{
AggKatalog.Catalogs.Add(new AssemblyCatalog(Assembly.LoadFile(DllDatei)));
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
}
ComContainer = new CompositionContainer(AggKatalog);
try
{
this.ComContainer.ComposeParts(this);
}
catch (CompositionException ComEx)
{
var ComExceptions = ComEx.Errors;
foreach (var ComException in ComExceptions)
{
MessageBox.Show(ComException.ToString());
}
}
catch (ReflectionTypeLoadException RTLEx)
{
Exception[] Exceptions = RTLEx.LoaderExceptions;
foreach (Exception Ex in Exceptions)
{
MessageBox.Show(Ex.ToString());
}
}
}
}
Where is the problem loading the plugins from the subdirectories? I'm just a beginner in programming and I have absolutely no clue why it isn't working anymore..

Unauthorized Access Exception DirectoryInfo.GetFiles() method

I wrote a program (on Windows 7) that call the method DirectoryInfo.GetFiles(), and in the folder "documents and settings", I have the exception of UnauthorizedAccess.
I tried lots of solutions, like:
create a manifest with
`<requestedExecutionLevel level="highestAvailable" uiAccess="false" />`
and also with this
DirectorySecurity dSecurity = Directory.GetAccessControl(dir.FullName);
dSecurity.AddAccessRule(new FileSystemAccessRule("Luca", FileSystemRights.FullControl, AccessControlType.Allow));
Directory.SetAccessControl(dir.FullName, dSecurity);
What could be the issue?
First off, you should be using DirectoryInfo.EnumerateFiles(...) instead of GetFiles(...). EnumerateFiles(...) keeps you from having to get the entire list until you actually need to.
I ran into this issue a while back and found that I ended up needing to implement a replacement IEnumerable in order to be able to complete an enumeration over folders that I may only have selected access to.
You can see the result of my research in the following thread. DirectoryInfo.EnumerateFiles(...) causes UnauthorizedAccessException (and other exceptions)
Just a Quick Copy Paste because I just had the same Problem.
Adjust the Code to your needs (because I calculate the the size, counting all files and "save" all the Files I want to copy in a List).
After you got all files in your List you can start copy them or what ever you wanna do with the Files:
private double CalculateSize(string sourcePath, Progress state, List<FileInfo> filesToCopy)
{
int _fileCount = 0;
DirectoryInfo sourceDirectory = new DirectoryInfo(sourcePath);
FileInfo[] files = null;
try
{
files = sourceDirectory.GetFiles();
}
catch(UnauthorizedAccessException ex)
{
// DO SOME LOGGING-MAGIC IN HERE...
}
if (files != null)
{
foreach (FileInfo file in files)
{
fullSizeToCopy += file.Length;
filesToCopy.Add(file);
_fileCount++;
}
}
DirectoryInfo[] directories = null;
try
{
directories = sourceDirectory.GetDirectories();
}
catch(UnauthorizedAccessException ex)
{
// Do more logging Magic in here...
}
if (directories != null)
foreach (DirectoryInfo direcotry in directories)
{
CalculateSize(direcotry.FullName, state, filesToCopy);
}
state.FileCount = _fileCount;
return fullSizeToCopy;
}
Your best bet might be to put a try/catch block around the call and ignore any directories you don't have access to. Maybe not the best solution, but it would at least make your method get all the directories you do have access to. Something like this:
try
{
directory.GetFiles();
}
catch (UnauthorizedAccessException)
{
string logMsg = string.Format("Unable to access directory {0}", directory.FullName);
//Handle any desired logging here
}
Just like blow, use EnumerateDirectories rather than DirectoryInfo.getfiles
private void ScanEmptyDirs(string dir, ref int cnt, CancellationToken token)
{
if (String.IsNullOrEmpty(dir))
{
throw new ArgumentException("Starting directory is a null reference or an empty string: dir");
}
try
{
foreach (var d in Directory.EnumerateDirectories(dir))
{
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
ScanEmptyDirs(d, ref cnt, token);
}
EmptyJudge(dir, ref cnt);
}
catch (UnauthorizedAccessException) { }
}

What is the common way to throw exception if my exe file that i need to start does not exist on the machine

in my application i am start capinfos.exe that is part of Wireshark.
in the constructor i am check if Wireshark install on the machine:
private string _filePath = "";
public Capinfos(string capturePath)
{
if (Directory.Exists(#"C:\Program Files (x86)\Wireshark"))
{
_capInfos = #"C:\Program Files (x86)\Wireshark\capinfos.exe";
}
else if (Directory.Exists(#"C:\Program Files\Wireshark"))
{
_capInfos = #"C:\Program Files\Wireshark\capinfos.exe";
}
_filePath = capturePath;
}
what is the best way to do it and throw an exception if the file does not exist on the machine: please install Wireshark
private string _filePath = "";
public Capinfos(string capturePath) throws FileNotFoundException
{
if (Directory.Exists(#"C:\Program Files (x86)\Wireshark"))
{
_capInfos = #"C:\Program Files (x86)\Wireshark\capinfos.exe";
}
else if (Directory.Exists(#"C:\Program Files\Wireshark"))
{
_capInfos = #"C:\Program Files\Wireshark\capinfos.exe";
} else
{
throw new FileNotFoundException(#"Wireshark installation not found");
}
_filePath = capturePath;
}
You can then catch the exception by using this code:
try
{
Capinfos("path");
}
catch (FileNotFoundException ex)
{
Messagebox.Show("Please install wireshark.");
}
I don't have C# installed, this was written by hand. Hope it's fine!
Here's an excellent resource to learn on exceptions: http://msdn.microsoft.com/en-us/library/0yd65esw(v=vs.80).aspx
Something like:
throw new FileNotFoundException("Could not find " + _capInfos, _capInfos);
Not sure if this is what you want, but try to use a try-catch block. You could attempt to start the .exe in the try block and if it fails, throw a FileNotFoundException and create a popup box in the catch block that will alert the user of what they need to do.

Permission problem with bitmap.Save()

I have this simple code:
System.Drawing.Bitmap bm = bitmapSourceToBitmap(source);
try
{
bm.Save(#"C:\Seva\testeImagem.jpg");
}
catch (Exception ex)
{
}
This throws: Generic Error GDI+.
Anyway, I seached and people say that the problem is with permissions. How can I give permissions to it? Thanks
First find out under what credentials the code is running.
Then check (and, when needed, fix) the security/NTFS settings of the Seva folder.
Especially when this code is running from within a website or service the account will not have permissions to write to the folder.
instead of saving to C:\Seva\testeImagem.jpg why not try saving to
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"testeImagem.jpg");
You must ensure that the Seva folder exists under C:\ and ensure that the current user has permissions to write to\create this folder. Also, its considered bad practice to write to folders that the user doesn't own. If the user is Running As A Normal User (not an admin) failure to do so results in permission exceptions.
Could you test if the folder exists?
void BitmapCopy(System.Drawing.Bitmap source, string filename) {
if (!String.IsNullOrEmpty(filename) && (source != null)) {
string dirName = #"C:\Seva";
if (!System.IO.Directory.Exists(dirName)) {
dirName = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
string bmpFile = System.IO.Path.Combine(dirName, filename);
System.Drawing.Bitmap bm = bitmapSourceToBitmap(source);
try {
bm.Save(bmpFile);
} catch (ArgumentNullException ex) {
Console.WriteLine(ex.Message);
} catch (System.Runtime.InteropServices.ExternalException ex) {
Console.WriteLine(ex.Message);
}
}
}

Categories

Resources