Good day to all!
I copy a method with use of Mono.Cecil, and have faced the following problem:
My function for copying is simple (it's for example):
public static bool Ping()
{
MessageBox.Show("Ping");
try
{
MessageBox.Show("status");
}
catch (Exception exception)
{
MessageBox.Show("Exception ");
return false;
}
return true;
}
It's work not problem. But if I do:
MessageBox.Show("Exception " + exception.Message);
I have the trouble: when execution reaches the function call, it's generate "Unhandled Exception" and clr finishes work. I can't even see MessageBox.Show("Ping")!
I copy try/catch blocks so:
foreach (ExceptionHandler exh in SourceMethod.Body.ExceptionHandlers)
{
var ex = new ExceptionHandler(exh.HandlerType)
{
TryStart = exh.TryStart,
TryEnd = exh.TryEnd,
HandlerStart = exh.TryEnd,
HandlerEnd = exh.HandlerEnd,
CatchType = Assembly.MainModule.Import(typeof(Exception)),
HandlerType = exh.HandlerType,
FilterStart = exh.FilterStart
};
target.Body.ExceptionHandlers.Add(ex);
}
And I think my problem is here:
CatchType = Assembly.MainModule.Import(typeof(Exception)),
But I do not know how to make this properly
I tryed:
CatchType = exh.CatchType
But unfortunate.
How to solve this situation? Have any ideas?
Most likely you are generating invalid IL and the runtime is detecting that and not even starting to run your program (whence you don't see the ping).
You can check that (on Windows at least) by running:
peverify path-to-your-assembly
That being said, you can see a full example here: https://cecilifier.me/?gistid=fd87051cdca0860916a171c419a30f80
I am developing in C# for the Motorola device "MC67" and I have having issues with initialising the scanner.
The code I am using seems to be generic as I have found similar examples all over the Internet; for reference here is the code that is causing me problems:
/// <summary>
/// Initialize the reader.
/// </summary>
///
public override bool InitReader()
{
Logger.Instance.Debug("InitReader");
bool result = false;
// Logger.Instance.AddToDebuggerLog("Symbol.InitReader");
// If reader is already present then fail initialize
if (this._MyReader != null)
{
return false;
}
try
{
// Create new reader, first available reader will be used.
this._MyReader = new Symbol.Barcode.Reader();
// Create reader data
this._MyReaderData = new Symbol.Barcode.ReaderData(
Symbol.Barcode.ReaderDataTypes.Text,
Symbol.Barcode.ReaderDataLengths.MaximumLabel);
// Enable reader, with wait cursor
this._MyReader.Actions.Enable();
if ((GetDeviceType() != DeviceTypes.SymbolMC3070) && (GetDeviceType() != DeviceTypes.SymbolMC3090BT))
{
this._MyReader.Parameters.Feedback.Success.BeepTime = 0;
}
else
{
this._MyReader.Parameters.Feedback.Success.BeepTime = 50;
}
SetScannerDecoderTypeToUseWithScanSys();
result = true;
}
catch (Exception ex)
{
// Something has gone wrong Initializing barcode reader etc
// Log Exception
Logger.Instance.Exception("InitReader", ex);
// Ensure reader is Disposed
if (_MyReader != null)
{
try
{
_MyReader.Dispose();
}
catch
{
// Just incase something goes wrong
Logger.Instance.Error("Error Disposing MyReader in InitReader Exception");
}
_MyReader = null;
}
// Ensure ReaderData is Disposed
if (_MyReaderData != null)
{
try
{
_MyReaderData.Dispose();
}
catch
{
// Just incase something goes wrong
Logger.Instance.Error("Error Disposing MyReaderData in InitReader Exception");
}
_MyReaderData = null;
}
// null the EventHandler
_MyEventHandler = null;
}
return result;
}
My problem is that when the above method is called, the following line produces an exception error:
this._MyReader.Actions.Enable();
The exception is "OperationFailureException" and the error message mentions "Get all supported attributes failed : E_SCN_INVALIDIOCTRL"
Now the strange thing is that I am able to actually use the scanner on the device correctly, so I can scan barcodes and read the data even with this exception but the fact that it is happening concerns me so I am trying to prevent it.
Does anyone have any idea why I am getting the exception or any suggestions of things I can try?
This is a "handled" exception in the Symbol library. Just turn off the breakpoint for thrown exception-- Ctrl-Alt-E, in the row "Common Language Runtime Exceptions" uncheck the box under "Thrown". Unfortunately if you're trying to debug an exception that isn't working correctly, you just gotta keep pressing play every time this exception comes up.
I haven't found a way to make it stop throwing the exception though... I'd really like to be able to turn off whatever feature is failing.
I'm working on writing my own FTPDownload class and an encountering an issue after having changed some things around that I'm trying to address.
The code I'll paste below effectively starts a download and runs through it for some time, pulling full arrays of data in each iteration of the 'main' loop. What I can say for sure is that for small files ( for instance a meeting agenda in html ) get copied quickly and seemingly completely - however something is still quite off.
As we speak I'm downloading a 1.05 gig file, and my download status control is showing me 325 Megs complete - I can attest to the fact that this much data has been collected over the stream BUT, this is where things get weird... So far only 548 KB has been written to my output file.
The following method is doing the collecting, counting, and writing of the data - and before my recent changes it was performing rather well, with the exception of some performance issues I was intending to resolve by turn this into an extension of another series of classes.
class DownloadThread : StreamReader
{
protected override void Cycle()
{
if (this.IsComplete)
{
this.FireEvent("OnComplete", new Event(this, "DownloadThread has confirmed completion of the targetted download."));
this.Stop();
return;
}
else if ((this._InputSource = this.GetResponseStream(this.RemotePath)) == null)
{
this.FireEvent("OnException",new Event(this,"DownloadThread could not execute. A Response Stream could not be retrieved from the Input Source '" + this.RemotePath + "'."));
this.Stop();
return;
}
else
{
try
{
this._StartTime = DateTime.Now;
Byte[] Bytes = new Byte[4096];
while ((this.BytesLastRead = this.Read(Bytes, 0, 4096)) > 0)
{
this.LocalStream.Write(Bytes, 0, DataMetrics.Length(Bytes));
this.LocalStream.Flush();
this.BytesSinceLast += this.BytesLastRead;
this.TotalRead += this.BytesLastRead;
this.TriggerProgress();
continue;
}
return;
}
catch (Exception e)
{
this.FireEvent("OnException", new Event(this, "An exception was encountered while reading data for the download." + Environment.NewLine + e.Message + Environment.NewLine + e.StackTrace));
return;
}
}
}
protected override Stream GetResponseStream(string RemotePath)
{
this.Request = (FtpWebRequest)FtpWebRequest.Create(this.RemotePath);
if (this.Credentials != null)
this.Request.Credentials = this.Credentials;
this.Response = (FtpWebResponse)this.Request.GetResponse();
Stream ResponseStream = this.Response.GetResponseStream();
return ResponseStream;
}
}
Something of note - before anyone jumps to conclusions - is that this 'cycle' method is automatically run inside of a loop in its own thread; and will recur every 'ThreadDelay' milliseconds ( assuming it returns ).
The 'LocalStream' variable in this class is as follows:
protected Stream _LocalStream = null;
protected Stream LocalStream
{
get
{
if (this.LocalFile == null)
return null;
else if (this._LocalStream == null)
{
if (!this.LocalDirectory.Exists)
this.LocalDirectory.Create();
this._LocalStream = this.LocalFile.OpenWrite();
return this.LocalStream;
}
else
return this._LocalStream;
}
}
I've considered that this could cause some conflicts - and ensuring some thread safety is on my to-do list, but I'm not encountering any issues in this field at the moment - I just assumed someone might want to take a glance.
Per the 'DownloadThread.Read' method - since I'm sure someone will be curious... This is inherited from my own 'StreamReader' class; again inherited from my 'InputReader' class. Affiliated fields included below.
protected Object _InputSource = null;
public Object InputSource
{
get
{
return this._InputSource;
}
}
public Stream InputStream
{
get
{
if (this.InputSource == null)
return null;
else
{
try
{
return (Stream)this.InputSource;
}
catch (Exception)
{
return null;
}
}
}
}
public override double Read(byte[] buffer, int offset, int count)
{
try
{
return this.InputStream.Read(buffer, offset, count);
}
catch (Exception e)
{
this.Stop();
this.FireEvent("OnException", new Events.Event(this, "An exception was encountered while reading from the InputStream." + Environment.NewLine + e.Message + Environment.NewLine + e.StackTrace));
return 0;
}
}
Now - to reiterate - my issue here is that for some reason the data I am receiving is not being pushed out to the file properly. I'm just about to finish the ~1 gig download as I am finishing typing this, and thus far no exceptions have been thrown and the stream has not 'fallen apart' - but my output file is only 17 megs.
After waiting another 30 seconds to allow this download to finish, my 1.05 gig file has turned into an 18 meg file; but I see no particular reason why the above code shouldn't handle this properly.
Anyone's advice would be great.
I think the problem might be in this line of code:
this.LocalStream.Write(Bytes, 0, DataMetrics.Length(Bytes));
I assume that your DataMetrics.Length() method returns the wrong number of bytes, thus I suggest you to try :
this.LocalStream.Write(Bytes, 0, this.BytesLastRead);
instead.
Something of note - before anyone jumps to conclusions - is that this
'cycle' method is automatically run inside of a loop in its own
thread; and will recur every 'ThreadDelay' milliseconds ( assuming it
returns ).
My first guess is that the OS is discarding data on the network card since it isn't actively being dequeued, which is why you're getting 17mb instead of 1gb.
I have VS2012 professional and would very much like my finely honed tests to run at the end of a build.
I thought I could do by writing an addin quite simply. So I have this in a c# addin.
public void OnConnection(object app, ext_ConnectMode cM, object aI, ref Array cust) {
_applicationObject = (DTE2)app;
_addInInstance = (AddIn)aI;
if (_applicationObject != null) {
_bldevents = _applicationObject.Events.BuildEvents;
_bldevents.OnBuildDone += _bldevents_OnBuildDone;
}
}
void _bldevents_OnBuildDone(vsBuildScope Scope, vsBuildAction Action) {
try {
_applicationObject.ExecuteCommand("TestExplorer.RunAllTests");
} catch(Exception e) {
string d = " + " + e.HResult;
Clipboard.SetText(e.Message + " ~ " + e.HResult);
MessageBox.Show(e.Message);
}
}
However when I do a build I get the error Error HRESULT E_FAIL has been returned from a call to a COM component. ~ -2147467259
ExecuteCommand work on stuff like File.NewFile run TestExplorer.RunAllTests in the command window with no problems.
Is there some setup that needs doing or have ms somehow stymied the behaviour because they want me to bankrupt myself and get the ultimate version ;)
Any thoughts?
It looks like TestExplorer.RunAllTests performs build first, your _bldevents_OnBuildDone is called again, TestExplorer.RunAllTests is called again and second time it throws the exception.
You can add the IsCommandAvailable check to prevent this recursion:
if (IsCommandAvailable("TestExplorer.RunAllTests"))
_applicationObject.ExecuteCommand("TestExplorer.RunAllTests");
bool IsCommandAvailable(string command)
{
Commands2 commands = (Commands2)(_applicationObject.Commands);
if (commands == null)
return false;
Command dte_command = commands.Item(command, 0);
if (dte_command == null)
return false;
return dte_command.IsAvailable;
}
I have a web service method I am calling which is 3rd party and outside of my domain. For some reason every now and again the web service fails with a gateway timeout. Its intermittent and a call to it directly after a failed attempt can succeed.
Now I am left with a coding dilemma, I have code that should do the trick, but the code looks like amateur hour, as you'll see below.
Is this really bad code, or acceptable given the usage? If its not acceptable, how can I improve it?
Please try hard to keep a straight face while looking at it.
try
{
MDO = OperationsWebService.MessageDownload(MI);
}
catch
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
}
catch
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
}
catch
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
}
catch
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
}
catch (Exception ex)
{
// 5 retries, ok now log and deal with the error.
}
}
}
}
}
You can do it in a loop.
Exception firstEx = null;
for(int i=0; i<5; i++)
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
firstEx = null;
break;
}
catch(Exception ex)
{
if (firstEx == null)
{
firstEx = ex;
}
Thread.Sleep(100 * (i + 1));
}
}
if (firstEx != null)
{
throw new Exception("WebService call failed after 5 retries.", firstEx);
}
Here's another way you might try:
// Easier to change if you decide that 5 retries isn't right for you
Exception exceptionKeeper = null;
for (int i = 0; i < MAX_RETRIES; ++i)
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
break; // correct point from Joe - thanks.
}
catch (Exception ex)
{
exceptionKeeper = ex;
// 5 retries, ok now log and deal with the error.
}
}
I think it documents the intent better. It's less code as well; easier to maintain.
All of the answers so far assume that the reaction to any exception should be to retry the operation. This is a good assumption right up until it's a false assumption. You could easily be retrying an operation that is damaging your system, all because you didn't check the exception type.
You should almost never use a bare "catch", nor "catch (Exception ex). Catch a more-specific exception - one you know you can safely recover from.
Try a loop, with some kind of limit:
int retryCount = 5;
var done = false;
Exception error = null;
while (!done && retryCount > 0)
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
done = true;
}
catch (Exception ex)
{
error = ex;
}
if (done)
break;
retryCount--;
}
You should use recursion (or a loop), and should only retry if you got the error you expected.
For example:
static void TryExecute<TException>(Action method, Func<TException, bool> retryFilter, int maxRetries) where TException : Exception {
try {
method();
} catch(TException ex) {
if (maxRetries > 0 && retryFilter(ex))
TryExecute(method, retryFilter, maxRetries - 1);
else
throw;
}
}
EDIT: With a loop:
static void TryExecute<TException>(Action method, Func<TException, bool> retryFilter, int maxRetries) where TException : Exception {
while (true) {
try {
method();
return;
} catch(TException ex) {
if (maxRetries > 0 && retryFilter(ex))
maxRetries--;
else
throw;
}
}
}
You can try to prevent future errors in retryFilter, perhaps by Thread.Sleep.
If the last retry fails, this will throw the last exception.
Here is some retry logic we are using. We don't do this a lot and I was going to pull it out and document it as our Retry Pattern/Standard. I had to wing it when I first wrote it so I came here to see if I was doing it correctly. Looks like I was. The version below is fully commented. See below that for an uncommented version.
#region Retry logic for SomeWebService.MyMethod
// The following code wraps SomeWebService.MyMethod in retry logic
// in an attempt to account for network failures, timeouts, etc.
// Declare the return object for SomeWebService.MyMethod outside of
// the following for{} and try{} code so that we have it afterwards.
MyMethodResult result = null;
// This logic will attempt to retry the call to SomeWebService.MyMethod
for (int retryAttempt = 1; retryAttempt <= Config.MaxRetryAttempts; retryAttempt++)
{
try
{
result = SomeWebService.MyMethod(myId);
// If we didn't get an exception, then that (most likely) means that the
// call was successful so we can break out of the retry logic.
break;
}
catch (Exception ex)
{
// Ideally we want to only catch and act on specific
// exceptions related to the failure. However, in our
// testing, we found that the exception could be any type
// (service unavailable, timeout, database failure, etc.)
// and attempting to trap every exception that was retryable
// was burdensome. It was easier to just retry everything
// regardless of the cause of the exception. YMMV. Do what is
// appropriate for your scenario.
// Need to check to see if there will be another retry attempt allowed.
if (retryAttempt < Config.MaxRetryAttempts)
{
// Log that we are re-trying
Logger.LogEvent(string.Format("Retry attempt #{0} for SomeWebService.MyMethod({1})", retryAttempt, myId);
// Put the thread to sleep. Rather than using a straight time value for each
// iteration, we are going to multiply the sleep time by how many times we
// have currently tried to call the method. This will allow for an easy way to
// cover a broader range of time without having to use higher retry counts or timeouts.
// For example, if MaxRetryAttempts = 10 and RetrySleepSeconds = 60, the coverage will
// be as follows:
// - Retry #1 - Sleep for 1 minute
// - Retry #2 - Sleep for 2 minutes (covering three minutes total)
// - Retry #10 - Sleep for 10 minutes (and will have covered almost an hour of downtime)
Thread.Sleep(retryAttempt * Config.RetrySleepSeconds * 1000);
}
else
{
// If we made it here, we have tried to call the method several
// times without any luck. Time to give up and move on.
// Moving on could either mean:
// A) Logging the exception and moving on to the next item.
Logger.LogError(string.Format("Max Retry Attempts Exceeded for SomeWebService.MyMethod({0})", MyId), ex);
// B) Throwing the exception for the program to deal with.
throw new Exception(string.Format("Max Retry Attempts Exceeded for SomeWebService.MyMethod({0})", myId), ex);
// Or both. Your code, your call.
}
}
}
#endregion
I like Samuel Neff's example of using an exception variable to see if it completely failed or not. That would have made some of the evaluations in my logic a little simpler. I could go either way. Not sure that either way has a significant advantage over the other. However, at this point in time, I'm not going to change how we do it. The important thing is to document what you are doing and why so that some idiot doesn't come through behind you and muck with everything.
Just for kicks though, to get a better idea if the code is any shorter or cleaner one way or the other, I pulled out all the comments. They came out exactly the same number of lines. I went ahead and compiled the two versions and ran them through Reflector Code Metrics and got the following:
Metric: Inside-Catch / Outside-For
CodeSize: 197 / 185
CyclomaticComplexity: 3 / 3
Instructions: 79 / 80
Locals: 6 / 7
Final exception logic inside the catch (22 lines):
MyMethodResult result = null;
for (int retryAttempt = 1; retryAttempt <= Config.MaxRetryAttempts; retryAttempt++)
{
try
{
result = SomeWebService.MyMethod(myId);
break;
}
catch (Exception ex)
{
if (retryAttempt < Config.MaxRetryAttempts)
{
Logger.LogEvent(string.Format("Retry attempt #{0} for SomeWebService.MyMethod({1})", retryAttempt, myId);
Thread.Sleep(retryAttempt * Config.RetrySleepSeconds * 1000);
}
else
{
Logger.LogError(string.Format("Max Retry Attempts Exceeded for SomeWebService.MyMethod({0})", MyId), ex);
throw new Exception(string.Format("Max Retry Attempts Exceeded for SomeWebService.MyMethod({0})", myId), ex);
}
}
}
Final exception logic after the for-loop (22 lines):
MyMethodResult result = null;
Exception retryException = null;
for (int retryAttempt = 1; retryAttempt <= Config.MaxRetryAttempts; retryAttempt++)
{
try
{
result = SomeWebService.MyMethod(myId);
retryException = null;
break;
}
catch (Exception ex)
{
retryException = ex;
Logger.LogEvent(string.Format("Retry attempt #{0} for SomeWebService.MyMethod({1})", retryAttempt, myId);
Thread.Sleep(retryAttempt * Config.RetrySleepSeconds * 1000);
}
}
if (retryException != null)
{
Logger.LogError(string.Format("Max Retry Attempts Exceeded for SomeWebService.MyMethod({0})", MyId), ex);
throw new Exception(string.Format("Max Retry Attempts Exceeded for SomeWebService.MyMethod({0})", myId), ex);
}
I'm using the following generic method for a retry scenario. I especially want to draw attention to the PreserveStackTrace method which helps to preserve the full call stack trace, because (as I learned the hard way) neither throw or throw ex yields the complete call stack trace information.
public static void RetryBeforeThrow<T>(Action action, int retries, int timeout) where T : Exception
{
int tries = 1;
do
{
try
{
action();
return;
}
catch (T ex)
{
if (retries <= 0)
{
PreserveStackTrace(ex);
throw;
}
Thread.Sleep(timeout);
}
}
while (tries++ < retries);
}
/// <summary>
/// Sets a flag on an <see cref="T:System.Exception"/> so that all the stack trace information is preserved
/// when the exception is re-thrown.
/// </summary>
/// <remarks>This is useful because "throw" removes information, such as the original stack frame.</remarks>
/// <see href="http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx"/>
public static void PreserveStackTrace(Exception ex)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(ex, null);
}
As everyone else has pointed out the correct approach is to wrap your try/catch inside some loop with a MAX_RETRY of some sort.
You might also consider adding a timeout between each loop iteration. Otherwise you're likely to burn through your retry counter before the transient issue has had a chance to resolve itself.
It seems you have the answers you need, but I thought I'd post this link, What is an Action Policy?, that I found to provide a much more elegant solution. Lokad has some rather labyrinthine implementations, but the guy's logic is pretty solid, and the end code you'd end up writing is pretty and simple.
int cnt=0;
bool cont = true;
while (cont)
{
try
{
MDO = OperationsWebService.MessageDownload(MI);
cont = false;
}
catch (Exception ex)
{
++cnt;
if (cnt == 5)
{
// 5 retries, ok now log and deal with the error.
cont = false;
}
}
}
UPDATED : Fixed code based on comments.