COM Codebase Location - How to pick which version to use? - c++

I have needed to modify code in a C# DLL and use it within a C++ application. I am not savvy at all in C++, so if something isn't clear let me know.
I've registered the C# assembly using:
regasm file.dll /tlb:file.dll /codebase
However, when I try to use this in the c++ application:
CLSID clsid;
CLSIDFromProgID(L"MyApp.MyClass", &clsid);
HRESULT hr = CoCreateInstance(clsid,NULL, CLSCTX_INPROC_SERVER ,IID_MyClass, reinterpret_cast<void**>(&myclass));
hr returns with 0x8013151a: access to this member is denied
I've noticed that in registry, I see multiple versions of the C# dll (with Codebase pointing to different dll locations).
I think the problem is because it's not using the correct dll. (I could be completely wrong).
My question is this, how do you know which version of the dll it's trying to load?
Thanks in advance.

Pretty unlikely that this is a DLL Hell problem. You can double-check by using the debugger's Debug + Windows + Modules window, it shows you the path of the DLL. Keep your registry clean by letting MSBuild register the component, Project + Properties, Build tab, "Register for COM interop" option. VS must run elevated.
This is a MethodAccessException, always a coding bug. Psychic debugging required without seeing your code but the simplest explanation is that your C# class' default constructor is not public.

Related

How to debug an ActiveX application in VB Script using VB classic IDE

We have written an ActiveX application in VB 6.0 which hosts in VC++ dll. We want to debug that code using the VB classic IDE. We are unable to debug it, because it does not hit the breakpoint we have set. How do I debug an ActiveX application using the VB classic IDE?
If you start your ActiveX DLL project in the VB 6 IDE, and then create components from some other application (your C++ application, or testing it via another VB Project or any other language which can use the COM object), it should load the object in the debugger and you can set breakpoints and look at variables while running. Refer to "Testing and Debugging ActiveX Components" in the Visual Basic 6 Concepts Guide.
If that's not working for you, can you make a MCVE of the problem you're having, by creating a new simple ActiveX DLL component and calling it from a separate project (you may want to try calling it from more than one language), and reproduce the issue you're having to clarify what isn't working for you?
You probably have "Break on Unhandled Errors" selected in the IDE. If you do, then any error in your ActiveX object will set the breakpoint on the line of the client that accesses the object, typically a method call. If this is the behavior that you are getting ("does not hit the breakpoint that we have set" doesn't make this clear), then that is almost certainly the problem.
In any case, I would suggest that you check this. You should have "Break in Class Module" selected. For a full explanation of the different ways to handle breakpoints, and how to change the settings, see this post. Here also is the doc on the subject.

C++ : Dll injection. Why CreateRemoteThread() fail on Notepad?

I'm pretty new to DLL injection, doing this by curiosty and because I want to create an overlay in a game, without modifying his source code.
But for now, I'm stuck with a basic DLL injection : the one using CreateRemoteThread().
I followed this tutorial (in french, be carefull):
http://xevia.webege.com/old/atoray/2010/06180.php
What I have done :
Injection works fine on a basic program Target.exe (see Xevia's link)
I can see DLL loaded by a process with EnumProcessModules()
After the injection in Target.exe, I can see that my "Hook.dll" has been added.
[edit] Checked the exe version : both notepad and my injector are 32-bits
But when I inject the dll in other processes, it doesn't seems to work, even if CreateRemoteThread() does not return NULL.
So I've checked many posts, including this one: How do I prevent DLL injection
And this one : C++ - CreateRemoteThread DLL Injection [Windows 7] (tried the absolute path, without success)
And many others, without being able to really point what was wrong. So I invoke SO-gods.
1) Could it be an access-rights issue ?
2) Could it be my method of injection, too classical ? Which one should I try ?
3) [Topic question] Why my dll isn't injected in Notepad with CreateRemoteThread?
Thanks for your time.
[open to any grammar/formulation edit]
It works!
What I needed to change :
Build in x86 in order to match with target app
Use an absolute path
I did both but forgot to change my absolute path when switching between x86/x64...
Thanks to Adrian Roman, who put me in the right way.

How can we unit test our c++ COM code without registering the dlls?

We are trying to add unit testing to out legacy c++ COM application. We also need our build machines to be able to runt he unit tests to ensure each build hasn't introduced errors. However we don't want the build machines to have to register the com dlls so that one build machine can build multiple versions in parallel.
We assumed that we could change to using registration free com with manifest files, but i am having a very difficult time getting that to work. Not on our code base yet but just on the basic example provided by Microsoft.
I've been using this page http://msdn.microsoft.com/en-us/library/ms973913.aspx#rfacomwalk_topic8
and it simply won't work, when i try to run with the dll unregistered to use the manifest files, i get the "Class not registered error"
The samples they provide work fine (using c++ com server and c++ client), however when i rebuild them they don't work.
We are using Visual Studio 2013 and so it looks to me like there has been a large change in the way that registration free com works, which makes this tutorial incompatible with the newer compiler.
Can anyone point me to resources on using registration free com with the latest version of visual studio? To further complicate things in our own app when i get there we are using VS 2013 but targeting the 2010 compiler, hopefully that won't make to much difference.
Also if there's a better way of running c++ unit tests on com components without registering than manifest files i would like to hear about those as well.
Thanks for your help.
Probably too late for the OP but for anyone else that comes across this question, there is an article by Samuel Jack on this here... which may or may not help future readers...
See http://blog.functionalfun.net/2012/09/a-quick-guide-to-registration-free-com.html
You could implement your own version of CoCreateInstance that take an extra DLL path parameter. The code would be something like this (error handling and other details omitted for brevity):
HRESULT CoCreateInstanceForTest(dllPath, rclsid, riid, ppv)
{
HINSTANCE hinst = LoadLibrary(dllPath); // TODO: Maybe it is already loaded
dllGetClassObject = GetProcAddress(hinst, "DllGetClassObject");
return dllGetClassObject(rclsid, riid, ppv);
}
Besides error handling, you also need to keep track of the DLLs you already loaded. Use a list or array in which each element has a tuple to track this. At some point you might want to unload all or some of them.
Of course, I am assuming these are inproc COM servers.

One C++ client fails to load with our new COM registered .NET .dll, another works

We have an old C/C++ .dll that a customer accesses via COM.
We have tried to replace our old .dll with a new one written i .NET.
Customer cannot recompile their client so it is important that the old .dll can be replaced simply by COM unregister / register new (using regsvr32 / regasm).
We believe we have built the .NET .dll with the same COM interface as the old; GUID's, names, dispid's etc. all match. We have verified this by writing our own C++ test application and it continues to work when we unregister old .dll / register new one.
The problem is that the customer's client failes to start.
Strangely if we leave the old .dll registered (e.g. both .dll's are registerd) it works; The customer's application starts and calls methods in our new .dll. But as soon as we unregister the old .dll the application fails to start again.
We have tried different ways to register the new .dll; using regasm with /codebase option, /tbl, etc.
If I inspect with OLE/COM Viewer I can see some minor differences between new and old .dll, for example the type library "name" differs. But I suppose since our own C++ test client works with either .dll the COM interfaces are enough similar?
Please, anyone has any idea? How is it possible for one C++ client to load with our new .dll while another fails? Why do both work if we leave the old .dll registered in parallel to the new one? Is there any explanation why the two C++ clients behave differently?
UPDATE:
The error message in the client says:
"failed when running: CLSIDFromProgID. Check if [myDll].dll is registered."
Kind Regards P.T
There are many possibilities. First, ensure you are registering the type library of your new DLL. The old one may be doing it as part of DllRegisterServer, but AFAIK, .Net DLLs do not. Register it with REGTLB.exe.
Also check the threading models are the same in both DLLs.
If neither of those help, I suggest you keep on until OLEVIEW says they are identical - you never know what the client is doing which is different from yours.

How can I run Visual Basic code in a running Visual Basic 6.0 process (e.g. MSVBVM60.DLL)?

I'm working on debugging a legacy Visual Basic 6.0 application; the application was built into native code, but unfortunately we just have the binaries, but no source code. So I'm rather limited as far as modifications to the program go.
My final goal is to get the value of the 'Name' property of some controls given their HWND. I can easily write VisualBasic code to do this, but unfortunately I don't see how to execute this code in the context of the running application.
My first attempt was to create an ActiveX DLL in VisualBasic which exposes my 'controlNameForHWND' function. At runtime, I then had a little utility injected a second helper DLL into the VB running process, and that helper DLL then called CoCreateInstance so that my ActiveX control (which features the 'controlNameForHWND' function I wrote in VB) is instantiated inside the process of the application.
This worked well, but unfortunately the ActiveX control is apparently not executed in the same context as the application to be debugged. For instance, the global App.hInstance value is different, the array returned by the global Forms array is always empty, and so on. So all my VisualBasic script code is running in a parallel universe. Bad luck. :-/
Does anybody else have ideas how to be able to "inject" VisualBasic code into a VB6 process? Looking at the process using Process Explorer shows that the library MSVBVM60.DLL is loaded (the Microsoft Visual Basic Virtual Machine), but not e.g. VBA.DLL. The latter would be interesting since it exports an undocumented EbExecuteLine function to execute script statements.
I'm running a bit low on ideas, so I'm grateful for the craziest ideas, too. :-)
A VB6 ActiveX DLL will run in the client process, but it won't have access to the Forms collection of the client process. I think the App.hInstance should return the same value though.
If you are debugging your DLL in the VB6 IDE debugger, that will cause it to run in a separate process. That debugger does some crazy things. You might be better to build a PDB file from the ActiveX DLL and debug in the Visual C++ debugger.