I am getting this error:
ImageMagick.MagickResourceLimitErrorException: 'TooManyExceptions (exception processing is suspended) # error/exception.c/ThrowException/969'
On this line
using (MagickImageCollection tiffPageCollection = new MagickImageCollection())
{
tiffPageCollection.Read(tifName); // fails here.
}
The problem occurs because the 92 page tif has three errors like this on each page:
{"ASCII value for tag \"Copyright\" does not end in null byte. `TIFFFetchNormalTag' # warning/tiff.c/TIFFWarnings/1007"} ImageMagick.MagickException {ImageMagick.MagickCoderWarningException}
The number of warning errors is exceeded so that triggers TooManyExceptions errors.
This URL alludes to a solution:
http://www.imagemagick.org/discourse-server/viewtopic.php?t=33989
of adding this handler:
private void MagickNET_Log (object sender, LogEventArgs e)
{
// write to a single log file...
if ((RemoteImageMagickEventLogging & e.EventType) != LogEvents.None)
{
switch (e.EventType)
{
case LogEvents.Exception:
if (!e.Message.Contains ("TIFFWarnings"))
{
TriggerRemoteLoggingEvent (e.EventType,
EZLogger.LoggingLevel.Note1, e.Message);
}
break;
}
}
}
It also references that this exception was added to "ImageMagick.Net 7.4.5 Q8 AnyCPU" and did not happen on earlier versions. I am experiencing the problem on "ImageMagick.Net-Q16-AnyCPU v7.9.1" I updated to v7.10.0 and still had the same problem.
So, my questions are:
What versions of ImageMagick have and don't have this feature?
What are the steps to handing that handler to my code?
Is there a way to increase the maximum number of allowed warnings and I can just raise that limit to something so high that I will not hit it?
This issue has been fixed in Magick.NET 7.10.1.0: https://github.com/dlemstra/Magick.NET/releases/tag/7.10.1.0. The TooManyExceptions (exception processing is suspended) exception will no longer be thrown because this has been changed into a warning.
What versions of ImageMagick have and don't have this feature?
From the changelog, it was added as early as version 7.0.7-22. The body of work around this feature was in response to Google's OSS-fuzz project.
Is there a way to increase the maximum number of allowed warnings and I can just raise that limit to something so high that I will not hit it?
Not currently. The limit is hardcoded MagickCore/exception.c as ...
#define MaxExceptionList 64
But this is opensource, and a rather new feature. If you post an issue under 'Bugs' message board, you may be able to have the developers revise the limit, or allow some resource attribute under polices.xml to be controlled by the user. Presenting a real world test-case also helps, and tiff file with 64+ warnings should require some level of scrutiny.
Related
First of all ...
I tried posting this question earlier, but didn't explain it properly, and it was just confusing people. So I deleted the old question and tried a complete re-write, with a completely different title.
And ... I've searched stack overflow, and there are related questions, but none of them answer this question. I would be very grateful for any help you could provide. The supplied answers on other stackoverflow questions don't solve the problem of compiler and dotfuscator changing the line numbers. I'm looking for a way to implement the VB solution below in a C# program
My test system:
-Windows 10
-VS2022
-C#
-.Net Framework 4.8
-WinForms
What I'm Trying to Accomplish:
We are trying to build an error reporting system in C# that will give the exact line number that throws an exception. It needs to work with the compiled release .exe file. It is easy to do this in VB.net, but I can't find a way to accomplish this in C#.
Here is how to get an exact location in VB.net:
10: On Error Resume Next
20: Err.Raise(60000)
' Returns 20.
30: MsgBox(Erl())
The above code is from the Microsoft documentation here, showing usage of the ErrObject.Erl property, which was carried over from VB6. I used that system to build an extensive error reporting capability back when I was a VB6 programmer. It was an extremely useful tool that allowed any end-user in the world to report detailed error information back to the Mother Ship (the developers). This allowed us to rapidly home in on the problem and do the necessary re-factoring.
Of course it is better to eliminate errors to begin with, but when shareware is being downloaded by a million users all over the world, on many different versions of Windows, with varying locality settings, there are going to be errors that don't pop up in beta testing.
Unfortunately, I'm not able to find any way in C# to add number tags at the beginning of code lines, like the 10:, 20:, 30: above. Those are not Visual Studio line numbers ... they are typed in by the programmer to label each line in the code as described in the Microsoft documentation here. I've also not found any way to get the Microsoft ErrObject working in C#, like it does in VB.net.
Here is what I've tried in C#:
Here is my test code:
private void button2_Click(object sender, EventArgs e)
{
try
{
int x = 10; // This is line 38 in the editor window
int y = 0;
int z = 0;
z = x / y; // This is line 41,throwing the exception (divide by zero)
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
The Problem:
The ex.ToString() always returns the first line of the try block (in this example, line 38), instead of returning the actual line that triggered the error (line 41). This is ALSO TRUE OF the other answers on stack overflow, involving StackTrace, etc.
My Question:
Is there a way in C# to get the exact code line that throws the exception, like we can do in VB.net? If so, how?
One Possible Solution
One person suggested it might be possible to increment an integer variable on every other line of code, then report that integer value with the exception. I appreciate that kind of creative thinking, but I'm hoping there will be other ideas as well. Thanks!!
Thanks!!
Any help you could provide would be sincerely appreciated.
.
Ok ... we have the solution. You can run the compiler optimized, then run the Dotfuscator, and still get the exact error line number reported by the System.Exception Class. And ... there are no PDB files to help hackers crack your software.
Just set Debugging information to "Embedded."
Instructions for .Net Framework 4.8 instructions (Current as of VS2022):
(Step-by-Step to help new people)
Right-Click on your project and select "Properties"
In the left panel of the Properties window, select "Build"
Make sure that "Optimize Code" is selected (or not ... it's your choice)
Click the "Advanced" button, at the bottom-right of the screen
In the Advanced window, about 2/3 down, you'll see "Debugging information:" with a drop-down box.
Select "Embedded" and click "OK". The Advanced window disappears.
Instructions for .Net 6.0 (Current as of VS2022):
Right-Click on your project and select "Properties"
In the left panel of the Properties window, select "Build > General"
Under "Optimize Code", select "Release" (or not ... it's your choice)
Directly under "Optimize Code, you'll see "Debug Symbols" with a drop-down box.
Select "Embedded in DLL/EXE".
Close the Project Properties window.
Now ... rebuild (REbuild!) the release version with compiler optimized and debug set to embedded. Then run the dotfuscator, and your dotfuscated Release .exe will still get the accurate line number from the following code:
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
Obviously, this example is bare-bones, but you can build a robust error-reporting system that includes this and other features built into the System.Exception Class (Microsoft documentation here). We intend to build a website that will receive the information from the desktop app, and store it into a DB as part of a basic service ticket system.
Performance Tests:
I set up a small app that runs a loop of simple math operations 200,000,000 repetitions, timing the results (average of 3 runs). Here are the results:
Compiler Optimized - Debugging information set to "None" - Dotfuscated:
Time: 4116.3 ms (no line number reported)
Compiler Optimized - Debugging information set to "Embedded" - Dotfuscated
Time: 4115.9 ms (exact line number reported!)
Hope this helps anybody who is interested in creating an error-reporting system for their software.
Best of luck to all!!
Try this:
try
{
int x = 10; // This is line 38 in the editor window
int y = 0;
int z = 0;
z = x / y; // This is line 41,throwing the exception (divide by zero)
}
catch (Exception ex)
{
int CodeLine = new System.Diagnostics.StackTrace(ex, true).GetFrame(0).GetFileLineNumber();
MessageBox.Show(CodeLine.ToString());
}
Getting the original line number from obfuscated code seems like a product feature that should be handled by the obfuscator. Alternatively, you could pre-process your the original .cs files, and the pre-processed files get passed to the obfuscator. For example, your input code is:
34 private void button2_Click(object sender, EventArgs e)
35 {
36 try
37 {
38 int x = 10; // This is line 38 in the editor window
39 int y = 0;
40 int z = 0;
41 z = x / y; // This is line 41,throwing the exception (divide by zero)
42 }
43 catch (System.Exception ex)
44 {
45 MessageBox.Show(ex.ToString());
46 }
47 }
Your pre-process takes the above code and inserts line numbers. Then this generated code is passed to the obfuscator.
private void button2_Click(object sender, EventArgs e)
{
int lineNumber = 36;
try
{
lineNumber = 38;
int x = 10; // This is line 38 in the editor window
lineNumber = 39;
int y = 0;
lineNumber = 40;
int z = 0;
lineNumber = 41;
z = x / y; // This is line 41,throwing the exception (divide by zero)
lineNumber = 42;
}
catch (System.Exception ex)
{
// decide how to handle Exceptions. Possibly wrap the exception in a new custom exception
// or write the line number and file to a log file
throw new LineNumberWrapperException(lineNumber, ex);
}
}
UPDATE
try
{
//Attemps string conversion for each of the point's variables
int.TryParse(row[0], out q.pointID); //Checks for existence of data on the line...
float.TryParse(row[1], out q.xValue); //Input x-value
float.TryParse(row[2], out q.yValue); //Input y-value
float.TryParse(row[3], out q.zValue); //Input z-value
float.TryParse(row[4], out q.tempValue); //Input temp-value
}
catch (IndexOutOfRangeException)
{
Debug.Log("File out of range...");
errorLogScript.errorCode = 1100;
SceneManager.LoadScene(4);
}
This is the current code that I have but it seems to be freezing whenever I attempt to transfer the scene to the errorScreen. That being said, I am not getting an error but my code is freezing and Unity crashes whenever I attempt to test this bug.
Does anyone have any ideas on how I can fix this?
OP
I am currently working on an application in Unity and I wanted to create a bug/crash-reporting system that shows the user a unique error code upon a failure to load. Being that this specific application will be used by many people with many different skill-sets, I wanted to break it as much as I can before I release it later this year. In doing so I wanted to make a quick reference that the user will be able to look up in the documentation.
The following code demostrates what happens if the user-input filepath does not exist...
if (File.Exists(dropDownMenuScript.dataFileName + ".csv"))
{
Debug.Log("File found, loading..."); //Debugs success to console
}
else
{
Debug.Log("File not found, aborting..."); //Debugs the problem to console
errorLogScript.errorCode = 1000; //Shows the code "E1000"
SceneManager.LoadScene(4); //Loads the error-screen which displays the code
}
I recently found another error that reads; "IndexOutOfRangeException" -- in this case this pertains to the parsing of the file, meaning it exists but it does not conform to the data format compatible with the program. I would like to create another error-log for this problem but I do know how to do this as it is a Unity Editor error.
I apologize if this isn't crystal-clear, but I will provide any context needed if you need it. Thanks!
Can't you use a try-catch block and specifically traps for IndexOutOfRangeException?
try
{
//Your code...
}
catch(IndexOutOfRangeException iore)
{
//Log here
}
I am facing issue with perforce api (.net), as i am unable to pull sync logs in real time.
- What am I trying to do
I am trying to pull real time logs as Sync is triggered using the
Perforce.P4.Client.SyncFiles() command. Similar to the P4V GUI Logs, which update when we try to sync any files.
- What is happening now
As the output is generated only after the command is done execution its not something intended for.
Also tried looking into Perforce.P4.P4Server.RunCommand() which does provide detailed report but only after the execution of the command.
Looked into this
Reason is -
I am trying to add a status update to the Tool i am working on which shows which Perforce file is currently being sync'd.
Please advise. Thanks in Advance.
-Bharath
In the C++ client API (which is what P4V is built on), the client receives an OutputInfo callback (or OutputStat in tagged mode) for each file as it begins syncing.
Looking over the .NET documentation I think the equivalents are the P4CallBacks.InfoResultsDelegate and P4CallBacks.TaggedOutputDelegate which handle events like P4Server.InfoResultsReceived etc.
I ended up with the same issue, and I struggled quite a bit to get it to work, so I will share the solution I found:
First, you should use the P4Server class instead of the Perforce.P4.Connection. They are two classes doing more or less the same thing, but when I tried using the P4.Connection.TaggedOutputReceived events, I simply got nothing back. So instead I tried with the P4Server.TaggedOutputReceived, and there, finally, I got the TaggedOutput just like I wanted.
So, here is a small example:
P4Server p4Server = new P4Server(cwdPath); //In my case I use P4Config, so no need to set user or to login, but you can do all that with the p4Server here.
p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent;
p4Server.ErrorReceived += P4ServerErrorReceived;
bool syncSuccess=false;
try
{
P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\...");
P4CommandResult rslt = syncCommand.Run();
syncSuccess=true;
//Here you can read the content of the P4CommandResult
//But it will only be accessible when the command is finished.
}
catch (P4Exception ex) //Will be caught only when the command has failed
{
Console.WriteLine("P4Command failed: " + ex.Message);
}
And the method to handle the error messages or the taggedOutput:
private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data)
{
Console.WriteLine("P4ServerErrorReceived:" + data);
}
private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj)
{
Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]); //Write the synced file name.
//Note that I used this only for a 'Sync' command, for other commands, I guess there might not be any Obj["clientFile"], so you should check for that.
}
logging exception
the code below allows to save the content of an exception in a text file. Here I'm getting only the decription of the error.
but it is not telling me where the exception occured, at which line.
Can anyone tell me how can I achive that so I can get even the line number where the exception occured?
#region WriteLogError
/// <summary>
/// Write an error Log in File
/// </summary>
/// <param name="errorMessage"></param>
public void WriteLogError(string errorMessage)
{
try
{
string path = "~/Error/" + DateTime.Today.ToString("dd-mm-yy") + ".txt";
if (!File.Exists(System.Web.HttpContext.Current.Server.MapPath(path)))
{
File.Create(System.Web.HttpContext.Current.Server.MapPath(path))
.Close();
}
using (StreamWriter w = File.AppendText(System.Web.HttpContext.Current.Server.MapPath(path)))
{
w.WriteLine("\r\nLog Entry : ");
w.WriteLine("{0}", DateTime.Now.ToString(CultureInfo.InvariantCulture));
string err = "Error in: " + System.Web.HttpContext.Current.Request.Url.ToString()
+ ". Error Message:" + errorMessage;
w.WriteLine(err);
w.WriteLine("__________________________");
w.Flush();
w.Close();
}
}
catch (Exception ex)
{
WriteLogError(ex.Message);
}
}
#endregion
I find that the easiest way to log exceptions in C# is to call the ToString() method:
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
This usually gives you all the information you need such as the error message and the stack trace, plus any extra exception specific context information. (however note that the stack trace will only show you source files and line numbers if you have your application compiled with debug information)
It is worth noting however that seeing a full stack trace can be fairly offputting for the user and so wherever possible you should try to handle exceptions and print out a more friendly error message.
On another note - you should replace your method WriteLogError with a fully featured logging framework (like Serilog) instead of trying to write your own.
Your logging method is not thread safe (your log file will probably end up with log messages being intermingled with each other) and also should definitely not call itself if you catch an exception - this will mean that any exceptions that occur whilst logging errors will probably cause a difficult to diagnose StackOverflow exception.
I could suggest how to fix those things, however you would be much better served just using a proper logging framework.
Just log ToString(). Not only will it give you the stack trace, but it'll also include the inner exceptions.
Also, when you deploy a release build of your code to a production environment for instance, don't forget to include the .pdb files in the release package. You need that file to get the line number of the code that excepted (see How much information do pdb files contain? (C# / .NET))
Your solution is pretty good. I went through the same phase
and eventually needed to log more and more (it will come...):
logging source location
callstack before exception (could be in really different place)
all internal exceptions in the same way
process id / thread id
time (or request ticks)
for web - url, http headers, client ip, cookies, web session content
some other critical variable values
loaded assemblies in memory
...
Preferably in the way that I clicked on the file link where the error occurred,
or clicked on a link in the callstack, and Visual Studio opened up at the appropriate location.
(Of course, all you need to do is *.PDB files, where the paths from the IL code
to your released source in C # are stored.)
So I finally started using this solution:
It exists as a Nuget package - Desharp.
It's for both application types - web and desktop.
See it's Desharp Github documentation. It has many configuration options.
try {
var myStrangeObj = new { /*... something really mysterious ...*/ };
throw new Exception("Something really baaaaad with my strange object :-)");
} catch (Exception ex) {
// store any rendered object in debug.html or debug.log file
Desharp.Debug.Log(myStrangeObj, Desharp.Level.DEBUG);
// store exception with all inner exceptions and everything else
// you need to know later in exceptions.html or exceptions.log file
Desharp.Debug.Log(ex);
}
It has HTML log formats, every exception in one line,
and from html page you can open in browser, you can click
on file link and go to Visual Studio - it's really addictive!
It's only necessary to install this Desharp editor opener.
See some demos here:
Web Basic App
Web MVC App
Console App
Try to check out any of those repos and log something by the way above.
then you can see logged results into ~/Logs directory. Mostly anything is configurable.
I am only answering for the ask, other people have already mentioned about the code already. If you want the line number to be included in your log you need to include the generated debug files (pdb) in your deployment to the server. If its just your Dev/Test region that is fine but I don't recommend using in production.
Please note that the exception class is serializable. This means that you could easily write the exception class to disk using the builtin XmlSerializer - or use a custom serializer to write to a txt file for example.
Logging to output can ofcourse be done by using ToString() instead of only reading the error message as mentioned in other answers.
Exception class
https://learn.microsoft.com/en-us/dotnet/api/system.exception?redirectedfrom=MSDN&view=netframework-4.7.2
Info about serialization, the act of converting an object to a file on disk and vice versa.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/
when i run this code :
CONADefinitions.CONAPI_FOLDER_INFO2 FolderInfo;
int iResult = 0;
IntPtr Buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CONADefinitions.CONAPI_FOLDER_INFO2)));
iResult = CONAFileSystem.CONAFindNextFolder(hFindHandle, Buffer);
while (iResult == PCCSErrors.CONA_OK )
{
FolderInfo = (CONADefinitions.CONAPI_FOLDER_INFO2)Marshal.PtrToStructure(Buffer,typeof(CONADefinitions.CONAPI_FOLDER_INFO2));
//......................... i got an error msg here as follows:
// Error Messege:
FatalExecutionEngineError was detected Message: The runtime has encountered a
fatal error. The address of the error was at 0x7a0ba769, on thread 0x1294. The
error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe
or non-verifiable portions of user code. Common sources of this bug include
user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
how to use CONADefinitions.CONAPI_FOLDER_INFO2, coz when i use CONADefinitions.CONAPI_FOLDER_INFO it only gives me the name and lable of the device
but when is use CONADefinitions.CONAPI_FOLDER_INFO2 it gives me freeSize and TotalSize
please help
I'm not sure what that error means but if you want to get the drive's size, you can use
DriveInfo di = new DriveInfo("f"); //Put your mobile drive name
long totalBytes = di.TotalSize;
long freeBytes = di.TotalFreeSpace;
It is correct that you get the exception when you try and convert the data in the buffer to a different type of structure than was originally created by CONAFileSystem.CONAFindNextFolder.
You are trying to force a data structure of type CONADefinitions.CONAPI_FOLDER_INFO into a structure of type CONADefinitions.CONAPI_FOLDER_INFO2. They almost certainly have different lengths and so on so its extremely unlikely this method would ever work.
From experience with C++ development on the Symbian OS, the pattern Nokia are likely to be using here is one where they have subsequently developed a newer version of the API and so have created a newer version of the CONADefinitions.CONAPI_FOLDER_INFO structure (i.e. CONADefinitions.CONAPI_FOLDER_INFO2).
Assuming this is correct there are 3 likelihoods:
1) There is an enum parameter to the first function which specifies which version of the output structure is to be created.
2) There is a new function which returns the new structure e.g. CONAFileSystem.CONAFindFirstFolder2, CONAFileSystem.CONAFindNextFolder2
3) Nokia have developed the new version internally but not yet released it publicly.