Visual Studio DllNotFoundException - asp.net

public const string LIB_GVC = "gvc.dll";
public const string LIB_GRAPH = "graph.dll";
public const int SUCCESS = 0;
[DllImport(LIB_GVC)]
public static extern IntPtr gvContext();
Later, in the main method I call gvContext() and it throws the DllNotFoundException. In my project, I have gone into the Project->Properties and set the reference paths so that I have a folder called "resources" which contains all my DLLs including gvc.dll. I thought this would do the trick but it didn't. What do I need to do?
Note: I cannot use Add Reference as I normally would, I realize that this behavior is normal considering Graphviz is not a C# library. I'm also a bit fuzzy on terminology, why is it called an "unmanaged DLL"? It seems to be because it wasn't compiled from C# code but is that true/not the whole story?
I'm following this tutorial if it helps clarify anything.

The problem is the executable is not finding the path to the executable. Try placing in the /bin folder after you ahve it running and see it works. If so, you resources folder is either a) not found or b) you have a copy operation on compile that is not set up correctly.
As for "what is unmanaged", COM and Native components have their memory handled either by the library itself (native always, COM may be handled by a runtime in some instance) or by something other than .NET. The CLR cannot manage the memory usage, as they are not .NET components. That is why they are called "unmanaged".

Related

UWP API in ASP.NET

I'd like to use a piece of Windows 10 specific UWP API (specifically, the Windows.Graphics.Printing3D stuff) in an ASP.NET code-behind DLL. Is there any way to do so?
While looking for a .NET-only resolution to this one, I've found a moderately clean way - a Win32/64 C++ DLL that would consume UWP API and present a COM- or P/Invoke-based interface to .NET.
Create a regular Win32 DLL. Build an interface for .NET to consume - exported functions or objects, depends. In my case, a single exported function will do. In the project's C/C++ settings, make the following changes:
Under General, set Consume Windows Runtime Extensions to Yes.
Under General, set Additional #using Directories to: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcpackages;C:\Program Files (x86)\Windows Kits\10\UnionMetadata (assuming Visual Studio 2015)
Under Code Generation, set Enable Minimal Rebuild to No (it's only Yes for Debug, not for Release).
Then instantiate and use UWP components in the DLL in the usual C++/CX manner, like you would in a Store app, via using namespace Windows::... and ref new.
In this approach, you lose bitness agnosticism; an unmanaged DLL can't be "Any CPU". You win some, you lose some. Also, the site will not run without the Visual C++ redistributable package on the system. On the other hand, it may run faster than a .NET app; less managed/native boundary crossings.
Inspiration: "Using C++/CX in Desktop apps" by Pavel Y.
Open the project file as XML, and paste the following line under the first <PropertyGroup>:
<TargetPlatformVersion>10.0</TargetPlatformVersion>
Once you do that, the Add reference dialog will include UWP libraries, and the file type options in the "Browse..." dialog there will include .winmd.
Load the project, do Add reference/Browse, locate C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Windows.winmd, add that.
There are some helpful extension methods in the managed assembly System.Runtime.WindowsRuntime (e. g. IBuffer.AsStream()), but for some reason, it's not listed under Assemblies. To reference it, you'd need to edit the project file directly, and under the first <ItemGroup>, add the following:
<Reference Include="System.Runtime.WindowsRuntime" />
Unlike the guide states, you don't need to change the compilation target to x86 or x64; leave AnyCPU be.
For desktop .NET applications, this is sufficient. For ASP.NET, however, there's a catch. The way the ASP.NET runtime sets up its AppDomains not compatible with UWP. It's probably a bug deep down, but I've reported it, and a Microsoft rep said the whole thing was not a supported scenario to begin with.
Anyway, you have to change the LoaderOptimization policy of the AppDomain to SingleDomain. The quickest way to do so is via abusing a private method of AppDomain:
AppDomain ad = AppDomain.CurrentDomain;
MethodInfo mi = ad.GetType().GetMethod("SetupLoaderOptimization", BindingFlags.Instance | BindingFlags.NonPublic);
mi.Invoke(ad, new object[] { LoaderOptimization.SingleDomain });
A good place to do that would be in the app startup code.
A slightly less dangerous approach would involve creating a new AppDomain, which would inherit all setup properties from the current one but LoaderOptimization, which will be set to SingleDomain, and running the UWP dependent code in that domain. Like this:
AppDomain CreateUnsharingDomain()
{
AppDomain cad = AppDomain.CurrentDomain;
AppDomainSetup cads = cad.SetupInformation;
return AppDomain.CreateDomain("Dummy", cad.Evidence,
new AppDomainSetup
{
ApplicationName = cads.ApplicationName,
ApplicationBase = cads.ApplicationBase,
DynamicBase = cads.DynamicBase,
CachePath = cads.CachePath,
PrivateBinPath = cads.PrivateBinPath,
ShadowCopyDirectories = cads.ShadowCopyDirectories,
ShadowCopyFiles = cads.ShadowCopyFiles,
ApplicationTrust = cads.ApplicationTrust,
LoaderOptimization = LoaderOptimization.SingleDomain
});
//Not sure which other properties to copy...
}
CreateUnsharingDomain().DoCallBack(MyUWPDependentMethod);
Again, it would make sense to create the domain once and cache it for the app lifetime.
This approach might be faster than the one with the monkey-patched AppDomain. The MultiDomain optimization exists for a reason; if you leave most of the Web code in a MultiDomain world, the optimization will do its work as intended.
Inspiration: "Walkthrough: Using WinRT libraries from a Windows Desktop application" by David Moore.

Qt and Linking to an external DLL

I've developed a program and I am trying to make this program work with a controllable light source manufactured by some other company. I've emailed the company and they have agreed to send me their external library as a DLL.
I have developed all of my software using Qt 4.8.1 and it has been compiled using MSVC2008.
The controllable light's DLL was compiled in Visual Studio 2008 and was written in either C++ or C# (the manufacturer is uncertain). All I have been given is the DLL and a text file saying that I must:
Add the DLL as a reference to my project
Add using LightName; to the top of the class
Instantiate an instance of the object like so: LightName *ln = new LightName();
Call function void turnOn() with the newly created LightName instance.
Firstly, I find it odd that an external library requires me to instantiate an instance of their object especially when its for a simple piece of hardware.
Secondly, the other company has provided me with no interface files.
My question is:
How can I possibly link to a C++ DLL and expose the functions nested in this library without having an interface header file in a Qt environment? Is there someway to make an interface for an external library?
I have already attempted using QLibrary and doing the following:
QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
myFunction();
However, this doesn't work because the DLL I was given was not a C DLL and I have no interface so Qt doesn't have a clue about what symbols it needs to resolve.
I've attempted to display all the definitions exported from my DLL using the dumpbin /EXPORTS command. Unfortunately this was unable to produce anything. I was hoping that I would get some sort of mangled C++ from this that I could then unscramble to make my own header.
I've attempted to use the dependency walker(very useful tool) however it couldn't resolve any symbols to give me some function definitions.
QLibrary only helps you if the library has functions exported as C symbols. If that is C++ you can dump the symbol table and look if that is sufficient for you. Names must be demangled: try to look for dumpbin or similar. It is however possible that you can't do this, it depends on how the symbols have been defined. In that case you'll have to ask for the header: read this.
Well it's absolutely legal to ask you for "instantiating an instance of their object". It's been simply their design decision to make the dll interface object oriented (as contrary to plain extern "C"). QtCore.dll is just someone else's DLL too, and you are instantiating their objects all the time.
But it also means that you will have harder time to call the DLL. The symbols are not "C" symbols (you can't export class that way) so QLibrary can't do anything for you. You can try dumpbin /EXPORTS from the DLL and then tediously unmangle them to reconstruct the class declaration. Luckily there are tools to help you (even online)
But not providing a header file for such DLL is completely dumb in the first place.

VS2008 Update Web Reference creates naming conflicts in Reference.cs

I have a Web service which, when updated on one computer with VS2008 works perfectly fine, but on another computer does not. The critical difference is the contents of the auto-generated Reference.cs.
In the correctly functioning environment, the methods have fully qualified class names, refering to classes in a class library. However, in the problem environment, the class names are unqualified and partial classes are declared near the end of the file. E.g.
public string MyMethod(MyClass pr_Class)
...
public partial class MyClass {
}
versus
public string MyMethod(Class.Library.Namespace.MyClass pr_Class)
This causes errors such as:
'<ClassType>' is an ambiguous reference between <ClassLibraryNamespace>.ClassType and <WebReferenceNamespace>.ClassType
The code is under source control. Checking out to the working environment works straight away, checking out to the problem environment will only work if the reference.cs is manually edited to be like the working environments. Transferring the project manually from problem environment to the working one only requires an "Update Web Reference" to be performed to allow compilation. Both Reference.cs files claim to be auto-generated by the same tool version. The settings from the good environment have been exported to the other. No success so far...
Any ideas would be greatly appreciated!
Matt
Ok, so I have the answer. The working environment has a long forgotten extension library for importing web references. Customizing generated Web Service proxies explains the procedure. I'm new to the project and so had no idea about this!

How a native C++ plug-in DLL can load a private assembly located in a specific directory

I have a native C++ DLL which is used as a plug-in in another application. This DLL has an embedded manifest and depends on a private assembly located in a folder external to the application. The application fails to load my plug-in DLL because my DLL depends on a private assembly which is never found (it is not located in the application directory, nor in the winsxs folder but in my plug-in directory whose location is not controlled by the application). The question is: how is it possible to make the system find my private assembly which is located in my own specific directory ? As an analogy, I would need an equivalent of setDllDirectory() but for assemblies. Or another way so that the system find my private assembly.
Constraints:
Because my DLL is a plug-in, I cannot install anything in the directory and sub-directories of the application. I also cannot modify the behavior of the application.
I would like to avoid sharing the assembly in winsxs.
I also have to use an assembly and not a simple DLL (that I could load with LoadLibrary) to avoid version conflicts.
Thanks.
you need to have a global location where you could give a list of directories that form your (from java-terminology) class-path. Once you have this list just traverse the directories looking for dll's.
I have used the Registry in windows for this. An environment variable or the /etc folder under linux would also do.
This is how linkers do it, and this is one way that the .NET GAC does (it specifies a list of directories in a registry key).
-- edit 1 --
Your problem seems quite a uncomfortable mix, it's like trying to eat with a straight jacket on :P. Why don't you drop the assembly requirement and have a function in a native DLL that returns a version identifier (name-version), and then have some application logic to determine if it may use the DLL.
For example file-name (fn) = monkey-1-1 and a function call returns a struct:
struct version-id
{
const char * name;
int major_number;
int minor_number;
};
Then fn monkey-1-2 would not conflict on file-name or internal conversioning. and your programming conventions or application logic would make sure no adverse collisions occur.

Class will compile for Tests/Console but not in Asp.net application

I have a simple interface:
public interface IVisitorsLogController
{
List<VisitorsLog> GetVisitorsLog();
int GetUniqueSubscribersCount();
int GetVisitorsCount();
string GetVisitorsSummary();
}
the class VisitorsLogController implements this interface.
From a console application or a TestFixture - no problem - the console/test fixture compile perfectly.
However, from an Asp.Net web site (not application) in the same solution with this code in the code behind
private IVisitorsLogController ctl;
protected int GetUniqueMembersCount()
{
ctl = new VisitorsLogController();
return ctl.GetUniqueSubscribersCount();
}
the compiler throws this exception:
Error 1 'WebSiteBusinessRules.Interfaces.IVisitorsLogController'
does not contain a definition for
'GetUniqueSubscribersCount' and no
extension method
'GetUniqueSubscribersCount' accepting
a first argument of type
'WebSiteBusinessRules.Interfaces.IVisitorsLogController'
could be found (are you missing a
using directive or an assembly
reference?)
yet for this code in the same file:
protected static int GetVisitorsCount()
{
return VisitorsLogController.Instance.GetVisitorsCount(DateTime.Today);
}
the compiler compiles these lines without complaining. In fact if I add anything new to the Interface the compiler now complains when trying to compile the asp.net page.
It can't be a missing using directive or assembly reference otherwise both methods would fail.
This is driving me nuts!
Any thoughts please?
Thanks,
Jeremy
Out of interest, can you compile the following line:
ctl = VisitorsLogController.Instance;
? I'm just wondering if somehow you've got two interfaces named the same thing.
What does Intellisense prompt you with when you type ctl. and press Ctrl-Space?
It would seem the other important bit of code would be VisitorsLogController, wouldn't it? It looks like VisitorsLogController is implementing a different IVistorsLogController interface.
Right clicking and GoTo Definition should clear things up, I think.
I would start by checking the namespaces on each of the files involved and make sure that you don't have a conflict or a namespace that you are not expecting.
The solution contains the web site and three class projects (Data Layer, Service Layer and Core Services). They are added as references to the web site as Projects.
I had compiled the solution at one point for Release - published the site, and then changed the config to Debug.
Evidently what had happened was that the Release dll's in the /bin file of the website were not being overwritten by the new Debug dll's. I manually deleted all the files in the /bin directory, and lo and behold - everything compiled perfectly.
So Mark and John - you were both spot on - I effectively did have two interfaces named the same thing.
Thanks very much for your help - if you hadn't given me these pointers I would never have finally worked it out.

Resources