Showing posts with label Exception. Show all posts
Showing posts with label Exception. Show all posts

Tuesday, August 15, 2023

Azure @ Enterprise - Configuring PnP.Framework SDK logs to trace file

Context

Environment - Microsoft Azure Virtual Machines

Technology - .Net Framework 4.8, SharePoint Online

Functionality - Interacting with SharePoint Online via Graph SDK and PnP.Framework, Mainly uploading a large number of files.

Requirement - Trying to collect the logs emitted by PnP.Framework especially the HTTP calls.

Solution

The PnP.Framework emits the traces by default using the standard .Net Trace class. Note it is not the ILogger that is now the standard after .Net Framework. Refer to the source code to ensure they change in the future. There is an ILogger class involved but that is not the same .Net Core uses
  • .Net Core programming model - Microsoft.Extensions.Logging.ILogger & Microsoft.Extensions.Logging.ILogger<TCategoryName>
  • PnP.Framework - PnP.Framework.Diagnostics.ILogger
The default implementation of PnP.Framework is using TraceLogger class which is implemented by the same SDK. It uses the Trace class as mentioned above. So if we don't configure anything else, we can collect the logs to a file using the below configuration changes in app.config or web.config.
<system.diagnostics>
    <trace autoflush="true" indentsize="1">
      <listeners>
        <add name="Listener1" type="System.Diagnostics.TextWriterTraceListener" initializeData="path\to\file.ext" />
        <remove name="Default" />
      </listeners>
    </trace>
... 
</system.diagnostics>

Here ends the basic solution to the problem. Anytime PnP.Framework SDK logs it will be saved to the file mentioned in the <listeners> section.

Log Level

By default the PnP.Framework logs at 'debug' which is strange.
But that can be changed with some adjustments. Config changes goes below
<configSections>
    <sectionGroup name="pnp">
      <section name="tracing" type="PnP.Framework.Diagnostics.LogConfigurationTracingSection,PnP.Framework"/>
    </sectionGroup>
  </configSections>
  <pnp>
    <tracing logLevel="Debug">
    </tracing>
  </pnp>

Tuesday, May 30, 2023

[Video] .Net Framework v/s .Net - HttpClient throwing TaskCancelled instead on Timeout

Today released a new video after long time. It is talking about 2 scenarios in .Net ecosystem related to HttpClient class and how it handles timeouts.

  • It is not throwing timeout exception on timeout
  • The behavior of handling timeout is different in traditional .Net Framework and modern .Net

Watch the video for more details



References

https://thomaslevesque.com/2018/02/25/better-timeout-handling-with-httpclient/

Monday, June 9, 2014

We can't eat all the .Net exceptions using try catch block especially ThreadAbortException

Background

It is generally not recommended in .Net to control the application flow by throwing and catching exception. But in some cases people does it, to safely do the thing. In one of the WCF component in my project there is one scenario where the application flow is controlled via exception. The main intention was to keep the exception inside the thread itself and return a wrapper which says there was exception or not. Below is the stripped down code just for understanding.

internal class LongRunningProcessCaller
{
    private delegate ResultWrapper InvokeAsync(bool parameter);
    public void Invoke()
    {
        InvokeAsync invoker = new InvokeAsync(CallInvokerThreadHandler);
        invoker.BeginInvoke(truenew AsyncCallback(InvokeAsyncCompleted), null);
    }
    private ResultWrapper CallInvokerThreadHandler(bool test)
    {
        try
        {
            LongRunningMethodWhichMayThrowThreadAbortException();
            return new ResultWrapper();
        }
        catch (Exception ex)//All the exceptions should be caught and pass via Error property
        {
            return new ResultWrapper() { Error = ex };
        }
    }
    private void InvokeAsyncCompleted(IAsyncResult result)
    {
        InvokeAsync asyncDelegate = (result as AsyncResult).AsyncDelegate as InvokeAsync;
        //This method will hang, if there is any exception in CallInvokerThreadHandler
        ResultWrapper invokerResult = asyncDelegate.EndInvoke(result);
        if (invokerResult.Error == null)
        {
            Console.WriteLine("Errored");
        }
        else
        {
            Console.WriteLine("Worked");
        }
    }
    private void LongRunningMethodWhichMayThrowThreadAbortException()
    {
        System.Threading.Thread.CurrentThread.Abort();
    }
}
class ResultWrapper
{
    public Exception Error { setget; }
}

The problem

It went good for some time in production and slowly we started getting inconsistent issues from production. As it is inconsistent, we were not able to reproduce in dev machines and fix it. If we look at the code we can understand that inconsistent issue may happen, in case the catch inside CallInvokerThreadHandler() didn't eat and convert the exception properly.

The debug process

Since its using async delegate invocation mechanism we started thinking about exception behavior in threads and find nothing much. Then we put instrumentation code in catch block and pushed to environments where this issue is reproducing. This leads to investigation of ThreadAbortException which we were not expecting in normal course.

Further google about how to handle ThreadAbortException in IIS hosting environment, gives information only regarding the ASP.Net web sites related to Respose.Redirect. Some sites suggests to join the threads.
One says to resolve this exception, we can just increase maxConnections in web.config.

The Root cause

But our problem is different we have WCF service which calls another WCF service in different thread. The different thread is needed because the second WCF call is time consuming say 2-3 hours. Since the new thread is long running, there are chances for that to be aborted due to various reasons. Our aim should be to handle the failures properly. But what was the problem in the code listed above as it seems to be doing the purpose?

The root cause is, The ThreadAbortException  cannot be eaten by the catch block and we were relying on exception eating behavior.

So if the ThreadAbortException occurs the wrapping of the error result for returning to the completed handler will not work. The runtime will re throw the exception at the end of the catch which will make the EndInvoke in InvokeAsyncCompleted() to wait infinitely.

So rewrote the code as follows by avoiding the async completed handler.

internal class LongRunningProcessCaller
{
    private delegate ResultWrapper InvokeAsync(bool parameter);
    public void Invoke()
    {
        InvokeAsync invoker = new InvokeAsync(CallInvokerThreadHandler);
        invoker.BeginInvoke(truenullnull);
    }
    private ResultWrapper CallInvokerThreadHandler(bool test)
    {
        try
        {
            LongRunningMethodWhichMayThrowThreadAbortException();
            Console.WriteLine("Worked");
        }
        //All the exceptions should be processed here.
        //This is because the runtime rethrows ThreadAbortException from catch automatically.
        catch (Exception ex)
        {
            Console.WriteLine("Errored");
        }
    }    
    private void LongRunningMethodWhichMayThrowThreadAbortException()
    {
        System.Threading.Thread.CurrentThread.Abort();
    }
}

Happy coding...

Monday, October 21, 2013

ASP.Net MVC 4 Error handling in real time applications

Whenever we google for ASP.Net MVC exception handling techniques, we get a bunch of links but most of those explains about different techniques and finally ask us to decide one method based on our requirement. Sometimes we will end up in a more confused state. This article is to help a real time ASP.Net MVC developer to decide his logging mechanism.

Aim of error handling

Below are the things we should aim when we develop a error handling framework.

Never expose the exception details

We should never return the details of exception such as call stack to the end user. If we expose, it is considered as a security hole for hackers to understand the working of our system.

Log all the exception details

No system in this world is perfect. We need to accept the fact that, there may be exceptions. How we are dealing with those exceptions is important. To fix bugs and improve our system, it is required to log all the exceptions occurred in the system. The developers can therefore analyse the logs and fix.

Types of errors

Below are the different types of error conditions, we can expect in our ASP.Net MVC application.

Exceptions in ASP.Net MVC pages

This is the most common type of exceptions we need to handle. There may be exceptions when we execute the controller code which needs to be handled properly.

How to handle MVC page exceptions

There are 2 methods to handle this. Either we need to handle the exception at MVC framework level using the HandleError attribute on the controller classes or handle the exception at application level by global.asax :Application_Error(). 

I would suggest going for the error handling at the application level. It will capture all the error including routing issues. How that is useful in case of wrong URLs can be seen in next section.

One challenge in handling the exceptions at application level is that we cannot show the MVC Error page directly as we are out of MVC framework. For that we need to follow the below technique in the Application_Error method.

        protected void Application_Error(object sender, EventArgs e)
        {
            var httpContext = ((MvcApplication)sender).Context;
            new MVCApplicationExceptionHandler().Handle(httpContext,Server);
        }

    public class MVCApplicationExceptionHandler
    {
        internal  void Handle(HttpContext httpContext, HttpServerUtility server)
        {
            var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
            string currentControllerName = GetCurrentControllerName(currentRouteData);
            string currentActionName = GetCurrentActionName(currentRouteData);
 
            var ex = server.GetLastError();
            new ExceptionLogger().Log(ex);
            RedirectToErrorPage(httpContext, ex,currentControllerName,currentActionName);
        }
        private void RedirectToErrorPage(HttpContext httpContext,Exception ex, string currentControllerName, string currentActionName)
        {
            //Clearing httpContext
            httpContext.ClearError();
            httpContext.Response.Clear();
            httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
            httpContext.Response.TrySkipIisCustomErrors = true;
 
            //Setting values for new route
            string errorAction = GetErrorActionNameFrom(ex);
            var routeData = new RouteData();
            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = errorAction;
            
            //Fire the ErrorController
            var controller = new ErrorController();
            controller.ViewData.Model = new HandleErrorInfo(ex, currentControllerName, currentActionName);
            ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
        }
        private string GetErrorActionNameFrom(Exception ex)
        {
            var action = "Index";
            var httpEx = ex as HttpException;
            if (httpEx !=null)
            {
                switch (httpEx.GetHttpCode())
                {
                    case 404:
                        action = "NotFound";
                        break;
                    default:
                        action = "Index";
                        break;
                }
            }
            return action;
        }
        private string GetCurrentActionName(RouteData currentRouteData)
        {
            string actionName = string.Empty;
            if (currentRouteData != null &&
                currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
                {
                    actionName = currentRouteData.Values["action"].ToString();
                }
            return actionName;
        }
        private string GetCurrentControllerName(RouteData currentRouteData)
        {
            string controllerName = string.Empty;
            if (currentRouteData != null &&
                currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
                {
                    controllerName = currentRouteData.Values["controller"].ToString();
                }
            return controllerName;
        }
    }

The ErrorController and it's View can be simple. ErrorController.Index() action which will be invoked when an exception occurs inside the controller.

Requests to wrong ASP.Net MVC page URLs which cannot be routed

Sometimes there will be requests to wrong URLs. We need to respond with proper message instead of showing the white screen or ASP.Net generated error page.

eg: www.mycompany.com/Emplyee/1 - The spelling mistake in the word 'employee' should be handled by our application.

How to handle wrong MVC URL requests

The above solution will work for wrong URLs as well. In this case the NotFound action will be invoked.See the attached sample for more details.

Exceptions in AJAX calls

AJAX calls may also raise exception in the controller. Those needs to be handled and the required information needs to be passed to the client side to inform the user about his request.

How to handle AJAX exceptions

Instead of error page we should return a JSON response which tells that there is an error happened. Lets see one example below

<script type="text/javascript">
    function divide() {
        var n1 = $("#n1").val();
        var n2 = $("#n2").val();
        //Lets not bother about the data which is available in n1 and n2. Assume that those are numbers
        $.ajax({
            type: "GET",
            cache: false,
            url: "../Calculator/Divide",
            data: { "n1": n1, "n2": n2 },    // multiple data sent using ajax
            success: function (html) {
                if (html.IsSuccess) {
                    $("#res").val(html.Result);
                }
                else {
                    alert(html.Result);
                }
            },
            error: function (a, b, c) {
                alert("Some unexpected error happened");
            }
        });
    }
</script>

    public class CalculatorController : Controller
    {
        public ActionResult Divide(int n1,int n2)
        {
            try
            {
                return new JsonResult() {JsonRequestBehavior = JsonRequestBehavior.AllowGet,Data = new  { IsSuccess = true, Result = n1 / n2 } };
            }
            catch (DivideByZeroException ex )
            {
                return new JsonResult() {JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = new { IsSuccess = false, Result = "You cannot divide by Zero" } };
            }
        }
    }

I don't think it needs any explanation. Even in case of exception its returning the JSON response. But before processing at the client side, it should check for IsSuccess property. If any other exception occurs the control goes to application level which we can see in next section.

The catch blocks should not be exception eating blocks. Use the catch blocks which we are sure that we can handle.

AJAX Request to wrong URLs which cannot be routed

In case of an AJAX request to wrong url either, we should return JSON response with error details or return "Not found status". Here we are redirecting to  ErrorController.APINotFound() action from there we are returning JSON result. The response http code will still be error. Only advantage here is that the clients will get details of the error or what went wrong in a secure manner. This is the better method which I could see instead of throwing http errors alone.

How to handle wrong AJAX requests

For this we had to modify one of the method in earlier code which is used to retrieve the Error action name. Now we need to look into the request header for the origin. If its originated from AJAX the value will be "XMLHttpRequest".

        private string GetErrorActionNameFrom(Exception ex, HttpContext context)
        {
            var action = "Index";
            if (!string.IsNullOrWhiteSpace( context.Request.Headers["X-Requested-With"]) &&
                context.Request.Headers["X-Requested-With"].Equals("XMLHttpRequest"))
            {
                action = "APINotFound";
            }
            else
            {
                var httpEx = ex as HttpException;
                if (httpEx != null)
                {
                    switch (httpEx.GetHttpCode())
                    {
                        case 404:
                            action = "NotFound";
                            break;
                        default:
                            action = "Index";
                            break;
                    }
                }
            }
            return action;
        }


        public ActionResult APINotFound()
        {
            return new JsonResult() { JsonRequestBehavior = JsonRequestBehavior.AllowGet, 
                Data = new { IsSuccess=false,Result="Not able to process your API request due to wrong url or unexpected errors"} };
        }

    function divide() {
        var n1 = $("#n1").val();
        var n2 = $("#n2").val();
        //Lets not bother about the data which is available in n1 and n2. Assume that those are numbers
        $.ajax({
            type: "GET",
            cache: false,
            url: "../Calculator/ivide",
            data: { "n1": n1, "n2": n2 },    // multiple data sent using ajax
            success: function (html) {
                if (html.IsSuccess) {
                    $("#res").val(html.Result);
                }
                else {
                    alert(html.Result);
                }
            },
            error: function (a, b, c) {
                alert(JSON.parse(a.responseText).Result);
            }
        });
    }
</script>

Sample can be download from sky drive. Now we can say out ASP.Net MVC application has an exception handling framework.

Monday, July 1, 2013

What,Why & How to resolve OutOfMemoryException in .Net

This is a normal exception happens in most of the .net applications. When ever developers see this they start thinking about the RAM of the system and divert their thoughts towards physical memory. But before going to that area there are some other things to be noted. 

What is OutOfMemoryException

  • An Exception in .Net which will be fired when the .net runtime is not able to allocate memory for object
  • The MSIL instructions such as newobj,newarr and box may throw this exception

Why OutOfMemoryException is occuring

  • Its not actually because there is not enough memory in the machine.(Memory shown in Task manager) 
  • Its because there is not enough continuous free memory in the process's address space to do memory allocation for objects

How to resolve

  • Facts before you try to solve this issue.
  • Steps for quick fix.
    • Convert the application to 64bit. This will remove the 2GB memory limit on process and largely increase the process address space so that there will be lesser fragmentation which provides more continuous free memory space.
  • Steps for actual fix
    • Use tools such WinDbg, .Net memory profiler etc... to find out the size of objects in the process memory. In most cases this will be very less than the memory shown in task manager.You may also use performance monitor counters to do the same.
    • If the size of objects and task manager reading has less difference ,it means you actually uses so many objects or the object you created are not deallocated properly. Check for memory leaks and fix it.
    • Check for LOH (Large Object Heap) fragmentation and fix it.
    • If you really want to work with huge objects use MemoryFailPoint class
Reference
http://blogs.msdn.com/b/tess/archive/tags/memory+issues/
http://msdn.microsoft.com/en-us/magazine/cc163528.aspx
http://stackoverflow.com/questions/4767651/what-is-the-cause-of-outofmemoryexception-in-net-on-the-windows-service-under-a

Monday, February 11, 2013

Maximum length of .net exe filename

Environment : Win 7
.Net version : 4.0 (File version of C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll is 4.0.30319.17929)
Technology : WPF

We had a situation where there is a WPF exe which contains more than 47 characters in file name .When we double click on the exe it simply shows 'not working'.

eg: The below file works
ABCEDFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU.exe
But if we add one more character to the file name it stops working
ABCEDFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV.exe

This happens even in case we place this file in c:\ which means this is not windows file limitation.

Console application

Obviously when we hit with this issue the first will be to try out the scenario in a console application. I tried that and there is no issue. We can have big file names.

Whats the error showing

There are no exception thrown in .net code. Simple shows stopped working. When we get the "Stopped working" dialog, if we select debug with new Visual Studio instance it shows some call stack in kernel

In the event log its logged as Application Error


Faulting application name: ABCEDFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV.exe, version: 1.0.0.0, time stamp: 0x50e559e0
Faulting module name: igdumd32.dll, version: 8.15.10.1995, time stamp: 0x4af4b4e4
Exception code: 0xc0000409
Fault offset: 0x00014fe6
Faulting process id: 0x13c8
Faulting application start time: 0x01ce08d99c9f454b
Faulting application path: E:\ABCEDFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV.exe
Faulting module path: C:\Windows\system32\igdumd32.dll
Report Id: dbba9063-74cc-11e2-bed6-005056c00008


Also there is another information entry


Fault bucket 50, type 5
Event Name: BEX
Response: Not available
Cab Id: 0

Problem signature:
P1: ABCEDFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV.exe
P2: 1.0.0.0
P3: 50e559e0
P4: igdumd32.dll
P5: 8.15.10.1995
P6: 4af4b4e4
P7: 00014fe6
P8: c0000409
P9: 00000000
P10:

Attached files:
C:\Users\joyg\AppData\Local\Temp\WERDD06.tmp.WERInternalMetadata.xml

These files may be available here:
C:\Users\joyg\AppData\Local\Microsoft\Windows\WER\ReportArchive\AppCrash_ABCEDFGHIJKLMNOP_934479f7c7ed9f73aa3ad0f14ce25746e867c84a_1f8bfff1

Analysis symbol:
Rechecking for solution: 0
Report Id: e98cb1b8-74cb-11e2-bed6-005056c00008
Report Status: 0


What to do

When googled we were left with no answers. Asked in Stackoverflow .For the time being we reduced the file length and continuing. Hopefully can get some answers using windbg.

Monday, February 27, 2012

DotNet Watcher - To find out eaten exceptions at runtime

One of my current .Net projects, which started from the VB 6.0 days has lot many areas where exceptions are eaten using empty catch blocks. As the project is in Agile methodology where people give more importance to delivery than quality, we cannot blame developers for writing this type of code. On a build day, if the app shows an exception dialog, the best way they are finding is the empty try-catch block and handle the consequences as bugs.

When we went to MSFT for reviewing the app, this caused so many troubles and they introduced us to their internal tool which captures the eaten exceptions. That was really helpful for debugging the application in the production environment. There are so many tools available public to track the same but this tool is so simple and easy to use. I was really excited and wanted to blog about the same. But not sure whether there were any permission or other license-related issues as the tool is Microsoft internal.

Days were happy when we were on .Net 3.5. But when we migrated our project to .Net 4.0, the MSFT tool stopped its support. It was targeted to the .Net 2.0 base run time and we were forced to recompile against .Net 4.0. The process of reflecting on the tool and google started in parallel and the reflecting wins and we got the tool in 4.0. But the interesting thing I got during the google is a link to Mike Stall's .Net blog which explains the basics of that tool.Yes.I can blog about the tool as the details are already available to the public.

How the tool works

The tools work based on MDbgCore.dll1 engine provided by Microsoft. It can either start an application in the attached mode or attach itself to a running process. Then it hooks to the debug points and other operations that are happening on the target application. Once a hooked operation happens it passes the control to our debugger host application where we can print or log the details.

Coding a Debugging host 

From the programming aspect, things are more clear. You need to refer the MDbgCore.dll to your application. Then create an instance of MDbgEngine to start or attach to a process that will give you MDbgProcess instance. The processInstance.Go.WaitOne() will wait for the notification from the target application. Once a notification comes, it will be an instance of the BuiltInStopReason derived class.Handle that accordingly.
            MDbgEngine debugEngine = new MDbgEngine();

            if (int.TryParse(args[0], out processId))
            {
                proc = debugEngine.Attach(processId);
            }
            else
            {
                proc = debugEngine.CreateProcess(args[0], ""DebugModeFlag.Debug, null);
            }
            while (proc.IsAlive)
            {
                // Let the debuggee run and wait until it hits a debug event.
                ManualResetEvent handle = proc.Go() as ManualResetEvent;
                handle.WaitOne();
                object o = proc.StopReason;
                // Process is now stopped. proc.StopReason tells us why we stopped.
                // The process is also safe for inspection.            
                ExceptionThrownStopReason m = o as ExceptionThrownStopReason;
                if (m != null)
                {
                    ProcessException(m, proc, callback);
                    continue;
                }
            }

Note: Important thing here is you need to run this in a separate thread or use async delegate to avoid the application waiting endlessly.  This was not in the sample provided by Mike Stall :-).

Modifications I did

Mike Stall's blog explains the basics such as how to attach to the target application and print the exception. I took it a little further to have a UI around. Also planning to add more scenarios such as capturing when the classes are being loaded along with capturing eaten exceptions.

Intended audience

Mainly the developers who are coding in .Net for years but don't know how the .Net application works internally. Then the developers who are in the same state as mine where they had to deal with so many eaten exceptions. Finally, developers who are interested in writing their own debugging tools. I know there are so many apps available that do the same. But seems a little difficult to make suitable for our purpose.

Source code

As I am planning to add more features I am not attaching it with this blog post. You need to go codeplex for the sample ie the application named DotNet Watcher  GitHub for the application source code. This is my first published project in CodePlex.

1 Locate the dll at :\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\MdbgCore.dll

Monday, November 14, 2011

Generic retry mechanism & catch using generic exception type

Couple of weeks back we faced one situation where a portion of our code breaks due to a IIS not available situation and we were advised to implement a retry mechanism.Hope I can talk about that server down problem in future posts. The retry mechanism needs to implement based on the exception which will occur on that particular scenario. We tried test code by putting the try catch block and could see its working in one place. But there  are a bunch of other areas we need to modify the code.Also in future too developers may need to use this retry mechanism.
The architect resting in me jumped and said that we can use a generic retry mechanism using .net generics. My colleagues were in little confusion about how to achieve a generic mechanism for retry where the size and location of code differs and spread out in 150 projects.With the help of Action delegate I was able to convince them and the subsequent google gave us ready made code to do the same.
public static void ExecuteWithRetry( Action action, UInt16 noOfAttempts )
{
    //Validate args:Throw exception on retryCount=0
    int count = 1;
    for (; ; count++)
    {
        try
        {
            action();
            break;
        }
        catch (ReTryableException ex)
        {
            Log(ex, count);
            if (count == noOfAttempts) throw;
        }
    }
}

Everybody became happy like after the first fight seen in movies. We know that the movie needs to complete its 2 hours with excitement and for that villain  should come back with more power. Here too the villain come back when the perfectionist in me put forward the suggestion of making it real generic so that we can move to the utility project and can be consumed by other fellow developers as well. So we rewrote the logic as follows.


public static void ExecuteWithRetry<TException> ( Action action, UInt16 noOfAttempts ) where TException :Exception   
{
    //Validate args:Throw exception on retryCount=0
    int count=1;
    for(;;count++)
    {
        try
        {
            action();
            break;
        }
        catch (TException ex)
        {
            Log(ex, count);
            if (count == noOfAttempts) throw;
        }
    } 
}

Oh what an idea sir ji…There was one more suggestion came to make retry after specific interval. But before that we tried to integrate modified function in our app.

Catching exception using generic type

Here starts the second part of the story. When we run from Visual studio it didn’t hit the catch block!!! Theoretically there are no issues but practically it failed. At least for some moment surrounding people even I thought that our understanding about either Exception handling or generics is wrong. Even we thought of getting rid of this concept and write redundant retry code everywhere. But when we came back to our original state , we googled it and find that it is a BUG in .Net when running inside Visual Studio debugging mode.We tried running by double clicking the application and it works perfect.We were also able to see this bug in the Microsoft connect and says its fixed.

There is on workaround available for this issue its as follows

catch (Exception ex)
{
    TException tEx = ex as TException;
    if (tEx != null) { /*Process */}
    else throw;
}

This changed my perception

“The bug is there only due to poor dev’s coding mistake never by compilers, development tools or the framework”

to

“Compilers, development tools and frameworks are also coded by developers”.

Later I happen to read a post about fixing a compiler bug which enforced my perception.

Tuesday, August 30, 2011

Getting right app.config file in Office Addins

Recently we got one issue while deploying our project’s Office Add-in component in one of the testing machine which has Microsoft Office 2007. We first tested in Excel after initial debugging we could see that one of the registry reading from add in code  is failing.Then we started digging into the inner areas and could see that the registry key is getting formatted using a app.config value, not getting correctly formatted.After some time by putting couple of message boxes we confirmed that the excel add-in is taking app.config file of excel from the below location!!!

<Install Drive>:\Program Files\Microsoft Office\Office12\EXCEL.EXE.config

We tested the manifest files, registry keys etc…but didn’t get any clue. According to us the add in should take its own config file and never the excel’s config file.Used almost all the debugging tools we know but no luck.We even thought of putting our config entries in the excel.exe.config Smile.Since that is not the right way finally started asking google.It gave the reason and solution very quickly.It is very simple .We need to change a registry entry where we specify the vsto addin path. The change seems so silly

The manifest registry entry needs to be prefixed with file:///.ie instead of "[TARGETDIR]ExcelAddIn.vsto|vstolocal": we need to use "file:///[TARGETDIR]ExcelAddIn.vsto|vstolocal":

http://stackoverflow.com/questions/1671587/word-addin-not-reading-appsetting .According to Microsoft this is a performance fix.

Simple fix but it took our half day and it was a SaturdaySad smile

Saturday, January 15, 2011

How to find the application which locked a file

When we deal with any application which does file copy or move we will end up in a scenario where some other application holds our target file and hence we cannot operate on that file.

In a perfect world where everybody codes well,this is not at all an issue.But nothing is perfect. So we need to check whether our target file system object is in use by any other application or process.I used the word file system object particularly because it includes files as well as folders .

Last week I got three queries from different people about the same .That is the reason for this post.

As always there are so many ways .I started with the usual try catch way. Write a method like bool IsLocked(string fileName) which uses a try catch block and inside the try read the file.If exception occurs its locked ie return true else false.

I myself said this hits your performance as each and every time you need to go through a try catch block.Oh what should we do then? I gave them another link which uses unmanaged code to find out the process which locked the file.

http://www.codeguru.com/Cpp/W-P/dll/article.php/c3641/#more
They became happy.

But was that a good solution? If we are trying for perfection will this handle all the possible scenarios? I will say no.Because immediately after you check for the lock and it says no locks some other application may take that file. It may be fraction of seconds .But there is a possibility.So what we can do?

My recommendation is to put all the file related operations in a transaction / try catch where ever appropriate and maintain a log.When one file breaks ,call the routine to find out the process which locked the file and ask the user to shut down that process.If user says ok we can continue else roll back the operations based on our log.

Still there are loop holes.What will happen if a file gets locked when you do the rollback operation? If that file is not a really meant to be used by any process ie your application specific ,kill the process else show the same UI to the user that we are not able even roll back.Still if the user is not willing to shut down his process,its his fate to have an environment which is not correct.

Remember there is no 100% perfection but 99.99%.

Friday, October 2, 2009

Will finally work if there is a return in catch

Confusing?? Just see the code below

Public Sub MyFun()
    Try
        Dim ope = 2
        Dim a As Integer = 10 / ope
    Catch ex As Exception
        MessageBox.Show("Exception")
        Return
    Finally
        MessageBox.Show("Finally")
    End Try
End Sub
This will execute properly and the finally will work.No doubt.But what about the below code.

Public Sub MyFun()
    Try
        Dim ope = 0
        Dim a As Integer = 10 / ope
    Catch ex As Exception
        MessageBox.Show("Exception")
        Return
    Finally
        MessageBox.Show("Finally")
    End Try
End Sub

There is no question that the above code will throw an exception.Then the catch will get executed which contains a return statement.Will that return statement works properly and go back to the calling function?


The answer is NO. The finally will execute even the catch contains a return.