I have written a plugin system inspired from NotePad.NET, this plugin system read all DLL File in given folder and load them at runtime if they match my Interface using reflection. code is below
foreach (string file in System.IO.Directory.GetFiles(dir + "\\plugins\\", "*.dll", System.IO.SearchOption.AllDirectories))
if (file.EndsWith(".dll"))
{
Assembly dll = Assembly.LoadFrom(file);
foreach (Type t in dll.GetTypes())
{
try
{
log.WriteLine("Trying to match " + t.BaseType.FullName + " with " + typeof(Acoustical.PluginBase.FileFormatBase).FullName + " and " + typeof(Acoustical.PluginBase.ReportBase).FullName);
if (t.BaseType.FullName == typeof(FileFormatBase).FullName)
{
log.WriteLine(" we compare for " + t.BaseType.FullName);
try
{
fileformatPlugin.Add((dynamic)Activator.CreateInstance(t));
}
catch (Exception ex)
{
log.WriteLine("Error in loading File Plugin ::" + ex.Message + "\r\n" + ex.StackTrace);
}
continue;
}
else if (t.BaseType.FullName == typeof(ReportBase).FullName)
{
log.WriteLine(" we compare for " + t.BaseType.FullName);
reportPlugin.Add((dynamic)Activator.CreateInstance(t));
continue;
}
}
catch (Exception ex) {
log.WriteLine("Error in loading Plugin ::" + ex.Message + "\r\n" + ex.StackTrace);
}
}
dll = null;
}
Above code shows the part where Iterate over all found files in folder and than load them.
The above code works for me if I use the Windows Form or WCF interface application, it works on Windows service but doesn't guarantee that. It 60-70% of time on recompile doesn't load the plugin, then I after 10-15 attempts it sometime load plugins or sometime load only 1-2 plugins.
as you see I put Try catch on almost all lines to trace where the error is coming but no error is showing up. Since it is Windows SErvice it is not possible to debug when this code is written on ONStartup event.
I did see "We compare for" line in log, but when we try to see fileformatplugin got any element it's count remain 0 and error line is not there in log.
Any advice?
Related
I'm trying to get the grid extent types. its either gonna be "model" or "specificView"
with the code i have, I am able to get the Levels extent types but not the Grid extent types.
I've found these sources so far that have helped.
https://forum.dynamobim.com/t/switching-between-2d-and-3d-extent-levels-grid/10980/2
https://www.revitapidocs.com/2019/b3498ccf-1180-e0fd-502c-6c767f5b42cc.htm
https://disqus.com/home/discussion/revit-api-docs/setverticalextents_method_60/#edit-3254927585
This is the error im getting:
Exception thrown: 'Autodesk.Revit.Exceptions.ArgumentException' in RevitAPI.dll
Error StackTrace: at Autodesk.Revit.DB.DatumPlane.GetDatumExtentTypeInView(DatumEnds datumEnd, View view)
at ChangeGridExtentsTo2D.Command.Execute(ExternalCommandData commandData, String& message, ElementSet elements)
Error Data: System.Collections.ListDictionaryInternal
Error Source: RevitAPI
Error TargetSite: Autodesk.Revit.DB.DatumExtentType GetDatumExtentTypeInView(Autodesk.Revit.DB.DatumEnds, Autodesk.Revit.DB.View)
Here is my code so far:
FilteredElementCollector colGrids = new FilteredElementCollector(doc)
.WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_Grids)
.OfClass(typeof(Grid));
Debug.WriteLine("colGrids count: " + colGrids.GetElementCount()); //output is 3 which is correct
FilteredElementCollector colLevels = new FilteredElementCollector(doc)
.WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_Levels)
.OfClass(typeof(Level));
Debug.WriteLine("colLevels count: " + colLevels.GetElementCount()); // output is 7 which is correct
using (Transaction tx = new Transaction(doc))
{
try
{
tx.Start("Changing extends to 2d");
foreach (DatumPlane xLevels in colLevels)
{
//x.GetDatumExtentTypeInView(DatumEnds.End0, uidoc.ActiveView);
Debug.WriteLine(xLevels.Name + ": " + xLevels.GetDatumExtentTypeInView(DatumEnds.End0, uidoc.ActiveView));
Debug.WriteLine(xLevels.Name + ": " + xLevels.GetDatumExtentTypeInView(DatumEnds.End1, uidoc.ActiveView));
}
foreach (DatumPlane xGrids in colGrids)
{
Debug.WriteLine(xGrids.Name + ": " + xGrids.GetDatumExtentTypeInView(DatumEnds.End0, uidoc.ActiveView));
}
tx.Commit();
}
catch (Exception e)
{
Debug.WriteLine("Error StackTrace: " + e.StackTrace);
Debug.WriteLine("Error Data: " + e.Data);
Debug.WriteLine("Error Source: " + e.Source);
Debug.WriteLine("Error TargetSite: " + e.TargetSite);
tx.RollBack();
}
}
PS - I am new to VS IDE so if anyone has any tips on getting more verbose errors like:
what line the error occurs on
the variable or function it crashed at
or anything like that
That would be a huge help
I suggest you work through some simple getting started tutorial on debugging in Visual Studio IDE.
In the debugger, you can step through the code line by line, examine the values of all the variables, and much more, thereby answering all your requests above in one fell swoop.
I'm tasked with converting some older VB.net code to C#. Been slowly chipping away at the errors -went from about 100, down now to ~10. The first vb.net code that needs to be converted is:
Try
My.Computer.FileSystem.CopyFile(strFile, strExportPath + "\" + strFileName(0), FileIO.UIOption.OnlyErrorDialogs, FileIO.UICancelOption.DoNothing)
intFilesCopied += 1
My.Computer.FileSystem.MoveFile(strFile, _strPath + "Data\Backup\" + strFileName(0), FileIO.UIOption.OnlyErrorDialogs, FileIO.UICancelOption.DoNothing)
intFilesMoved += 1
Catch ex As Exception
My.Application.Log.WriteException(ex, TraceEventType.Error, "ExportDataToolStripMenuItem_Click")
End Try
My C# attempt is as follows:
try
{
File.Copy(strFile, strExportPath + #"\" + strFileName[0], UIOption.OnlyErrorDialogs,
FileIO.UICancelOption.DoNothing);
intFilesCopied += 1;
File.Move(strFile, _strPath + #"Data\Backup\" + strFileName[0],
UIOption.OnlyErrorDialogs, UICancelOption.DoNothing);
intFilesMoved += 1;
}
catch (Exception ex)
{
Application.Log.WriteException(ex, TraceEventType.Error, "ExportDataToolStripMenuItem_Click");
}
The next piece of VB.NET is the catch portion of the try-catch clauses.
My.Application.Log.WriteException(ex, TraceEventType.Error, "Could not write record to data file " + _strActiveFileName + Environment.NewLine + "Record Data: " + strRecordText);
And for the life of me, cannot find the C#-equivalent for this.
I've tried adding the Microsoft.VisualBasic dll/reference/namespace, but that doesn't work either. Tried to google the C#-equivalent, but couldn't find anything.
The next piece of VB.NET is the catch portion of the try-catch
clauses.
My.Application.Log.WriteException(ex, TraceEventType.Error, "Could not
write record to data file " + _strActiveFileName + Environment.NewLine
+ "Record Data: " + strRecordText);
And for the life of me, cannot find the C#-equivalent for this.
This can be converted by (with reference to Microsoft.VisualBasic.dll):
Microsoft.VisualBasic.ApplicationServices.ApplicationBase MyApplication = new Microsoft.VisualBasic.ApplicationServices.ApplicationBase();
then :
MyApplication.Log.WriteException(ex, TraceEventType.Error, "ExportDataToolStripMenuItem_Click");
And you can check the log file with :
System.Windows.Forms.MessageBox.Show(MyApplication.Log.DefaultFileLogWriter.FullLogFileName);
(just tested on Windows 10)
I am working on a .NET project using C# and I have the following doubt.
I have this method that write some error information into a .log file in a specific directory on my file system:
private static void writeErrorLog(string error)
{
string date = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string currDir = Directory.GetCurrentDirectory();
System.IO.File.AppendAllText(currDir + "\\FILE\\LOG\\Error_" + date + ".txt", error);
}
Ok this writeErrorLog() method will be called into some try catch block of my code, something like this:
try
{
currentAttachmentFileData = currentAttachmentFile.OpenBinary();
currentAttachementModel = new AttachmentModel(currentAttachment, currentAttachmentFileData);
attachmentsModelList.Add(currentAttachementModel);
}
catch (Exception ex)
{
//writeLog(2, String.Format("Unable to read the attachment, it may be corrupted {0} - {1}", fileName, ex.Message));
writeErrorLog("Errore inserimento attachment. Numero protocollo: " + recNumber
+ " Data protocollo: " + recDate
+ " Nome attachment: " + currentAttachmentFile
+ " INFO: " + ex.ToString() + " | " + ex.Message + " | " + ex.StackTrace);
}
It happens in different places of my code.
My doubt is: the file is the same, so it means that it will be added a new line to this file every time that an error occours.
Is it my reasnong correct?
The file name is string date = DateTime.Now.ToString("yyyyMMdd_HHmmss"); so it changes every second.
You should definitely add some abstraction here and hide writeErrorLog behind an interface. Behind the interface you could have your own implementation of writeErrorLog, but as others suggested I would strongly recommend using libs over your custom solution.
More on available libraries:
benchmarking-5-popular-net-logging-libraries
dotnetlogging.com
I have two apps. They share common features and addons. To be compatible, both are using same namespace structure. The apps loads addons as cs and compiles them to dll.
Same addons as cs works in both apps - loaded from the source and compiled to dll. On the next run, the apps load the dll files only.
I want to allow distribution of addons as dll only without the source code. The problem is that if a dll is compiled form the first app, it cannot be loaded from the second.
On the image below, I have "Adaptable MACD" compiled form each app separately.
When I try to load the first, from the second app, I receive the following error message:
"Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."
This is my code:
public void LoadDllIndicator(string dllPath, out string errorMessages)
{
errorMessages = string.Empty;
Assembly assembly = Assembly.LoadFrom(dllPath);
try
{
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (!typeof (IIndicator).IsAssignableFrom(type))
continue;
var newIndicator = Activator.CreateInstance(type) as Indicator;
if (newIndicator == null)
{
errorMessages = "Cannot load: " + dllPath;
return;
}
newIndicator.Initialize(SlotTypes.NotDefined);
newIndicator.CustomIndicator = true;
newIndicator.LoaddedFromDll = true;
IntegrateIndicator(dllPath, out errorMessages, newIndicator);
}
}
catch (Exception exception)
{
errorMessages = "ERROR: Loading '" + Path.GetFileName(dllPath) + "': " + exception.Message;
if (exception.InnerException != null && !string.IsNullOrEmpty(exception.InnerException.Message))
errorMessages += " " + exception.InnerException.Message;
}
}
How to make possible, dll compiled form one of the apps to work in the other?
So I have a C# console app that goes through a huge list of files and copies missing files to a remote location using a WebDAV mapped drive.
In essence, I'm not using a custom client, I'm using windows built-in client.
net use j: http://127.69.69.69 /user:testme pass /persistent:yes
Everything seems to work just fine (I've increased the file size limits on the IIS 7.0 server, etc. ) EXCEPT occasionally I get a "Delayed Write Failure" popup from the OS.
My problem is that my application does not bail/throw an exception on the File.Copy() Method on the client-- How might I detect this?
I guess it's not a huge deal, but part of me wonders why no exception is thrown. It appears to move onto the next file without logging an error. My script checks if the remote file size is the same and can replace a partial file on the next cycle.
Pretty simple code where it actually copies:
Log("\n copying " + lf.FullName);
try
{
if (!Directory.Exists(Path.Combine(remotePath, localDir.Name)))
Directory.CreateDirectory(Path.Combine(remotePath, localDir.Name));
}
catch (Exception e)
{
Log("Cannot create remote directory " + Path.Combine(remotePath, localDir.Name) + " " + e.Message , "error");
}
try
{
File.Copy(lf.FullName, Path.Combine(new string[] { remotePath, localDir.Name, lf.Name }), true);
}
catch (Exception e)
{
Log("Cannot copy file to " + Path.Combine(new string[] { remotePath, localDir.Name, lf.Name }) + " " + e.Message, "error");
}