I have a query regarding dotnet framework.
Suppose I have a class library DLL for my clients, which have set of methods. For some reason, I have removed some methods, and deliver it to my client. How I could ensure that my client will not get any error in their code because of removed of methods as they are using it.
If you remove the methods they will certainly get an error so marking them as obsolete would be the best solution to go. You will break compatibility between the code using different versions of your DLL which is quite bad and unpleasant for clients.
Related
I'm working with one application that that has and C# API. This program has different versions of it. But the api stays the same through its versions.
So i have written a managed code to one of its versions, and now i want to run the same code at different version of the application at runtime where i exactly know witch version of the app is running.
Question is:
Is it possible to replace assembly version and dll location at run time without writing unmanaged code using reflections?
Yes, you can use Assembly.LoadFrom to load an assembly. You can then use reflection to go thru the types of said assembly and call methods.
To avoid needing to use reflection for everything there should be a shared interface-assembly that define your api. There should also be a single entry point to the API. So you can use reflection find the class that implements the entry-interface, create an instance of this class and cast it to the interface. That lets the rest of the code use actual types.
You still need to be careful however, if there is any miss match between the interface and the actual types, you will get an runtime exception. You will not get an exception when the interface method is called (as might be expected), but when the method that calls the interface method is called. This due to the jitter resolving types when a method is compiled, and this is done the first time it is called.
I am using Unity 3D engine. Its API is located in UnityEngine.dll.
Is there a way to block/forbid/make sure some of it's API methods can't be used? It contains some methods that shouldn't be used in my project by other team members even if they accidentally try to. Can this be done in C#?
UPDATE: I have no access to code of the library.
One thing to do could be offering your team members a facade DLL that will only expose the 'allowed' methods.
You might write some sort of analyzer that checks your scripts for forbidden API calls. Options:
Analyze the source code by iterating through all Assets of type MonoScript and identify rule violations using Regex tests (easy to implement as long as you are only looking for specific methods, but inaccurate)
Analyze the compiled code on IL level (accurate but tricky to implement)
You can then have this analyzer invoked automatically:
After every compilation by using DidReloadScripts attribute
After every build by using PostProcessBuildAttribute
I'm not sure if there's a way to make the build fail during post processing, but maybe throwing an Exception when a rule violation is detected will do it.
I have a large windows forms project that was ported from MFC to WinForms. The business logic is all in C++ so we have a couple of assemblies written using C++/CLI to wrap the unmanaged code. The original port was done using Visual Studio 2005 and .net 2.1. We have migrated it to VS2010 and .net 4.0. We are currently maintaining both versions. Everything was fine until I added a header file for a class so I could utilize one of its methods. Just adding the header caused the error:
Error 21 error LNK2022: metadata operation failed (80131195) : Custom attributes are not consistent: (0x0c0004c7). c:\XXXX\Project\AAAAPI.obj
Project.API
There are two clases involve3 here:
AAAAAPI.cpp with header AAAAAPI.h
BBBBAPI.cpp with header BBBBAPI.h
if AAAAAPI only included AAAAPI.h
and BBBBAPI.cpp only includes BBBBAPI.h everything links and runs as expexcted
But when I add AAAAPI.h to BBBBAPI.cpp I get the above error. What is interesting is it is not compalining about BBBAPI.OBJ but AAAAPI.OBJ
Also If I remove AAAAAPI.h from BBBBAPI.h (which works as above) and add BBBBAPI.H to AAAAPI.cpp it works. So the same two headers in one cpp filr work and in another they do not work.
I hope this is enough information for you to understand my problem. The code involved it part of a very large system and it would be difficult to add more detail about what the code is doing. Just note that all I have to do is add a header file which is just a class definition, no executable code to cause the errors.
Any halp would be greatly apreciated.
I've gotten this error when I had a #define that affected a class definition, and the class definition ended up different depending on which file it was included from. Check that you don't have any #defines or similar that might be affecting your classes.
You'll have to post code if you want a firmer answer. It's impossible to diagnose code issues without seeing the code.
I’m working with a .NET 4 application written mostly in C#. The application has a user interface, but it also has an automation interface that allows the features of the application to be exploited directly from a .NET client. It also supports automation via COM, and for this there are “COM adapter” DLLs that present the classes/methods in the “real” DLLs in a COM-friendly way.
For example, let’s say the API for the bulk of the functionality is in a DLL called “Alpha.DLL”: a .NET client can simply reference that DLL directly, but a separate DLL called “Alpha.Com.DLL” is provided for use by COM clients (e.g. VBA).
There are 3 such COM adapter DLLs, and while two work fine, I simply cannot get the last one to work correctly.
The problem DLL only has two classes defined within it, and while I can instantiate one of them from a COM client such as VBScript, I get an error when I try to instantiate the other. The error I get is:
-2146234304 (0x80131040) Automation Error
I can instantiate the same class from .NET code, just not from a COM client.
I’ve tried using FUSLOGVW.EXE to look for assembly-loading errors, but there don’t seem to be any (and in any case, the fact that I can instantiate the other class from the same DLL suggests that it’s not the DLL itself that can’t be found/loaded?).
I’ve tried attaching a debugger and putting a breakpoint inside the constructor for the offending class, but it doesn’t get hit when I try to instantiate the class from VBScript. (A breakpoint in the constructor of the class that works does get hit).
I’ve checked the registry entries for the class I’m trying to instantiate, and I can’t see any problem. The GUIDs and version numbers all seem to match up.
I’m all out of ideas, and at the end of my tether, and I’d be extremely grateful for some help…
-2146234304 (0x80131040) Automation Error
The common problem with using .NET code from a COM client like VBA is that .NET exceptions get rather difficult to diagnose. You have to make do with an often cryptic HRESULT error code, you don't get the Holy Stack trace to see how code blew up. This exception is a doozy like that, it is FUSION_E_REF_DEF_MISMATCH, you can find these HRESULT codes in the CorError.h SDK include file.
You'd normally get the easier to interpret exception message "The located assembly's manifest definition does not match the assembly reference". And the stack trace to tell you what type caused this exception so you'll know what assembly is the problem. Nothing like that when this failed when called from VBA.
It is otherwise an every-day .NET mishap, the CLR found your assembly but its [AssemblyVersion] does not match the reference assembly's version that your code was compiled with. COM certainly increases the odds that this can go wrong, the version is recorded in the registry when you register the assembly with Regasm.exe. Forgetting to re-register if you do it by hand instead of letting the build system take care of it is a very easy oversight. Also very easy to copy dependent DLLs in the client EXE's directory, so the CLR can find them, and forgetting to update them.
Fuslogvw.exe does show this kind of mishap, hard to guess why you don't see anything. The backup plan is to use SysInternals' Process Monitor. It also shows you how the client is reading the registry, another thing that often goes wrong in COM. And you'll see it locating the DLL from the registry key so you'll have a shot at guessing why it found an old one.
Stay out of trouble by using the GAC, often necessary anyway to help the CLR to find dependent assemblies and to solve COM's rather severe DLL Hell problem. And strongly consider using the .NET 4 AppDomain.FirstChanceException event. Good to log exceptions before they turn undiagnosable in the COM client.
please check first
your com dll is placed into GAC
you dont't forget about regasm
http://www.jagjot.com/2014/01/register-c-vb-net-dll-regasm-gacutil/
check cpu architecture
does your com dll depends on anything outside GAC?
Aaargh. I found the problem. I said in my question:
I’ve checked the registry entries for the class I’m trying to instantiate, and I can’t see any problem. The GUIDs and version numbers all seem to match up.
...which was true. However, what I had not noticed was that in the registry definition of one of my classes, the public key token was wrong.
This explains why one class could be instantiated while the other could not, and possibly why there was nothing in the FUSLOGVW log (because the assembly was loaded OK when an instance of the "good" class was created).
Thanks for your help, Hans and Dimzon.
I have a WCF service that requires me to add the folowing to Reference.svcmap
<NamespaceMappings>
<NamespaceMapping TargetNamespace="http://schemas.datacontract.org/2004/07/System.DirectoryServices"
ClrNamespace="System.DirectoryServices" />
</NamespaceMappings>
If I don't have that line I get the following error:
Warning 1 Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension:
System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: ISerializable type with data contract name 'DirectoryServicesCOMException'
in namespace 'http://schemas.datacontract.org/2004/07/System.DirectoryServices'
cannot be imported. The data contract namespace cannot be customized for
ISerializable types and the generated namespace
'DomainManagement.Console.UserManagementProxy' does not match the required CLR
namespace 'System.DirectoryServices'. Check if the required namespace has been
mapped to a different data contract namespace and consider mapping it
explicitly using the namespaces collection.
XPath to Error Source:
//wsdl:definitions[#targetNamespace='http://example.com/v1']/wsdl:portType[#name='IUserManagement']
I also know having a common DLL between the client and server will also solve the issue but I do not want to have to require any client to also have the accompanying DLL to communicate with the service.
I understand the issue, and the fix (both dll and editing the file). What I would like to know is: Is there anything I can do on the Host side so every client that subscribes to this service does not need to any extra configuration of the service after generating the proxy in visual studio? (i.e. Using SvcUtil and using the /n:http://schemas.datacontract.org/2004/07/System.DirectoryServices,System.DirectoryServices parameter is not a preferred option)
I think this is simply down to the fact that some types "don't serialize well". Trying to pass a NameValueCollection across WCF (prior to VS2010) produced exactly the same error as you are seeing, despite it being serializable. Another one that I've seen crop up from time to time is the SqlException (see here).
Alas I'm not aware of any server-side solutions. I find that providing clients with a "service interface" DLL to be the cleanest approach - it avoids having to generate client-side code via svcutil/add service reference, but you seem to have your reasons for not doing this. The alternative would be to refactor your server-side code to avoid passing around a DirectoryServicesCOMException. You could try Googling the "NameValueCollection WCF serialization" issue and see if any of the suggested workarounds from back then might be applicable to your scenario. I suspect not though, as this was caused by the way it implemented certain interfaces internally.