satnhak
satnhak

Reputation: 9861

Call to native DLL fails from a .NET Windows service

I have a 3rd party API in the form of a native dll that I call from C# using DllImport. This native dll depends on the 3rd party application being open.

When I run the code normally the API does what is expected and drives the application. However, when I run the same code as a Windows service, even as myself, the API returns the same (undocumented) error code that I have seen when the application is closed; process explorer confirms that the native dll is correctly loaded from the application directory.

What could be causing this and how might I be able to resolve the issue?

Upvotes: 3

Views: 2450

Answers (3)

Vaszil
Vaszil

Reputation: 121

If you have to call native dll from a service, before starting it, try change the current directory like this:

static void Main()
{
    System.Environment.CurrentDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
    System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);

    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
    {
        new XYZService()
    };
    ServiceBase.Run(ServicesToRun);
}

After this, the service has no trouble to find the Native DLL's without changing Environment variables or without moving the native DLL's into the system folder.

Upvotes: 0

Christopher
Christopher

Reputation: 9824

A bit old, but it came up as one of the top results in a search. So I asume my data would still be helpfull.

I have a 3rd party API in the form of a native dll that I call from C# using DllImport. This native dll depends on the 3rd party application being open.

The (t)rusty Office Interop DLL is the same way. You are actually starting a background instance of the Office Programm in question. The Background Instance needs an interactive Session, even if it does not show anything (design asumptions/mistakes at work). Services do not run in an interactive session since Vista. Using the override is not recommended practice. That is one of the (3?) reasons to not use Office Interop anymore.

Possible workarounds:

  1. stop using a service. The Windows Task sheduler can do jsut about the same work, while giving you full interactive sessions. Even MS themself started to move stuff out of services, into the Sheduler whereever possible
  2. move the DLL access into a Helper process. That one can run in an interactive session. Use any way of interprocess communication to talk between the helper and the main service. This pattern is primarily used to work with x32 only dll from a x64 programm, but it should work here too. Both the manifest and Process.Start() have a way to start a programm interactively from a Service.

Based on one of the comments it appears you choose option 2, but using a Webservice instead. Unfortunately Webserices/Webapplications are usually run as Windows Service. And that is before you consider that they run under some of the most restrictive rights (since they are web reachable). So it would just get you back to square 1 or even another step backwards to square 0.

Upvotes: 2

Fadrian Sudaman
Fadrian Sudaman

Reputation: 6465

Hard to tell, but there is three possibilities I can think of:

  • Your service has UI component that require "interact with desktop" option checked
  • The working directory for windows service is %WinDir%\system32 (e.g. C:\windows\system32) and your dll have code that uses relative path reference to other resources that can't be found
  • Your service uses netpipe communication with the application that run in two different sessions

Upvotes: 1

Related Questions