Above is my folder structure. I have a Cordova app and a Windows Runtime Component - IBscanUltimate. The include folder has the C# code calling into the unmanaged IBscanUltimate.dll. Class1.cs is like this:
using System;
namespace IBscanUltimate
{
public sealed class Class1
{
public static String getSDK()
{
IBscanUltimate.DLL.IBSU_SdkVersion a = new DLL.IBSU_SdkVersion();
IBscanUltimate.DLL._IBSU_GetSDKVersion(ref a);
return "SDKVersion: " + a;
}
}
The IBScanUltimateApi.cs & _IBSU_GetSDKVersion look something like this:
internal partial class DLL
{
[DllImport("IBScanUltimate.DLL")]
private static extern int IBSU_GetSDKVersion(ref IBSU_SdkVersion pVerinfo);
public static int _IBSU_GetSDKVersion(ref IBSU_SdkVersion pVerinfo)
{
int nRc = IBSU_STATUS_OK;
nRc = IBSU_GetSDKVersion(ref pVerinfo);
return nRc;
}
}
I have placed the DLL in many locations to see if it'll get picked up and they all have the above properties. But when I try to run my app, it says unable to locate the IBScanUltimate.DLL
This is how the output is coming:
I am not sure what is it that I am doing wrong and why the DLLImport cannot find my dll. Thank you for your help.
Exact error is:
System.DllNotFoundException: Unable to load DLL 'IBScanUltimate.DLL': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
Update #1:
I have come across https://msdn.microsoft.com/en-us/library/windows/desktop/hh447159(v=vs.85).aspx This article is explaining that LoadPackagedLibrary function can be used to load the dll. I am not seeing any example on how to use this in C#.
Update #2:
Specify the search path for DllImport in .NET Mentions that SetDllDirectory or AddDllDirectory can be used. He has a code snippet for SetDllDirectory, but the argument is string[] paths. How would I specify the relative argument?
Update #3:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
public static bool setPath(String path)
{
//Windows.Storage.
//return SetDllDirectory("ms-appx:///");
return SetDllDirectory(path);
}
I tried calling the SetDllDirectory(path) method with various locations that my app should have access to but I am keep getting "false". Few examples that I have tried:
NativeMethods.setPath(Package.Current.InstalledLocation.Path.ToString());
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFolder folder = Windows.Storage.KnownFolders.MusicLibrary;
This is where my app is installed:
C:\Users\AAA\App\hello\platforms\windows\build\windows\Debug\x64\AppX
and I can see that my DLL is there. But still I'm getting the exception that DLL cannot be found. Do I have to put something on the manifest regarding this?
Update #4:
I ran a dumpbin on the DLL and i see the below DLL in the dumpbin:
WINUSB.DLL
mfc90.dll
MSVCR90.dll
KERNEL32.dll
USER32.dll
GDI32.dll
VERSION.dll
MSVCP90.dll
SETUPAPI.dll
I guess I'd like to check on each dll above separately to see if my windows runtime can pick it? One of them could be the culprit that's not being loaded?
Update #5:
Upon seeing the answer from Peter Torr - MSFT, and googling for MFC I came across this article https://msdn.microsoft.com/en-us/library/d06h2x6e.aspx Which states:
The MFC classes and their members cannot be used in applications that execute in the Windows Runtime.
I guess to conclude this wild hunt now. I would close this up that the library I tried to load is dependent on libraries not available for Windows Runtime.
I had this feeling because Windows form application would run but the the code converted to Windows Runtime would give the error that the DLL is not being found. Thanks to Peter for guiding in the right direction.
The DLL you are trying to load was clearly built for desktop apps (it has User, GDI, and MFC imports) and will not work as a UWP binary. I suspect also that the DLL does not have the AppContainer flag set (an option you pass to the linker). You will need to find another way to accomplish what you need (if necessary, please make any feature requests via the Windows Platform UserVoice.
I suspect that it can find your DLL just fine, but it fails to find one or more of its dependencies. Unfortunately, both of these cases result in extremely generic DllNotFoundException that mentions the DLL your try to P/Invoke to.
There is an easy way to figure out what's missing! Windows contains a feature called "loader snaps", which, when enabled, will log all the things that Windows DLL loader does for your process. That means it will also print what DLLs it fails to load. To enable it, run this in admin command prompt:
gflags.exe -i "<executableName>.exe" +sls
Where executable name is just the name of your executable without the folder. To see the output, you will also need to enable either native or mixed mode debugger. You can do that in your project properties debugging tab in Visual Studio.
You can read more about load snaps here:
https://blogs.msdn.microsoft.com/junfeng/2006/11/20/debugging-loadlibrary-failures/
I have a C# COM object in a dll that I have registered using regasm.exe.
I do a createObject on the COM object and call methods on the object in a vbs script run with cscript.
If I run this on the command line it all works properly, creates the object calls the method via com.
cscript.exe c:\mypath\myvb.vbs argument
I now am trying to run this same command from C#. I use the System.Diagnostics.Process methods
ProcessStartInfo si = new ProcessStartInfo();
si.Filename = "cscript.exe";
si.Arguments = "c:\mypath\myvb.vbs argument";
Process exe = ProcessStart(si);
...
When I run this way I get the 0x80070002 error , which is basically a file not found error. I dont understand why it is different from C# to the command line.
Edit - More Info
I am running on a 64bit OS. The C# COM dll was built with "AnyCPU" .
I used the 64bit regasm.
The cscript I used was from c:\windows\system32 so it was the 64 bit version.
From the command line if I deliberately use the 32 bit version of cscript I also get the 0x80070002 error. This leads me to suspect the problem from c# is related, but I still don't get it.
"File not found" is not the first kind of error you'd expect in this scenario. But it is certainly possible, you have to register the assembly twice. Once with the 64-bit version of Regasm.exe so that the 64-bit registry keys are written. And again with the 32-bit version, it writes the keys to HKLM\Software\Wow6432Node, where 32-bit client programs search for keys.
Which is easy to overlook of course, you never mentioned doing this so that's a Big Red flag. You'd normally get "Class not registered", that didn't happen, maybe there was an earlier registration we don't know about. Like Visual Studio registering it, you'd normally always favor it doing that way because it prevents registry pollution. Simple changes to the project or file can then trigger "File not found". Forgetting the /codebase option when you ran the 32-bit version of Regasm is another way.
Best thing to do is just not guess at this. File not found errors are very easy to diagose with SysInternals' Process Monitor. You'll see cscript.exe searching for the file and not finding it. The name of the file gives you a very strong hint what the underlying cause can be. Look at the trace from the bottom up to avoid drowning in the data. And pre-emptively ensure you use both versions of Regasm.exe because you know that's necessary.
I've been using TuesPechkin for some time now and today I went to update the nuget package to the new version 2.0.0+ and noticed that Factory.Create() no longer resolved, so I went to read on the GitHub the changes made and noticed it now expects the path to the dll?
IConverter converter =
new ThreadSafeConverter(
new PdfToolset(
new StaticDeployment(DLL_FOLDER_PATH)));
For the past few hours I've tried almost all the paths I can think of, "\bin", "\app_data", "\app_start", etc and I can't seem to find or figure out what it wants for the path and what dll?
I can see the TuesPechkin dll in my bin folder and it was the first path I tried, but I got the following error:
Additional information: Unable to load DLL 'wkhtmltox.dll': The
specified module could not be found. (Exception from HRESULT:
0x8007007E)
Where is that dll and now can I get it as the library doesn't seem to contain it, I tried installing the TuesPechkin.Wkhtmltox.Win32 package but the dll still is nowhere to be found. Also I am using this in a asp.net website project so I assume that using the following should work for obtaining the path, right?
var path = HttpContext.Current.Server.MapPath(#"~\bin\TuesPechkin.dll");
Further information: https://github.com/tuespetre/TuesPechkin/issues/57
The Tuespechkin has a zip file as a resource in the Win32 and Win64 embedded packages for the 'wkhtmltox.dll' file.
What it does when you use the Win32 or Win64 Embedded package is unzips the file and places it in the directory that you specify.
I have been putting a copy of the wkhtmltox dll at the root portion of my web app directory and pointing the DLL_FOLDER_PATH to it using the server physical path of my web app to get to it.
According to the author, you must set the converter in a static field for best results.
I do that, but set the converter to null when I am finished using it, and that seems to work.
Tuespechkin is wrapper for the wmkhtmlox dll file.
The original file is written in C++ and so will not automatically be usable in C# or VB.NET or any of the other managed code domains.
The Tuespechkin.dll file DOES NOT contain a copy of 'wkhtmltox.dll'. You either have to use one of the other embedded deployment modules or install a copy of the 'wkhtmltox.dll' in your web app after downloading it from the internet. That is what I do, and it seems to work just fine.
I am using Team Foundation Server, and attempts to compile code after using the Tuespechkin routines will fail the first time because the 'wkhtmltox.dll' file gets locked, but all you have to do is simply retry your build and it will go through.
I had issues with the 32-bit routine not working in a 64-bit environment and the 64-bit environment not being testable on localhost. I went with the workaround I came up with after examining the source code for Tuespechkin and the Win32 and Win64 embedded deployment packages.
It works well as long as you specify a url for the input rather than raw html.
The older package didn't render css very well.
If you are using a print.aspx routine, you can create the url for it as an offset from your main url.
I don't have the source code I am using with me at this point to offset to your base url for your web application, but it is simply an offshoot of HttpRequest.
You have to use the physical path to find the .dll, but you can use a web path for the print routine.
I hope this answers your question a bit.
If you are getting this error -> Could not load file or assembly 'TuesPechkin.Wkhtmltox.Win64' or one of its dependencies. An attempt was made to load a program with an incorrect format.
In Visual Studio Go to -
Tools -> Options -> Projects and Solutions -> Web Projects -> Use the 64 bit version of IIS Express for web sites and projects.
I installed TuesPechkin.Wkhtmltox.Win64 Nuget package and used the following code in a singleton:
public class PechkinPDFConvertor : IPDFConvertor
{
IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
public byte[] Convert(string html)
{
// return PechkinSync.Convert(new GlobalConfig(), html);
return converter.Convert(new HtmlToPdfDocument(html));
}
}
The web application then has to be run in x64 otherwise you will get an error about trying to load an x64 assembly in an x86 environment. Presumably you have to choose x64 or x86 at design time and use the corresponding nuget package, it would be nicer to choose this in the web.config.
EDIT: The above code failed on one server with the exact same message as yours - it was due to having not installed VC++ 2013. So the new code is running x86 as follows
try
{
string path = Path.Combine(Path.GetTempPath(), "MyApp_PDF_32");
Converter = new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win32EmbeddedDeployment(
new StaticDeployment(path))));
}
catch (Exception e)
{
if (e.Message.StartsWith("Unable to load DLL 'wkhtmltox.dll'"))
{
throw new InvalidOperationException(
"Ensure the prerequisite C++ 2013 Redistributable is installed", e);
}
else
throw;
}
If you do not want run the installer for wkhtmltox just to get the dll, you can do the following:
As #Timothy suggests, if you use the embedded version of wkhtmltox.dll from TuesPechkin, it will unzip it and place it in a temp directory. I copied this dll and referenced it with the StaticDeployment option without any issues.
To find the exact location, I just used Process Monitor (procmon.exe). For me it was C:\Windows\Temp\-169958574\8\0.12.2.1\wkhtmltox.dll
In my case, I am deploying on a 64-bit VPS then I got this error. I have solved the problem by installing the wkhtmltopdf that I downloaded from http://wkhtmltopdf.org/downloads.html. I chose the 32-bit installer.
In my case, I have solved the problem by installing the Wkhtmltox for win32 at https://www.nuget.org/packages/TuesPechkin.Wkhtmltox.Win32/
This error: Unable to load DLL 'wkhtmltox.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E) is returned in two situations:
1- Deploy dependency not installed:
For solve this, you can install nuget package "TuesPechkin.Wkhtmltox.Win64" and use this code (for WebApplications running in IIS):
IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
// Keep the converter somewhere static, or as a singleton instance!
// Do NOT run the above code more than once in the application lifecycle!
byte[] result = converter.Convert(document);
In runtime this code will copy the dependency "wkhtmltox.dll" in a temporary directory like: "C:\Windows\Temp\1402166677\8\0.12.2.1". It's possible to get the destination of file using:
var deployment = new Win64EmbeddedDeployment(new TempFolderDeployment());
Console.WriteLine(deployment.Path);
2- Microsoft Visual C++ 2013 Redistributable not installed:
As described here:
https://github.com/tuespetre/TuesPechkin/issues/65#issuecomment-71266114, the Visual C++ 2013 Runtime is required.
The solution from README is:
You must have Visual C++ 2013 runtime installed to use these packages. Otherwise, you will need to download the MingW build of wkhtmltopdf and its dependencies from their website and use that with the library. https://github.com/tuespetre/TuesPechkin#wkhtmltoxdll
or, you can install the Microsoft Visual C++ 2013 Redistributable:
choco install msvisualcplusplus2013-redist
Here is AnyCpu version, also support iis-base or winform application
using TuesPechkin.Wkhtmltox.AnyCPU;
...
var converter = PDFHelper.Factory.GetConverter();
var result = converter.Convert(This.Document);
Reference : https://github.com/tloy1966/TuesPechkin
Installing the Visual C++ Redistributable for Visual Studio 2013 resolved the error for me.
https://www.microsoft.com/en-us/download/details.aspx?id=40784
I have successfully got Reg-Free COM working using C++ and C# using manifest files i.e. early binding. I am now trying to get this working using late binding. The technique I have found, after much web searching, appears to be using "Microsoft.Windows.ActCtx".
An example I used to test this was MS's "Registration-Free Activation of COM-Based Components" found at http://msdn.microsoft.com/en-us/library/ms973913.aspx to generate the SideBySide example. I then attempted to use a scripting language; VBScript and Python however both have fail in the same way (also tried VBA). The VBScript example is given below:
Set actctx = CreateObject("Microsoft.Windows.ActCtx")
actctx.manifest = "C:\test\client.exe.manifest"
Set SBSObj = actctx.CreateObject("SideBySide.SideBySideClass")
wscript.echo SBSObj.Version
Using something like SysInternals' "Process Monitor" you can see that running the following command (Windows 7 x64):
C:\Windows\SysWOW64\cscript.exe //Nologo C:\test\VBRegFreeTest.vbs
appears to work by loading the manifests and attempt to start looking for the equivalent registry calls and fails to find them. So it appears to partially work. I've also copied wScript.exe to the local directory to rule out directory issues for running application and manifest files.
I've read Microsoft.Windows.ActCtx on Windows Xp and have included the "prodID" in the manifest but it still fails. The manifest files work correctly with C++ and C# examples.
I can't help feeling that the "Microsoft.Windows.ActCtx" has issues. Documentation on this is very limited. Any help on using manifest files with Python or VBScript would be very much appreciated. I would be interested to know if anyone has got "Microsoft.Windows.ActCtx" to work.
Your EXE must have manifest with dependency section describing name and version of COM server, e.g. SideBySide.dll.
If your EXE has internal manifest: Windows 7 will not read external manifest, if internal one exists (Windows XP looks firstly for external manifest).
On Windows 7 the internal manifest of EXE must be changed with dependency to COM server, or internal manifest must be removed from EXE. It is possible with mt.exe from Visual Studio.
SideBySide.dll and SideBySide.dll.manifest must be in the same folder as EXE.
SideBySide.dll.manifest must include progID of COM server in comClass section.
Example of VBS code, using DLL from: Registration-Free Activation of COM Components: A Walkthrough
Dim o
Set o = CreateObject("Microsoft.Windows.ActCtx")
//in example here is a manifest reference: o.manifest = "SideBySide.X.manifest"
//but it does not function by me. By me a dependency is described in manifest of EXE.
Dim obj
Set obj = o.CreateObject("SideBySideLib")
Call MsgBox(obj.Version())
Set obj = Nothing
Set o = Nothing
I am trying to import scikit-learn in a C# (console) application. I am using Python Tools for Visual Studio and IronPython 2.7.3.
I managed to run an external python script and I also managed to import numpy by declaring the python path: "C:\Python27\Lib\site-packages\"
However, when it comes to scikit-learn I get an error message:
Oops! We couldn't execute the script because of an exception: No module named _c
heck_build
___________________________________________________________________________
Contents of C:\Python27\Lib\site-packages\sklearn\__check_build:
setup.py setup.pyc setup.pyo
_check_build.pyd __init__.py __init__.pyc
__init__.pyo
___________________________________________________________________________
It seems that scikit-learn has not been built correctly.
If you have installed scikit-learn from source, please do not forget
to build the package before using it: run `python setup.py install` or
`make` in the source directory.
If you have used an installer, please check that it is suited for your
Python version, your operating system and your platform.
The file "_check_build.pyd" exists in "C:\Python27\Lib\site-packages\sklearn__check_build\".
My code is based on this article: http://devleader.ca/2013/09/23/visual-studio-c-python-sweet/
The file I am using has only the following code:
from sklearn.svm import SVC
print('Hello Python in C#')
Is it possible to add and use scikit in C#? If yes, could you please provide a workaround?
Looks like scikit-learn requires a C extension, which means it won't run under IronPython.