Windows service in C# + C++ is refusing to start in Docker - c#

I created a solution in VS 2017 with 2 main projects (& common ones). The architecture illustrates a very large legacy project, therefore cannot be changed.
The main project is a .Net executable which it's main class inherits from 'ServiceBase' class in order to be used as a Windows service. It defines WCF endpoint and uses an interface 'IWcfXmlServer' to process a request.
The other project is a C++ project with a class that implements 'IWcfXmlServer' interface and used to process a request.
I have created a Windows service locally and pointed it to the .exe file of the solution and it worked fine.
The next step is to put that app on a Docker container.
I added Docker support, which added "docker-compose" .yml file:
version: '3.4'
services:
wcfservice:
image: ${DOCKER_REGISTRY}wcfservice
build:
context: .\..\WcfService
dockerfile: Dockerfile
and a Dockerfile:
FROM microsoft/dotnet-framework:4.7.1-windowsservercore-1709
ARG source
WORKDIR /app
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["C:\\app\\WcfService.exe"]
When I build the solution and start debugging I get:
Cannot start service from the command line or a debugger. A Windows Service must first be installed (using installutil.exe) and then started with the ServerExplorer, Windows Services Administrative tool or the NET START command.
but still, the container is created.
I opened PowerShell in the created Docker container and used "New-Service" to create a new service and point it to my .exe file. When I try to run Start-Service I get an error.
I used the Windows event log to get the error description:
EntryType : Error
Message : Service cannot be started. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or
assembly 'testole.dll' or one of its dependencies. The specified module could not be found.
at WcfService.WcfXmlServerFacade..ctor()
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.ServiceModel.Description.ServiceDescription.CreateImplementation(Type serviceType)
at System.ServiceModel.Description.ServiceDescription.SetupSingleton(ServiceDescription serviceDescription, Object implementation, Boolean isWellKnown)
at System.ServiceModel.Description.ServiceDescription.GetService(Type serviceType)
at System.ServiceModel.ServiceHost.CreateDescription(IDictionary`2& implem...
Source : WcfService1
'testole.dll' is my c++ project compiled.
** I already checked that 'testole.dll' is present in the same directory of the .exe file inside the container.
I can't figure out neither why it fails to run the C++ dll, nor how to get more information about the error (Console.Writeine() \ Debug.Writeine()) didn't work for some reason.
Thanks in advance.

Most probably you're missing Visual C++ Redistributable package. I suspect it's not installed by default on windows docker images.
Try adding following lines (for downloading VC++ 2015 Update 3 x64) to your Dockerfile just below FROM line:
ADD https://download.microsoft.com/download/6/A/A/6AA4EDFF-645B-48C5-81CC-ED5963AEAD48/vc_redist.x64.exe /vc_redist.x64.exe
RUN C:\vc_redist.x64.exe /quiet /install
Source (https://github.com/Microsoft/dotnet-framework-docker/issues/15)

Related

Can't instantiate multiple VFP COM Dlls: 80004005 Unspecified error

I've got two sample VFP9 OlePublic dlls that I'm calling from a .NET Core 2.1 project running full framework .NET 4.6.1. Everything is working fine locally but upon deployment to a Windows Server 2016 machine, I'm only able to instantiate an instance of a.dll or b.dll, not both. It seems the last one to be registered wins.
If I register a.dll then b.ll, I can instantiate an instance of b & vice versa.
Retrieving the COM class factory for component with CLSID {CF0998BA-54F1-40BD-BB92-4E938A77E1E5} failed due to the following error: 80004005 Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL)).
Define Class miked As Session OLEPUBLIC
FUNCTION HelloWorld as String
RETURN "Hello World"
ENDFUNC
FUNCTION Echo(thingToEcho as String) as String
RETURN thingToEcho
ENDFUNC
Enddefine
public void TestMikeDll()
{
new miked.miked();
}
I'm guessing I haven't configured/defined something correctly in my VPF9 projects? šŸ¤”
publish profile:
update
So it's not the last one registered, it's the first one to get instantiated. If I successfully instantiate a.dll then b.dll fails but if I recyle the app pool & try b.dll first it succeeds & a.dll fails.
Give the AppPool identity write (maybe modify too) access to the location of the VFP COM Dlls. Apparently, it needs to dynamically create another DLL: [original name]r1.dll that has a file desc of "Microsoft Visual FoxPro 9.0 SP2 Runtime Library" (the purple box).
Go to properties on folder where COM DLLs live
Security Tab
Edit
Add
in enter the object names to select: IIS AppPool\[your AppPool name]
reference: MSFT doc page on giving AppPool identity file permissions
credit: this comment from Aloio Kraus lead me down the path:
the 5 of the error code is the Win32 error code which means access denied. I would run procmon and watch for registry/file accesses which fail. That should hint to the right direction what went wrong

extracting CAB file throwing error while running as linux container

I am using SevenZipExtractor (https://www.nuget.org/packages/SevenZipExtractor/) to extract CAB files using below code, it's works on my windows machine,
using (ArchiveFile archiveFile = new ArchiveFile(#"C:\TEMP\x.cab"))
{
foreach (Entry entry in archiveFile.Entries)
{
Console.WriteLine(entry.FileName);
// extract to file
entry.Extract(entry.FileName);
}
}
While I am pushing this to Linux container, it's throws below error,
This seems the NuGet package using some internal Windows DLL.
Question: can I make some docker file change and make it running on Linux container?
> āÆ docker run -i test
Unhandled exception. SevenZipExtractor.SevenZipException: Unable to
initialize SevenZipHandle ---> System.DllNotFoundException: Unable to
load shared library 'kernel32.dll' or one of its dependencies. In
order to help diagnose loading problems, consider setting the LD_DEBUG
environment variable: libkernel32.dll: cannot open shared object file:
No such file or directory at
SevenZipExtractor.Kernel32Dll.LoadLibrary(String lpFileName) at
SevenZipExtractor.SevenZipHandle..ctor(String sevenZipLibPath) at
SevenZipExtractor.ArchiveFile.InitializeAndValidateLibrary() ---
End of inner exception stack trace --- at
SevenZipExtractor.ArchiveFile.InitializeAndValidateLibrary() at
SevenZipExtractor.ArchiveFile..ctor(String archiveFilePath, String
libraryFilePath) at ConsoleDocker.Program.Main(String[] args) in
/src/Program.cs:line 33
https://www.nuget.org/packages/SevenZipExtractor/
C# wrapper for 7z.dll (included)
You trying to use windows dll under linux.
Instead, you can use https://www.7-zip.org/sdk.html - there is pure c# code, not .dll wrapper

dotnet build/msbuild fails on GenerateResource Task with .NET 6

I try to build my project in my CI/CD pipeline with a gitlab runner, but I always end in the following error message:
C:\Program Files\dotnet\sdk\6.0.100\Microsoft.Common.CurrentVersion.targets(3264,5): error MSB4216: The GenerateResource task could not be performed because MSBuild could not create a task host or connect to a task host with runtime CLR4 and architecture x86. Make sure that (1) the requested runtime and/or architecture is available on the computer and (2) the required executable file "C:\Program Files\dotnet\sdk\6.0.100\MSBuild.exe" exists and can be executed. [project_path]
C:\Program Files\dotnet\sdk\6.0.100\Microsoft.Common.CurrentVersion.targets(3286,7): error MSB4028: The output of the GenerateResource task could not be retrieved from the FilesWritten parameter. Object does not match target type. [project_path]
IĀ“ve installed .NET6 SDK with version 6.0.100.
It seems like its trying to find the msbuild.exe and itĀ“s not there. IĀ“ve copied the file temporarely but this causes a endless building without result or error message.
Am I missing something? In my Visual Studio 2022 the build process is working and generating my binaries.

CSC : error CS2001: Source file '.NETPortable,Version=v4.5,Profile=Profile78.AssemblyAttributes.cs' could not be found

When start build on my Bamboo server ,I am getting following error:
Using shared compilation with compiler from directory: C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\Roslyn
CSC : error CS2001: Source file 'C:\Windows\system32\config\systemprofile\AppData\Local\Temp.NETPortable,Version=v4.5,Profile=Profile78.AssemblyAttributes.cs' could not be found. [E:\bamboo-agent-home\xml-data\build-dir\Domain\Domain.csproj]
Done Building Project "E:\bamboo-agent-home\xml-data\build-dir\Business\Business.csproj" (default targets) -- FAILED.
Unable to understand this error. On Local this works perfect even on command line - MSBuildcommand.
It looks like your build service is running as a system account (e.g. local system, network service, etc.) which leads to undesired behaviour in msbuild.
You should create a dedicated service user and configure the service to run as this user or ensure that the service user has sufficient rights to modify the system profile directory (which I don't recommend).
You can follow Atlassian's guide on how to run the windows service as a local user.

.NET, Topshelf service, Mono and different build machines

I experience a problem with running my .NET application service built with TopShelf on Mono.
The development setup is: Win 8.1, VS 2015, .NET 4.5.2 as a target framework
The CI setup: Win Server 2012, TeamCity 9.1.6, both server and build agent are running at the same machine
The execution (test server) setup: CentOS 6 x86_64, Mono 4.2.2
So I've implemented an application running as both a console application and background service (with the TopShelf) and successfully debugged and tested it locally.
I've set up the CI server in the way it builds an application on a build agent and produces as a folder with multiple dlls and .exe runner file inside (Release configuration) as a output. Finally CI publishes this folder to the remote CentOS server.
When I connect to the CentOS server via ssh and try to run it with the mono myapp.exe command, I get an error:
# mono myapp.exe
Configuration Result:
[Success] Name myapp
[Success] DisplayName myapp
[Success] Description myapp
[Success] ServiceName myapp
Topshelf v3.3.154.0, .NET Framework v4.0.30319.17020
[DEBUG][2/4/2016 7:42:57 PM][Thread 0001][EventStream] StandardOutLogger started
[INFO][2/4/2016 7:42:57 PM][Thread 0006][[akka://AkkaGrid/system/log1-NLogLogger]] NLogLogger started
[DEBUG][2/4/2016 7:42:57 PM][Thread 0001][EventStream(AkkaGrid)] Logger log1-NLogLogger [NLogLogger] started
[DEBUG][2/4/2016 7:42:57 PM][Thread 0001][EventStream(AkkaGrid)] StandardOutLogger being removed
2016-02-04 22:42:57.4509 DEBUG Start
2016-02-04 22:42:57.4538 DEBUG Logger log1-NLogLogger [NLogLogger] started
2016-02-04 22:42:57.4714 DEBUG StandardOutLogger being removed
2016-02-04 22:42:57.4714 DEBUG Default Loggers started
The myapp service is now running, press Control+C to exit.
2016-02-04 22:42:57.5075 ERROR Error while creating actor instance of type MyApp.Actors.Supervisor with 0 args: ()EXCEPTION OCCURRED:Akka.Actor.ActorInitializationException Exception during creation Void Create(System.Exception)
TypeLoadException Error while creating actor instance of type MyApp.Actors.Supervisor with 0 args: () Akka.Actor.ActorBase NewActor()
TargetInvocationException Exception has been thrown by the target of an invocation. System.Object InternalInvoke(System.Object, System.Object[])
MissingMethodException Method 'Array.Empty' not found.
2016-02-04 22:42:57.5216 INFO Message FetchEntityMessage from NoSender to akka://AkkaGrid/user/$b was not delivered. 1 dead letters encountered.
Ignoring the fact that there are also Akka.net and NLogger inside, the core issue seems to be in this line:
MissingMethodException Method 'Array.Empty' not found.
So, in order to test the compatibility of my code with Mono itself I've manually copied the application folder (Release) from my local machine (right after VS2015/MsBuild) to CentOS server and ran mono myapp.exe command again.
This way the execution succeeded and produced no errors in the output.
To ensure that the issue is not connected to the copying process, I've connected to the Win2012 server (with CI running on it), went to the build agent's working directory and executed myapp.exe as a simple windows console application. It ran successfully. Then I copied the application folder manually to the CentOS server via scp command from git bash and... got the same issue as above.
To provide some extra details, the build log is the following:
Step 2/7: Build .NET subsystem (MSBuild) (6s)
[22:36:32][Step 2/7] Starting: C:\TeamCity\buildAgent\plugins\dotnetPlugin\bin\JetBrains.BuildServer.MsBuildBootstrap.exe /workdir:C:\TeamCity\buildAgent\work\17605015421235b0 "/msbuildPath:C:\Program Files (x86)\MSBuild\14.0\bin\amd64\MSBuild.exe"
[22:36:32][Step 2/7] in directory: C:\TeamCity\buildAgent\work\17605015421235b0
[22:36:33][Step 2/7] .net\MyApp.sln.teamcity: Build target: TeamCity_Generated_Build (4s)
[22:36:33][.net\MyApp.sln.teamcity] TeamCity_Generated_Build (4s)
[22:36:33][Step 2/7] MSBuild command line parameters contain "/property:" or "/p:". It is recommended to define System Property on Build Parameters instead.
[22:36:38][Step 2/7] Process exited with code 0
So I can see that TeamCity doesn't run the MSBuild directly, but some MsBuildBootstrap application. MSBuild Tools 2015 are set in the build step settings. So... that's all the details, any help appreciated :)
MissingMethodException Method 'Array.Empty' not found.
This method is new in .NET 4.6 as specified in the documentation.
The problem is that Mono 4.2.2 is not compatible with this version of .NET.
I've looked at the sources, and it looks that Mono from the master branch already includes this. However, the commit in which it was introduced is not yet marked as being present in any tag or branch. That means you will have to wait until Mono 4.3 or 4.4 is released, or compile Mono from sources yourself, or maybe try to look for a weekly/nightly build that you could use.
An easier fix may be trying to depend on binaries that are not so bleeding edge (i.e. that were compiled using the framework version 3.5 or 4.0).

Categories