I am working within a 32-bit ETL tool (Pervasive Data Integrator v9). I need to give this tool the ability to call an external function that will remove a file from within a ZIP archive without extracting the archive.
The ETL tool provides the ability to load an external DLL and call its functions. The DLL and its function gets referenced by ETL tool's custom script language like this:
Declare function OemToCharA lib "user32" (byval lpszSrc as string, byval lpszDst as string) as long
The function (OemToCharA in this example) is then called somewhere in the lines of the script that follow that declaration. I have tested this with a registered DLL and it works.
So I want to build a DLL with a function that will do the zip manipulation.
Since I don't know how to manipulate zip files programatically, I found DotNetZip - a free .NET class library that provides the heavy lifting for the zip archive operations. Problem for me is that it is .NET (managed). I would still like to try to use it. So I built a C# DLL (.NET 4.0) with a function that utilizes DotNetZip to do the required zip file manipulation. I pass in two parameters, "zip file location" and the "file to remove" and the zip archive gets updated.
I read about the idea of building a mixed-mode C++/CLI DLL to take advantage of managed .NET code in the native world. I found this VS solution which consists of 3 basic projects:
Managed (C#) DLL project
Mixed-mode C++ DLL wrapper project which references the C# DLL
A native (unmanaged) C++ console test app project which references the C++ wrapper
I built a test solution based on that pattern which removes a file from a zip archive and it works great. Please note however that the mixed mode DLL is called from a native C++ console app which is part of the VS solution. I didn't have to register any DLLs and it just works.
However ultimately I need the ETL tool to call the mixed mode DLL. I am not able to get this to work.
Things I have tried on the ETL server thus far:
I tried to register the mixed-mode wrapper DLL but SysWow64\regsvr32 fails to find an entry point in the DLL.
I installed VS 2015 VC++ x86 and x64 redistributable libraries on the ETL server.
I placed the DLLs from my solution (i.e., the mixed mode, c# and dotnetzip dlls) in the ETL engine folder because the console app worked when the DLLs were in its deploy folder.
The ETL tool has the ability to call an external application so I believe I could let it call a console app similar to my VS test solution but I'd really like to get this to work with only the DLLs. Is this possible? If so, what am I missing?
Kudos to Matt, thanks for the hint to use Process Monitor.
ETL tool was not finding the DLL but Process Monitor told me the folders it was checking...I moved the DLLs to one of the checked folders
My wrapper function was originally void with an output parameter for the return value - that was causing issues as I didn't have a good example in the ETL documentation of how to call a void function. I changed the function to return a "long" and removed the output parameter.
After making those two changes it started working. Thanks again Matt!
In my case, I have project A (in C#) that call a library from project B(C++). A interacted with B by C++/CLI method. In project B, we applied this code to avoid alert exception like this question:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
However,in project B we have stored some interface control in MFC in a .rc file. Unfortunately, when I call the interface control of project B, it doesn't show in project A.
Solution (didn't work)
I have searched and find a solution like question. In this case, they converted rc file to res file to import to project A. However, when applying RC tool we saw that all of include not found, unlike in Visual Studio.
How can I run project A and see interface control defined in .rc file of project B?
How can I convert a Visual-C++ GUI project from app to DLL, and then have a C# app call the DLL and run the GUI?
When I try, the " dlg.DoModal();" causes "Debug Assertion Failed!".
I've got a visual studio 2010 C++ project with Config Props set for:
"Config Type is app (.exe)
Use MFC in a Shared DLL
Not Using ATL"
When I change it to DLL, select Common Lang Run Support (/clr), I can successfully call its individual functions from my C# solution.
I've tried calling a test function in the DLL that calls
"theApp.InitInstance();"
but this generates "Debug Assertion Failed!".
Looks like you tried to convert the Win32 application into .NET one with just one switch (/clr), and this won't work (well it can work but in very simple cases and not in yours).
You still can convert the EXE into Win32 unmanaged DLL (this requires writing a couple of extra lines in .def file and in the main code), then use P/Invoke to invoke that function.
Create an empty MFC DLL project and copy all the essential code from Exe into it. Just changing he project type in Visual Studio Settings won't correctly change all the other code that Wizard generates when you create DLL app from scratch.
I'm trying to use OpenBLAS in a c# project (more specifically I'm attempting to use it with Math.NET via MathNet.Numerics.Control.LinearAlgebraProvider). I've successfully created the files following https://github.com/xianyi/OpenBLAS/wiki/How-to-use-OpenBLAS-in-Microsoft-Visual-Studio.
Now I have a .lib and .dll file in a new directory (as per subsection Use OpenBLAS .dll library in Visual Studio), but I'm not sure where to go from here!
Does anyone know what I'm supposed to do from here? I cannot directly add the generated dll to my project, and from further reading it seems like I need to generate a new dll using Visual Studio.
Use the NativeWrappers solution file provided by MathNet.
Similar instructions for MKL and ACML are here:
http://mathnetnumerics.codeplex.com/wikipage?title=Native%20Providers&referringTitle=Documentation
This question is kind of lengthy but I try to provide you with the details that I think is necessary to find the answer.
I have a C# WPF solution (.Net 4) consisting of a main project, building a WPF windows app, which depends on a few class library projects residing in the same Visual Studio 2010 solution.
One of the class library projects encapsulates some previously developed python code that I want to make use of through IronPython and Microsoft Dynamic Language Runtime.
I would like the class library project to be self contained and not depend on a complete installation of IronPython.
The problem is that I don't know how to refer to the encapsulating library project holding the python code in a way that always work.
Normally I would just add a reference to the class library project as discussed in this question: Visual Studio 2010: How refer to a C# .Net class library project with third part dependencies. However it did not help.
How the solution is set up in Visual Studio:
The solution looks like this:
MainApp (windows WPF application project)
...
ClassLib1 (C# class library project)
...
ClassLibWithPython (C# class library project with IronPython)
C# classes
lib (directory)
IronPython.dll
IronPython.Modules.dll
Microsoft.Dynamic.dll
Microsoft.Scripting.dll
Microsoft.Scripting.Metadata.dll
pylib (directory with some used python modules)
os.py
... .py
ctypes (directory with some used python modules)
my pyton classes (directory)
ClassLibWithPython has references to the IronPython DLLs residing in its local lib folder (Copy Local attribute True). The MainApp project has references to ClassLib1 project and ClassLibWithPython project (also with Copy Local attribute True).
When compiling the solution all DLLs and the MainApp.exe file shows up in MainApp/bin/Debug and it works fine on some machines (XP and Win 7) however it fails on some other machines (XP). After doing some debugging I've found that the built-in IronPython modules are not loaded correctly. When importing the os module (pylib/os.py like this one http://pydoc.org/get.cgi/usr/local/lib/python2.5/os.py) I get a python exception (ImportError, no os specific module found) due to missing module name 'nt'.
When comparing what's happening where it works and where it doesn't I've found that sys.builtin_module_names just returns a few items compared to what I get when running the same code on some other machines.
Problematic machine has:
sys.builtin_module_names = ['clr', 'future_builtins', 'imp', 'sys', '__builtin__', 'exceptions']
Computers where everything works have:
sys.builtin_module_names: ['clr', 'future_builtins', 'imp', 'sys', '__builtin__', 'exceptions', '_codecs', 'cmath', '_sha512', 'msvcrt', 'array', '_winreg', '_weakref', '_warnings', '_subprocess', '_ssl', '_sre', '_random', '_functools', 'xxsubtype', 'time', 'thread', '_struct', '_heapq', '_ctypes_test', '_ctypes', 'socket', '_sha256', '_sha', 'select', 're', 'operator', 'nt', '_md5', 'math', 'marshal', '_locale', '_io', 'itertools', 'gc', 'errno', 'datetime', 'cStringIO', 'cPickle', 'copy_reg', '_collections', 'binascii', 'zlib', 'signal', 'mmap']
Work-around that didn't help
I've tried to add using statements to the C# code of ClassLibWithPython to make sure even the implicitly referenced assemblies are linked, but with no difference.
Work-arounds that helped
I've found two workarounds providing a working solution, however both of them breaks the encapsulation principle and exposes the implementation details of ClassLibWithPython:
Put all code from ClassLibWithPython in the MainApp project instead.
Keep ClassLibWithPython in a separate project but add references to IronPython.dll and IronPython.Modules.dll to the MainApp project as well.
What is it that make work-around #2 working?
Any suggestions how to make this work in a clean way?
Thank's for reading this far ;-)
I don't fully understand the deployed layout - but try the following.
1) For modules that you expect to be loaded from IronPython.Modules.dll ensure that this assembly is available in your deployment location, and/or hook AssemblyResolve (see here) event if this assembly is in a different location.
2) For modules that you expect to be loaded from a py module. Ensure the probing location is added to sys.path via sys or from the DLR hosting API. eg sys.path.append(...)