0

I have a Visual Studio project that has a VC++ .dll project, along with a C# Console Application and a C# service which both reference the VC++ .dll using this:

[DllImport("ImagingService.dll")]
public static extern int main();

In the Main() method of the console app I call the main() method of the .dll and everything works as expected.

In the C# service project I call the main() method from within the OnStart() method. If all I have for code is the return 0 in the VC++ application it returns 0 as expected. But, If I have code copied directly from this GitHub, I get an error like this:

System.DllNotFoundException: Unable to load DLL 'ImagingService.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

The console app is using the environment variables as expected to find the GStreamer dependencies linked and included in the VC++ application, but it seems that the windows service is unable to find them. I know it finds the ImagingService.dll because it works if I comment out the GStreamer code.

Am I right in assuming that, since it works in the console app, all my includes are correct in the C++ app? And there is something different about how the service calls the GStreamer dlls that fails.

UPDATE: Since there is question on how I have setup my service I have created a simple solution that includes a basic C++ dll and a C# service and a C# Console application. The console works fine, the service does not. If anyone is interested in looking it over I have included a download link.

Dropbox solution download

You will also need to install the main x64 GStreamer installer and the x64 Devel package found here: Gstreamer Download

*NOTE *- when installing the main gstreamer-1.0 installer make sure you select to install the "restricted codecs with potential patent issues in some countries" option. You will also need to install the devel package as well.

For testing you can use VLC by typing the following into Media>OpenNetwork Stream text box.

rtsp://127.0.0.1:8554/test

Otherwise with the GStreamer installer they packaged the ability to run this command for testing:

gst-launch-1.0 rtspsrc location = rtsp://127.0.0.1:8554/test ! rtph264depay ! avdec_h264 ! autovideosink

TonySchoborg
  • 81
  • 1
  • 11

1 Answers1

0

If you C# application is set to "Any CPU" then this is most likely your problem. If your C# application starts are a x64 application then the ImagingService.dll must be a x64 dll, if your application starts as a x86 application then the ImagingService.dll must be a x86 dll.

I would constrain the C# application to just one architecture type. You can change this setting in the C# project properties build tab for the "Platform target" property and (I would assume) set it to the x86 type.

If the architecture is correct then it can't load the ImagingService.dll because it can't load / find the dll and/or it can load / find any dependant dll that ImagingService.dll depends on. This can be a path problem or a dll load path problem.

Update: In your case the problem is that your DLL both statically and dynamically loads DLL from the "gstreamer" install. So all these DLL's have to be able to be loaded.

I am assuming that the console version works because the gstreamer install path is in the USER path setup and the service does not because it's not therefor you get the exception that you do.

So there are 3 possible ways to fix which are all basically one solution: add the gstreamer dll's to the DLL load path.

  1. Add the gstreamer path to the global path therefor the service user can find them.
  2. Add the required dll's to your installed directory.
  3. Change the C# and/or C++ to add the gstreamer installed path to the dll load path manually.

1 & 2 and simple and don't require any code changes. 3. require code changes.

For 3 for the C++ DLL you can do something like:

  • Setup to delay load all gstream dll's that are statically required by your dll (Project Properties / Linker / Input / Delay Loaded Dlls)

  • Add the gstreamer path to the dll load path (this could come from a your app configuration or the C# coponent).
    So before you call any gstreamer API's you add something like:

    SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); AddDllDirectory(L"C:\gstreamer\1.0\x86_64\bin");

Shane Powell
  • 13,698
  • 2
  • 49
  • 61
  • All projects are set to x64. The service runs if I comment out the GStreamer code, and the console app works 100%, I just need this running as a service. – TonySchoborg Feb 20 '18 at 20:24
  • So I assume that ImagingService.dll is a x64 binary. If that's the case then it's a DLL find/load issue as I said. Check all the ImagingService.dll dependant dll's and make sure that they are they are all accessible. You can use the www.dependencywalker.com application (x64 version). – Shane Powell Feb 20 '18 at 20:27
  • I have worked with dependency walker a little. I will have to spend some time figuring it out. It has so many unreferenced errors to things I have no clue what they are or where they are supposed to be. I am assuming built in windows things. They are there even if it works fine. If it is a dependency thing I do not understand how it can work in a console app and not in a service. – TonySchoborg Feb 20 '18 at 23:02
  • Environment differences between users: * Path * DLL load settings – Shane Powell Feb 20 '18 at 23:58
  • I referenced [this link](https://stackoverflow.com/questions/36240215/dependency-walker-missing-dlls) for dlls to ignore when using Dependency walker and it appears everything else is fine. There were three dlls that it found but shoed they had missing references, but "walking" them each individually showed them missing the same API-Set dependencies. – TonySchoborg Feb 21 '18 at 20:45
  • Then it must be the service environment. Copy the dll into the system32 directory. If it starts ok, that confirms it (I would not recommend installing it there on customer machines). I don't know how you setup your service but services follow the same dll load rules: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx – Shane Powell Feb 21 '18 at 21:45
  • Moving the dll to system32 does not change anything. The dll will load in local directory if I comment out all the GStreamer code. So I am guessing it is finding the dll I wrote, just not the GStreamer ones. – TonySchoborg Feb 22 '18 at 19:03