Gstreamer RTSP works in console app, but not windows service

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

c#
c++
gstreamer
asked on Stack Overflow Feb 20, 2018 by TonySchoborg • edited Feb 28, 2018 by TonySchoborg

1 Answer

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");

answered on Stack Overflow Feb 20, 2018 by Shane Powell • edited Mar 2, 2018 by Shane Powell

User contributions licensed under CC BY-SA 3.0