none
Windows Service crashing on call to unmanaged code, even though console app version works RRS feed

  • Question

  • I have a C# program that at some point calls 2 functions from an unmanaged dll using p/invoke.  Everything works fine when I'm running in a console app.  When I compile the same program as a windows service and run it, it crashes.  The console app and service should be identical as far as my code is concerned... all either program does is create an object from another assembly of mine and run a Start() method on it.

    I have used VS2010 to debug the managed and unmanaged code, and when I step through the Console app everything looks great.  When I attach the debugger to the service, i can step through the first function in the unmanaged code, control returns to the managed code, and then later when it comes to the point where it calls the second unmanaged function, the process terminates immediately before the debugger steps into the first line of unmanaged code.  There are no exceptions that I can see, and the only thing written to the event log is the generic "service terminated unexpectedly" message.  Running "sc query" on the command line lets me know the win32_exit_code is 1067.

    Im running everything in .net 4, on winxp 32bit.  The serivce is running as Local System ideally, but the same behavior exists when I run it under my user account.  The second function call takes an IntPtr that comes from some locked bitmap data, in case that makes a difference.  Here is the DllImport attribute (remember this all works fine in the console app).  You might recognize that the function is from the Tesseract OCR project "tessdll".  I built the dll in VS2010 (building it in VS2005 and VS2008 had the same results).

    [DllImport(tessdll, CallingConvention = CallingConvention.Cdecl)]
    private static extern int TessDllBeginPageUprightBPP(UInt32 xsize, UInt32 ysize, IntPtr buf, string lang, Byte bpp);
    

    The first function which succeeds has this DllImport attribute:

    [DllImport(tessdll, CallingConvention = CallingConvention.Cdecl)]
    private static extern void SetWhitelist(string whitelist);

    The actual function calls look like this:

    SetWhitelist(whitelist); //<-- this succeeds
    //some light processing tasks
    TessDllBeginPageUprightBPP((uint)bmp.Width, (uint)bmp.Height, data.Scan0, language, bpp); //<-- crashes here
    

    Any ideas what could be causing this or how to dig deeper?  All I can think of is that P/Invoking is somehow different when running a windows service.  If you'd like to suggest an alternative to Tesseract I could just forget the whole thing :).


    Thanks for your help!

    Tuesday, October 12, 2010 11:04 PM

Answers

  • Turns out the problem had to do with my working directory.  The unmanaged dll needs other files in order to operate, and I'm guessing that it looks for those files in the working directory.  In a console app the default working directory is wherever the executable is, but in a windows service its system32.  I changed added some code the set the working directory to the location of the executable at the start of the service and everything works fine.  I hope theres not a problem with doing this for a windows service ... not sure of the rationale behind services having system32 as their working directory.  Anyone with information on that please feel free to share!

     The real lesson here is that a .net service can crash out without any helpful information when an unmanaged dll has a problem, even if you're debugging the managed code.  I'm not sure why the process just dies when its about to step into the dll without any errors indicated ... makes it hard to diagnose the problem.

    • Marked as answer by TCooperCogdill Wednesday, October 13, 2010 4:06 PM
    • Unmarked as answer by TCooperCogdill Wednesday, October 13, 2010 4:12 PM
    • Marked as answer by TCooperCogdill Wednesday, October 13, 2010 4:27 PM
    Wednesday, October 13, 2010 3:38 PM

All replies

  • Hi,

    Thanks for your post.

    According to here, exit code 1067 indicates that : The process terminated unexpectedly.

    Currently I can think of the following measures to take:

    1. Add try/catch block to the p/invoke code and see if any exception is catched.

    2. Use some Managed Debug Assistents (MDA) to see what happens when p/invoke is made. We can use the MDAs related to p/invoke, such as PInvokeLog or PInvokeStackImbalance, etc. A full list of available MDAs can be found here.

    Some info about how to use MDAs:

    Introducing MDAs

    I am not familiar with Tesseract so I cannot recommend an alternative for it.

     


    Please mark the right answer at the right time.
    Thanks,
    Sam
    • Edited by SamAgain Wednesday, October 13, 2010 7:18 AM refine
    Wednesday, October 13, 2010 7:17 AM
  • Thanks Sam ... I have all MDA's enabled and neither they nor any other .net exceptions are thrown on the call to unmanaged code.
    Wednesday, October 13, 2010 2:31 PM
  • Turns out the problem had to do with my working directory.  The unmanaged dll needs other files in order to operate, and I'm guessing that it looks for those files in the working directory.  In a console app the default working directory is wherever the executable is, but in a windows service its system32.  I changed added some code the set the working directory to the location of the executable at the start of the service and everything works fine.  I hope theres not a problem with doing this for a windows service ... not sure of the rationale behind services having system32 as their working directory.  Anyone with information on that please feel free to share!

     The real lesson here is that a .net service can crash out without any helpful information when an unmanaged dll has a problem, even if you're debugging the managed code.  I'm not sure why the process just dies when its about to step into the dll without any errors indicated ... makes it hard to diagnose the problem.

    • Marked as answer by TCooperCogdill Wednesday, October 13, 2010 4:06 PM
    • Unmarked as answer by TCooperCogdill Wednesday, October 13, 2010 4:12 PM
    • Marked as answer by TCooperCogdill Wednesday, October 13, 2010 4:27 PM
    Wednesday, October 13, 2010 3:38 PM
  • Hi,

    Thanks for sharing your progress. According to here, Windows services runs in a non-interactive window station. And error messages should be logged in the Windows event log rather than raised in the user interface. So maybe there's something in the event log when it encounters an error. IIRC, by default windows service use system32 as its working directory, here is an interesting thread about how to changing that.


    Please mark the right answer at the right time.
    Thanks,
    Sam
    Thursday, October 14, 2010 3:23 AM