load native libraries in .NetCore 2.1 (Windows) - dll

I am trying to load native libraries in .NetCore 2.1 like this:
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern bool SetDllDirectoryA(string lpPathName);
...
SetDllDirectoryA(pathToDll);
var pDll = LoadLibrary(pathToDll+dllName);
if (pDll == IntPtr.Zero)
{
throw new System.ArgumentException("DLL not found", "pDll");
}
But the function LoadLibrary returns zero always. This code works fine with .NET Framework.
I am not really sure if loading native libraries is supported in .NetCore. If it is possible what is the correct way to do it?

I think you are using a 32 bit DLL. In netcore, a 32bit DLL could not be loaded with a 64bit process.
Try this code to check:
class Program
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
static void Main(string[] args)
{
if (System.Environment.Is64BitProcess)
{
Console.WriteLine("This is 64 bit process");
}
var pDll = LoadLibrary("aDLL.dll");
if (pDll == IntPtr.Zero)
{
Console.WriteLine("pDll: " + pDll);
throw new System.ArgumentException("DLL not found", "pDll");
}
Console.WriteLine("pDll: " + pDll);
}
}
Update: If you want to force NetCore runs at x86 flatform (to use 32bit DLL). First download NetCore x86 from https://dotnet.microsoft.com/download/thank-you/dotnet-sdk-2.1.500-windows-x86-installer. Then you should edit .CSPROJ file by adding RunCommand and changing PlatformTarget to x86 :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Prefer32Bit>false</Prefer32Bit>
<PlatformTarget>x86</PlatformTarget>
<Optimize>false</Optimize>
<RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand>
<RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand>
</PropertyGroup>
</Project>

Related

using Serilog Asp.net core dotnet 5 preview 7

Serilog community.
Firstly, thank you for the great library!
I am trying out Asp.Net on Net 5 Preview 7 at the time of writing this question. I have created 2 web API projects one targeting [netcoreapp3.1] and another targeting [net5].
Below is my bootstrapping code, it is identical for both APIs
using System.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Formatting.Elasticsearch;
namespace WebApplication1
{
public class Program
{
public static void Main(string[] args)
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(new ExceptionAsObjectJsonFormatter(renderMessage: true))
.CreateLogger();
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
The problem is when I am looking at logs, I no longer see TraceId and SpanId for the API targeting [net5] with the DotNet 5 preview 7 SDK.
I also tested using the vanilla Logger and there was no issue there. Do I have to configure something, did I just miss something or is the DotNet 5 Preview SDK not fully supported yet?
Thanks for any info, much appreciated.
PS: Serilog Nuget packages used
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Formatting.Elasticsearch" Version="8.2.0" />
Seems there was a change for logging in DotNet 5. Have a look at the GitHub issue linked here for the details,
serilog-aspnetcore github issue

"mono app.exe" gives error "File does not contain a valid CIL image."

I've made the following as a simple test.
using System;
namespace test
{
class App
{
static void Main(string[] args)
{
Console.WriteLine("test");
Console.ReadLine();
}
}
}
Then compiled and moved the entire bin folder to my pi and tried to run it using "mono app.exe" but I get the error in the title. How do I run compiled .Net core executables using mono on raspberry pi?
Realized that mono is .NET framework.
I installed .NET core runtime and it worked.
I followed this guide

How do I get an Angular TS file to compile and update on save in a .Net Core project?

So I was watching a channel 9 video on Angular CLI with .Net Core here: https://channel9.msdn.com/Shows/Visual-Studio-Toolbox/Angular-and-NET-Core
At position 8:15 he demos auto-syncing where updating a .ts file in the Angular CLI folder compiled on save, then later caused the view to update. I tried this an it does not update at all (unless I refresh the whole page).
I also noticed that the template does not work out of the box (big surprise). I managed to update it to the newer Angular version (and ran into an error where the template had incorrectly created "start": "ng serve --extract-css", to package.json where --extract-css is invalid and had to remove it). I also assumed that Visual Studio (2017) would compile Angular on its own, but it did not, so I added this to the project file:
<Target Name="NgDebug" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' ">
<!--Run Angular build in debug mode (NOTE: does not support symbolic links nor junction points)-->
<Message Importance="high" Text="Building the Angular code in debug (dev) mode ..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="ng build" />
</Target>
<Target Name="NgRelease" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Release' ">
<!--Run Angular build in prod mode (NOTE: does not support symbolic links nor junction points)-->
<Message Importance="high" Text="Building the Angular code in release (prod) mode ..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="ng build --prod" />
</Target>
Two questions here:
Is this sync feature expected to work today? Is there a configuration required?
Am I expected to setup the ng build step myself, or is there a different method I should be using for the ASP.Net Core (with Angular CLI) template?
Here is the app.UseSpa code:
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
So it appears the correct terminology is "Hot Module Replacement" (MHR - AKA "Live Reloading", or "Hot Updates/Reloading"). Following this answer got me part way there:
https://stackoverflow.com/a/50934814/1236397
The part missing was found here: https://github.com/aspnet/JavaScriptServices/issues/1654#issuecomment-430053872
Both of these links seem to suggest that the template Visual Studio creates is ready for production and not development. The two issues are:
The ClientApp\dist folder may get created at some point if you build outside Visual Studio. The existence of the manually created dist folder will break the live reloading. This folder must be deleted entirely.
The VS ASP.Net Core Angular CLI template is ready to serve static files in production mode. The template creator failed to wrap sections to prevent loading in dev mode.
For #2 change these lines:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
...
public IConfiguration Configuration { get; }
...
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
...
}
...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseSpaStaticFiles();
...
}
to this:
public Startup(IHostingEnvironment env, IConfiguration configuration)
{
HostingEnvironment = env;
Configuration = configuration;
}
...
public IHostingEnvironment HostingEnvironment { get; private set; }
public IConfiguration Configuration { get; }
...
public void ConfigureServices(IServiceCollection services)
{
...
if (HostingEnvironment.IsProduction())
{
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
...
}
...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
if (env.IsProduction())
{
app.UseSpaStaticFiles();
}
...
}
However, at this point the pages refresh in full. This is because HMR is not enabled by default. You'll have to follow the proper documentation here:
https://github.com/angular/angular-cli/wiki/stories-configure-hmr
If the link ever goes down, simply search for the documentation using the query configure HMR for angular CLI.
Tip: If you need IE9-11 support, take a look at the polyfills.ts file, and ignore the import 'classlist.js' line, unless you need it (otherwise run npm install --save classlist.js).

Microsoft.DotNet.Props directory does not exist for building xproj

We are trying to build an xproj project and an error about not being able to find the Microsoft.DotNet.Props file because it seems like its looking at the wrong directory.
Taking a look at the xml MSBuildExtensionsPath32 references C:\Program Files\dotnet\sdk\1.1.4\ where the directory Microsoft\VisualStudio\.. does not exist ... but the normal MSBuild directory C:\Program Files (x86)\MSBuild does have the directory for Microsoft.DotNet.Props file C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\DotNet\Microsoft.DotNet.Props
Here is the part of the XML
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
The error I see while building is:
error MSB4019: The imported project "C:\Program Files\dotnet\sdk\1.1.4\Microsoft\VisualStudio\v14.0\DotNet\Microsoft.DotNet.Props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
If anyone has any idea what is happening, help would be great
EDIT:
The build is invoked from a Jenkins project on Windows Server 2012 R2.
The VM image is from Azure market place "MicrosoftVisualStudio / VisualStudio / VS-2015-Comm-VSU3-AzureSDK-29-WS2012R2 / 2017.10.12" - which comes with Visual Studio 2015 community edition with update 3.
Azure SDK 2.9. Upgraded Node from old v0.12 to v8.x. Upgraded .NET core from not sure what was installed to 1.1.4.
The xproj itself has no code - except small amount in Startup.cs to serve static files (code at bottom of post).
The application is also used in a Service Fabric project. The error does not come from building the .sln but when packaging up the .sfproj (it might be its not set to build in the sln but packaging will need to build it).
Startup.cs:
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Website
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.Use(async (context, next) =>
{
await next();
if (context.Response.StatusCode == 404
&& !Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseStaticFiles();
}
}
}
Edit: here is the whole xproj xml
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<ProjectGuid>17107df8-0cfa-6946-917a-a9b8765cf9ea</ProjectGuid>
<RootNamespace>Website</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
</PropertyGroup>
<ItemGroup>
<DnxInvisibleContent Include="bower.json" />
<DnxInvisibleContent Include=".bowerrc" />
</ItemGroup>
<ItemGroup>
<DnxInvisibleFolder Include="wwwroot\Angular\dist\" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b69-4b1e-b82e-3ada8210c987}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
You are trying to use a preview tooling (xproj) with the 1.1.4 version of the .NET Core Sdk. The preview tooling available in VS 2015 does not work with the 1.0+ stable tooling for .NET Core.
Make sure that a preview2 version of the .NET Core SDK is installed both on your development machines and Jenkins server - e.g. 1.0.0-preview2-003156 - and that a global.json file exists your solution directory to tell VS to use this preview version of the SDK:
{
"sdk": {
"version": "1.0.0-preview2-003156"
}
}
As a long-term solution I recommend moving to the stable and supported .NET Core tooling by migrating to VS 2017.

DLL Pinvoke with Windows Mobile C++ libraries porting to C#

I am trying to use OpenCV as here, and I am stuck at one moment where I get PInvoke, namely:
my DLL.cpp
#define DLL_API __declspec(dllexport)
//...
DLL_API short processImage(const char* in_file, const char * out_file)
//...
my form.cs
[DllImport("DLL", EntryPoint = "processImage")]
private static extern short _ProcessImage(byte[] in_file, byte[] out_file);
public static short binarizeImage(string in_file, string out_file)
{
return _ProcessImage(StringToASCIIByteArray(in_file), StringToASCIIByteArray(out_file));
}
public static byte[] StringToASCIIByteArray(string str)
{
return Encoding.ASCII.GetBytes(str + "\0");
}
I think that this might be a problem with target architecture (in my VS 2008 project). When I use 'Any CPU' it compiles & runs but throws Pinvoke, when I set it to 'Windows Mobile 6 Professional SDK (ARMV4I)' it compiles but doesn't want to deploy and I got this in output window:
1>------ Deploy started: Project: DLL, Configuration: Debug Windows Mobile 6 Professional SDK (ARMV4I) ------
1>The system cannot find the path specified.
1>
2>------ Deploy started: Project: smartDeviceOcr, Configuration: Debug Any CPU ------
2>Deploying 'D:\VS 2008 Projects\C++\SmartDevice\ocr\smartDeviceOcr\bin\Debug\smartDeviceOcr.exe'
========== Deploy: 1 succeeded, 1 failed, 0 skipped ==========
Does the specific ARMV4I matter ? I have ARM920T on my mobile. Can/should I edit this to make it work ?
EDIT:
Just to be clear the Pinvoke points to :
return _ProcessImage(StringToASCIIByteArray(in_file), StringToASCIIByteArray(out_file));
and the exception message is :
System.MissingMethodException was unhandled
Message="Cannot find the library DLL PInvoke 'DLL'."
StackTrace:
in smartDeviceOcr.Form1.binarizeImage(String in_file, String out_file)
in smartDeviceOcr.Form1.button1_Click(Object sender, EventArgs e)
in System.Windows.Forms.Control.OnClick(EventArgs e)
in System.Windows.Forms.Button.OnClick(EventArgs e)
in System.Windows.Forms.ButtonBase.WnProc(WM wm, Int32 wParam, Int32 lParam)
in System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
in Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
in System.Windows.Forms.Application.Run(Form fm)
in smartDeviceOcr.Program.Main()
EDIT2:
Ok now it's really strange. I have changed few things. I have added the openCV's dlls to the deployment list in the project properties so that I can see that they are being copied on deployment and I have copied manually all the dlls to exe directory on the PC.
I have also changed some of the deployment options in DLL project so that the dlls are copied to the proper directory (automatically) on the phone and ....
now I have the error on runtime (when trying to access the function from the dll - opencv) :
The remote connection to the device has been lost
As I don't see any answers I post my answer (although I still have problems with this)
The problem can be solved by adding directories to which dlls should be deployed to:
Project-> Properties -> Deployment -> Remote Directory
and properly specify files in:
Project-> Properties -> Deployment -> Additional Files
as like
highgui200.dll|$(SolutionDir)\opencv_winmo\dll|%CSIDL_PROGRAM_FILES%\smartDeviceOcr|0
cv200.dll|$(SolutionDir)\opencv_winmo\dll|%CSIDL_PROGRAM_FILES%\smartDeviceOcr|0
cxcore200.dll|$(SolutionDir)\opencv_winmo\dll|%CSIDL_PROGRAM_FILES%\smartDeviceOcr|0
ml200.dll|$(SolutionDir)\opencv_winmo\dll|%CSIDL_PROGRAM_FILES%\smartDeviceOcr|0
msvcr90.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\smartDeviceOcr|0