I'm trying to interop with the ImageMagick library in Mono on a Mac. I installed the ImageMagick library with MacPorts and have verified that the file libMagickWand.dylib exists in the directory /opt/local/lib. I've also created a soft link to that file in the directory /usr/local/lib.
Here's my DllImport statement:
[DllImport("libMagickWand", EntryPoint = "MagickWandGenesis")]
static extern void WandGenesis();
Here's my App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<dllmap dll="libMagickWand" target="/opt/local/lib/libMagickWand.dylib" />
</configuration>
And, at the call to WandGenesis();, I get a DllNotFoundException, with the message 'libMagickWand'.
I've read this page and I think I'm following all the rules. Is there anything else I can try?
Update:
I ran the .exe with MONO_LOG_LEVEL=debug. Here is the pertinent information:
Mono: DllImport error loading library 'dlopen(/opt/local/lib/libMagickWand.5.dylib, 9):
no suitable image found.
Did find: /opt/local/lib/libMagickWand.5.dylib: mach-o, but wrong architecture'.
wrong architecture: I'm running Snow Leopard in 32-bit mode and always have. I installed ImageMagick with MacPorts, and I installed Mono with the Mac package from mono-project.com. What would have been compiled with a different architecture?
Update:
I think I found my problem:
MacBook-Pro:lib ken$ lipo -info libMagickWand.5.dylib
Non-fat file: libMagickWand.5.dylib is architecture: x86_64
Update:
...but I'm still having issues. I can't seem to figure out how to compile ImageMagick with i386 architecture. When I try to do so using flags, it complains about other libraries that were compiled as 64-bit.
Update:
Mono on Mac OS X is 32 bit (at least usually, you can confirm that with mono --version) and you are trying to link with 64bit binary which is not possible. You have to provide 32-bit binary (or use 64-bit Mono).
Do you have the error even when only the library's file name is in the target and the library is placed appropriately (or the DYLD_LIBRARY_PATH set)? In such case please provide the output of mono executed with MONO_LOG_LEVEL=debug.
Related
So I have a C# program that I'm making in Visual Studio Mac 2019. It uses the SFML.Net framework which depends on a dynamic library: libcsfml-graphics.2.5.0.dylib. Internally, the framework has a method called sfRenderWindow_createUnicode(...). This method uses a DLLImport for CSFML.graphics. If I run the program in Visual Studio, I get a DllNotFoundException with message csfml-graphics.
In my global config file for Mono, I have a DLL Mapping:
<dllmap dll="csfml-graphics" target="libcsfml-graphics.2.5.0.dylib" />
After adding that, if I run my program in Visual Studio, I still get a DllNotFoundException. However, the message now says libcsfml-graphics.2.5.0.dylib. So it's looking for the right library but can't find it? The .dylib file is in the same folder as the .exe.
The weird part is I can run the program from the terminal like so:
MONO_LOG_LEVEL=debug MONO_LOG_MASK=dll mono hello-csharp.exe > log.txt
The log.txt file contains the following lines:
Mono: DllImport attempting to load: 'libcsfml-graphics.2.5.0.dylib'.
Mono: DllImport loaded library '/Users/rutvik/Desktop/hello-csharp/hello-csharp/bin/Debug/libcsfml-graphics.2.5.0.dylib'.
Mono: DllImport searching in: 'libcsfml-graphics.2.5.0.dylib' ('/Users/rutvik/Desktop/hello-csharp/hello-csharp/bin/Debug/libcsfml-graphics.2.5.0.dylib').
Mono: Searching for 'sfRenderWindow_createUnicode'.
Mono: Probing 'sfRenderWindow_createUnicode'.
Mono: Found as 'sfRenderWindow_createUnicode'.
So it can find the .dylib for some reason. What is Visual Studio Mac doing differently? And how do I configure it to make it work?
For reference, here is otool -L run against libcsfml-graphics.2.5.0.dylib:
libcsfml-graphics.2.5.0.dylib:
libcsfml-graphics.2.5.dylib (compatibility version 2.5.0, current version 2.5.0)
#rpath/sfml-graphics.framework/Versions/2.5.1/sfml-graphics (compatibility version 2.5.0, current version 2.5.1)
#rpath/sfml-window.framework/Versions/2.5.1/sfml-window (compatibility version 2.5.0, current version 2.5.1)
#rpath/sfml-system.framework/Versions/2.5.1/sfml-system (compatibility version 2.5.0, current version 2.5.1)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
WHAT WORKED IN THE END:
Just to summarize, I put all the .dylib files in /usr/local/lib. The trick was to set the platform target to x64 as specified in the accepted answer. The DYLD_LIBRARY_PATH environment actually turned out to be not needed at all. And the .dylib files do not have to be in the same folder as the .exe.
Now both running from Visual Studio and running with mono in the terminal yield identical results.
Hooray!
1) Make sure your Platform Target matches your ABI type (x32 or x64 bit):
VS4M will launch the 32-bit Mono version by default as most project targets default to x32. Of course this does not matter if you are producing "fat" dylibs.
2) Set DYLD_LIBRARY_PATH in your Run Configuration to match your dylib location:
re: https://www.mono-project.com/docs/advanced/pinvoke/#macos-framework-and-dylib-search-path
I have a big problem with Mono; constantly receiving this error message.
WARNING: The runtime version Supported by This application is unavailable. Using default runtime: v4.0.30319
I have reinstalled the server three times already, but new installs unfortunately always have the same problem.
OS: Debian 7 mini
Mono: full instaled (mono-complet up to date)
PROCON: 1.4.0.6
Link: PROCON usage on Debian 7
If the application starts normally and you only want to suppress the warning, there are two options:
Configuration file
Add the configuration file to the directory where the binary is located, with the name <binary-name>.config, e.g. for application.exe use application.exe.config.
The contents of the file should be as following. Of course, the comment is optional.
<?xml version="1.0" encoding="utf-8"?>
<!-- Add this file to the legacy .NET application folder to prevent:
WARNING: The runtime version supported by this application is unavailable. -->
<configuration>
<startup>
<supportedRuntime version="v2.0.50727"/>
<supportedRuntime version="v4.0"/>
</startup>
</configuration>
Sources
http://do-the-right-things.blogspot.cz/2017/05/the-way-to-suppress-monos-warning.html
https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/#application-configuration-files
Command line
Specify the runtime manually when launching the application.
mono --runtime=v4.0 application.exe
Sources
https://linux.die.net/man/1/mono
Mono on MacOSX - "The runtime version supported by this application is unavailable." v4.5
If you use a dissembler to check the assemblies you should see which CLR version they were built against. My guess is that they were built against 2.0.
Mono 4 removes the old 2.0 CLR and 4.0 CLR (in fact 4.5 profile) becomes the default and the only. So this is simply a warning, not an error.
In my program I have this simple code:
using System;
using System.Data;
using Mono.Data.SqliteClient;
....
IDbConnection cnx = new SqliteConnection("URI=file:reestr.db");
cnx.Open();
....
And this is how I compile it:
$ mcs Test.cs -r:System.Data.dll -r:mono.data.sqliteclient.dll
It compiles ok. But when I run it with ./Test.exe, I get this error messages:
Missing method .ctor in assembly ....
Unhandled Exception:
System.IO.FileNotFoundException: Could not load file or assembly 'Mono.Data.SqliteClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756' or one of its dependencies.
File name: 'Mono.Data.SqliteClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756'
I'm not sure what I'm doing wrong here and how to repair it.
PS. I'm using Ubuntu as my OS.
It appears that Mono.Data.SqliteClient can not find the native SQLite binaries:
Prerequisites If you do not have SQLite, download it. There are
binaries for Windows and Linux. You can put the .dll or .so along side
your application binaries, or in a system-wide library path.
Ref: http://www.mono-project.com/docs/database-access/providers/sqlite/
To obtain pre-compiled native binaries (or source) for your platform:
http://www.sqlite.org/download.html
Also if you have the SQLite native shared libraries installed, are they available via dlopen? If not, you can assign the LD_LIBRARY_PATH env. var so Mono can find them at runtime.
Linux Shared Library Search Path From the dlopen(3) man page, the
necessary shared libraries needed by the program are searched for in
the following order:
A colon-separated list of directories in the user’s LD_LIBRARY_PATH
environment variable. This is a frequently-used way to allow native
shared libraries to be found by a CLI program. The list of libraries
cached in /etc/ld.so.cache. /etc/ld.so.cache is created by editing
/etc/ld.so.conf and running ldconfig(8). Editing /etc/ld.so.conf is
the preferred way to search additional directories, as opposed to
using LD_LIBRARY_PATH, as this is more secure (it’s more difficult to
get a trojan library into /etc/ld.so.cache than it is to insert it
into LD_LIBRARY_PATH). /lib, followed by /usr/lib.
Ubuntu Notes:
$ sudo apt-get install sqlite
$ ls -1 /usr/lib/libsqlite*
/usr/lib/libsqlite.so.0
/usr/lib/libsqlite.so.0.8.6
$ export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH
$ mono ./Test.exe
I solve the problem in my Mac in this way. Right Click in Mono.Data.Sqlite on References and click in Local Copy. This make mono copy dll to debug folder and your application will find the library.
OBS: Sorry for my bad english.
For the first time I have noticed that one of the mscordacwks DLLs in my collection is different (SVN told me). As I did some research I figured out that there are LDR versions and GDR versions of those DLLs.
For the files in question I noticed that one of them is not digitally signed, but the other one is (by Microsoft luckily).
So now I have the following questions:
If I have an LDR and a GDR version, how do I figure out which one is which?
Are both, GDR and LDR version of the DLL, signed by Microsoft?
Since one of them isn't signed, could someone inject malicious code into mscordacwks.dll which then gets executed on my machine with debugging privileges when I use it in WinDbg?
I'll try to find out where I got the unsigned DLL from. It is quite likely that I downloaded it from some some more or less dubious website when I needed that particular version.
FYI: the VirusTotal analysis did not reveal any viruses.
Thanks to the help in the comments I can summarize:
Digital signatures
According to Hans Passant, all Microsoft DLLs should be signed, so we have to be careful with unsigned ones.
Unfortunately this statement is not 100% true which I verified for the Mscordacwks.dll 2.0.50727.312 and SOS.dll 2.0.50727.312. Microsoft has shipped that version with Windows Vista. I tried that by installing Windows Vista from scratch.
This is the output of sigcheck -h on the DLL which come with Windows Vista:
Verified: Unsigned
Link date: 09:05 19.10.2006
Publisher: Microsoft Corporation
Description: Microsoft .NET External Data Access Support
Product: Microsoft« .NET Framework
Prod version: 2.0.50727.312
File version: 2.0.50727.312 (rtmLHS.050727-3100)
MachineType: 32-bit
MD5: 9252D83D169E84A442BB154A79AC2189
SHA1: 63464F337295D689384BAA514F260C54D06291C6
PESHA1: 99D57B38C554FFD4BEC6E6C2FAD7F77B980CB47B
PE256: EF387EF84028497D5F7D231ED3A6F5FB05C02D96BD3B0E470C6BEBFAD6942AC8
SHA256: 5ADB79D39FC8401CB9542B571EEEC82CAFCADAE2F26997C789E14EC8E9635C08
And also see the detailed information from VirusTotal which has the same hash codes. Please note the fact that the website is a bit misleading by listing "Authenticode signature block". In fact that is just the version information of the file. The most important line labelled "Signature verification: Signed file, verified signature" is missing for this DLL.
This is how it should look like if the file was really signed:
The output of sigcheck and Windows Explorer also show that that the file is not signed:
Verified: Unsigned
Link date: 09:05 19.10.2006
Publisher: Microsoft Corporation
Description: Microsoft .NET External Data Access Support
Product: Microsoft« .NET Framework
Prod version: 2.0.50727.312
File version: 2.0.50727.312 (rtmLHS.050727-3100)
MachineType: 32-bit
Screenshot of Windows Explorer where the file does not have a digital signatures tab:
At the end of the VirusTotal report, you find a statement by NIST (National Institute of Standards and Technology) which says that the file is delivered with Windows Vista Ultimate and that it seems to be safe. This is the website I am being led to after I uploaded an unsigned version.
Distinguishing GDR and LDR versions
The SysInternals sigcheck tool displays more information on the version number than Windows Explorer. If it includes "GDR", it is a GDR version. If it does not contain GDR, it is an LDR version.
To get a string for comparison in C#, you can use the following code:
var versionInfo = FileVersionInfo.GetVersionInfo(fullFileName);
var fileVersion = versionInfo.FileVersion;
Affected versions
I checked all my DLLs for signatures and found more unsigned DLLs than expected. However, most files have already been scanned on VirusTotal before. However, none of these versions has a NIST entry.
x86 SOS 1.1.4322.2032 VirusTotal
x86 SOS 2.0.50767.312 VirusTotal
x86 Mscordacwks 2.0.50767.312 VirusTotal
x86 Mscordacwks 2.0.50767.3603 VirusTotal
x86 Mscordacwks 2.0.50727.3623 VirusTotal
x64 SOS 2.0.50767.3074 VirusTotal
x64 Mscordacwks 4.0.30319.1008 VirusTotal
Malicious code injection
As stated by Jeroen Mostert, the DLLMain entry point will be executed, therefore there is the possibility of malicious code injection.
I've added a reference to the CUDAfy.NET library via NuGet.
<package id="CUDAfy.NET" version="1.12.4695.21111" targetFramework="net45" />
When I run my program, I hit a Win32Exception:
The system cannot find the file specified
This happens on the first actual line of the program:
CudafyModule km = CudafyTranslator.Cudafy();
There's no indication from the exception object as to what file they're attempting to load.
How can I get past this problem?
EDIT
I see the same exception when running the bundled examples from the Codeplex download in VS2010 using .NET 4.0.
The strack trace is:
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at Cudafy.CudafyModule.Compile(eGPUCompiler mode, Boolean deleteGeneratedCode)
at Cudafy.Translator.CudafyTranslator.Cudafy(ePlatform platform, eArchitecture arch, Version cudaVersion, Boolean compile, Type[] types)
at Cudafy.Translator.CudafyTranslator.Cudafy(ePlatform platform, eArchitecture arch, Type[] types)
at Cudafy.Translator.CudafyTranslator.Cudafy()
Setting VS to break on thrown exceptions shows the ProcessStartInfo object at the top of the stack in the locals pane of the debugger.
The relevant properties are:
FileName = nvcc
Arguments = -m64 -arch=sm_12 "c:\<path>\CUDAFYSOURCETEMP.cu" -o "c:\<path>\CUDAFYSOURCETEMP.ptx" --ptx
Some information from this article explains that the CUDA Toolkit must be installed. Fair enough.
Ensure that the C++ compiler (cl.exe) is on the search path. This set-up of NVCC is actually the toughest stage of the whole process, so please persevere. Read any errors you get carefully - most likely they are related to not finding cl.exe or not having either 32-bit or 64-bit CUDA Toolkit.
That article discusses version 4 of the toolkit, but version 5 is available now and supported since CUDAfy v1.1.
Download from https://developer.nvidia.com/cuda-downloads
Note that the 64-bit version of the CUDA Toolkit 5.0 is a 942 MB download. If you install everything you'll need an additional 2815 MB. The toolkit alone requires 928 MB.
EDIT After installing the CUDA Toolkit 5.0, the program failed with a CudafyCompileException at the same source line:
Compilation error: nvcc : fatal error : Cannot find compiler 'cl.exe' in PATH
Searching my system drive:
C:\>dir /s cl.exe
This shows many different versions of the compiler/linker, both from VS 10.0 and 11.0. Apparently only cl.exe versions 9 and 10 are supported, so I opted for the VS10.0 amd64 version, I included the following in my PATH environment variable:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64
Your path may be different, depending upon your CPU. I recommend running the search to see your options.
Note that you will have to restart VS after changing the PATH environment variable if you already have it open.
After taking these steps, my basic program ran successfully.
This may also happen if you had at some point installed CUDA Toolkit v7.5, but realized that the most recent version of CUDAfy supports CUDA 7.0.
On uninstalling CUDA 7.5 from the control panel, some files/folders may still remain. You should delete these manually. You may use CUDAfyViewer to see which version of CUDA Toolkit is being accessed.