I am creating a wpf application which need to interop with a third party tool(COM). the tool will be launched first and I will give some input in the tool. then he will launch my wpf application where again some input will be given.my wpf app need to interop with the running instance of a tool and execute some methods in the tool and get the result to my app.I tried using RCW. but RCW is just a proxy. I need a running instance of a tool to interact with. Can anybody help me out????????????
Edit: There is existing C++ code which does this, so how can this be translated to C#?
bool DisDriver::Create(CLSID clsid, DWORD ClsContext, LPCTSTR ServerName)
{
hRet = ::CoCreateInstanceEx(clsid,NULL,dwClsContext,strServerName==NULL?NULL:(&svrinfo),1,&multiqi);
if(hRet!=S_OK) {
#ifdef XYDISPDRIVER_DEBUG
_tprintf(_T("CoCreateInstance failed:"),hRet);
#endif
return false;
}
pDisp = (IDispatch*)(multiqi.pItf);
}
Type.GetType(prog.id),Activator.CreateInstance(type) will actually get the running instance of a com program which is the required one for this issue.
Related
I'm currently building a Xamarin based mobile application. For that project, I have created a PCL project with framework 4.5. I'm using VS 2013 as the development IDE. Now I want add a WCF service reference to this PCL. While adding service reference to this PCL project, I noticed that generation of asynchronous operation is disabled. Please check the image for more detail.
I added the BCL.Async package via Nuget to the project. But still I can't access the Task based operation from the radiobutton list (its disabled).
So is there any way to generate task based asynchronous operation in service client?
Hate to break it to you but you cannot generate Task based WCF client in Xamarin. The reason is Xamarin or Mono implements the Silverlight set which is a limited WCF implementation. As such you need to use SLSVCUTIL.exe instead(Adding a service reference in Xamarin would use this tool). The silverlight WCF client generated by SLSVCUTIL will be async based only.
All is not lost! You can easily wrap the silverlight async client into a task based client using the Task.FromAsync method.
A sample taken from the Xamarin website:
public async Task<List<TodoItem>> RefreshDataAsync ()
{
...
var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
foreach (var item in todoItems) {
Items.Add (FromWCFServiceTodoItem (item));
}
...
}
https://developer.xamarin.com/guides/xamarin-forms/web-services/consuming/wcf/
Now if someone can figure out how to catch an Fault Exception when wrapping in Tasks that would be awesome!
I've not used Xamarin before, but I'll assume APM and maybe Tasks are actually supported in it and this is just a Visual Studio limitation. Try using wsdl.exe manually to generate code. This is the tool Visual Studio calls when you add a service reference.
You'll need to pass either newAsync (Tasks) or oldAsync (APM) through the /parameters switch.
I have an out of process server based on the ATL Service VC++2010 Template. Now I wont to extend his COM Interface by dynamically loading additional dlls that contain its own COM Classes.
The dll to load is based on ATL dll VC++2010 Template, containing a simple ATL-object "IMModule". I changed the corresponding .rgs file to connect the class from the dll to the EXE server by adding a LocalServer section and the server's AppID as follows:
HKCR
{
NoRemove CLSID
{
ForceRemove {59276614-A811-4D27-B131-514656E643D3} = s 'IMModule Class'
{
ForceRemove Programmable
LocalServer32 = s 'path to the service exe'
{
val ServerExecutable = s 'path to the service exe'
}
TypeLib = s '{250685C7-CBD3-4FF8-A3A6-2AF668794CFC}'
Version = s '1.0'
val AppID = s '{7EFD508A-53C6-4EA0-B21A-D29277B86CBC}'
}
}
}
In a dll init() method called by the service after loading the dll I call CoRegisterClassObject to register the IMModule class object. But im not sure how to obtain the IUnknown interface pointer (second parameter to CoRegisterClassObject ). I tried the following:
CIMModule::_ClassFactoryCreatorClass* pClassFak =
new CIMModule::_ClassFactoryCreatorClass;
IUnknown* pUnk;
HRESULT hr =
pClassFak->CreateInstance(CIMModule::_ClassFactoryCreatorClass::CreateInstance,
IID_IIMModule, (LPVOID*)&pUnk);
But the call to CreateInstance fails with E_NOINTERFACE.
So, how to register my IMModule class implemented inside a dll to be available for COM clients from my out of process server?
With the help from Roman.R I get the behavior that I need. I can't say thank you enough, #roman-r. I will precisely describe what I did, so maybe someone can retrace the steps and give me some response.
First I created an ATL based Windows service (named UmbrellaService). Inside UmbrellaService I added a simple ATL-Object named Control and added the method:
FindMeAnInterface(BSTR moduleName, IDispatch** ppDispach);
Thats all with the VC++ Wizard. Then I fixed the Control.rgs file by adding:
val AppID = s '%APPID%'
Why has VC++ still such bugs after 17 years of evolution? (See
CoCreateInstance does not start or connect to ATL COM service)
Then I created an ATL-dll Project, named MyModule, with a "Module"
simple ATL-Object inside. The Module class has a method
testMethod (LONG a, LONG b, LONG* sum)"
The MyModule dll is registered as a in-proc server. Furthermore the dll has some classes
that makes the dll a plugin as I need it.
In the PreMessageLoop method of the UmbrellaService the MyModule dll will be loaded with LoadLibrary and through GetProcAddress the address of a factory creation method is obtained. The factory creation method returns a plugin-dependent FactoryClass that acts as a plugin entry point. This is my COM-independent plugin mechanism.
Now to export the module interface from the plugin dll through the UmbrellaService interface I did the following: On the FactoryClass I add the method:
IDispatch* getInterface();
In getInterface method I call
CoCreateInstance(__uuidof(Module), NULL , CLSCTX_INPROC_SERVER , __uuidof(IDispatch), (VOID**) &pDispatch);
and return the obtained IDispatch interface. The FactoryClass::getInterface method is called inside the Control::FindMeAnInterface method of the UmbrellaService after comparing the name passed to FindMeAnInterface with the name provided by the FactoryClass. FindMeAnInterface returns the then obtained IDispatch pointer to the client.
On the client side I import the tlb file from the UmbrellaService and the tlb from the apropriate plugin dll. I call testMethod as follows:
IControlPtr pControl(__uuidof(Control));
_bstr_t moduleName("Module");
IDispatchPtr moduleDisp = pControl->FindMeAnInterface(moduleName);
IModulePtr pModule(moduleDisp );
LONG res = pModule->testMethod(42,23);
This all works indeed, but I am not sure if this is the way to do it. Did I miss something about reference counting? Will the plugin DLL be loaded two times? First time through my plugin mechanism and second time through CoCreateInstance? Something else I should note?
Thanks for your help!
I could not find my code so far. But I did check one of my favorite websites, The Code Project. It used to be popular especially with older technologies like COM (yes, it is). I hope you're already convinced that you have to use COM instead of new WFC or another technology.
Please check good documentation and sample code # ATL COM EXE doc. I believe I used this web page as a start of my past project.
Good luck and have fun.
We have an app the requires Full Trust because of a Chilkat .NET 3.5 DLL
This has not been a huge issue, however we would like to submit our app to the: Windows Web Application Gallery and it must be Medium Trust.
So to make it medium trust all we need to do is
remove the reference to the DLL
comment out the methods that tie into that code
Rather than making 2 different versions of the app, what is the best approach to remove the reference to the DLL for one version of the app?
thanks!
That’s not a simple one, but my first thoughts on this would be to abstract it out with and interface and late bind it in, but you must remember to check you have full trust when you load it or it might not work.
static class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.Load("ExampleAssembly, Version=1.0.0.0, Culture=en, PublicKeyToken=a5d015c7d5a0b012");
IFullTrustAddin addin = asm.CreateInstance("Namespace.MyChilkatWrapper") as IFullTrustAddin;
if (addin == null)
return;
addin.DoSomething();
}
}
interface IFullTrustAddin
{
void DoSomething();
}
I have a solution with several projects most of which are code or control libraries. I have a main windows forms application that references and uses these libraries. What i am trying to do is create a 2nd windows application that extends the main one, but i would like to be able to deploy them as separate exe's.
When i try to add a reference to the new app referencing the main app; all seems fine until i try to run the new app i get several error msgs similar to below:
Error 1 Could not find file 'ADODB.dll' referenced by assembly 'D:\Visual Studio 2005\Projects\X\XX\bin\Debug\XXX.exe.manifest'. <newAppName>
i have tried adding references to all the dll's in the error messages and they are still listed when i try to run the new app. I thought of a few work arounds but they require user changes to maintain separate exe's at deployment. I would like to avoid this if possible. Any ideas?
Thanks in advance, Jeff
Your windows forms applications should not be the point that you extend, the exe files should really just be a shell for launching your process (as much as possible anyways). So this response doesn't answer your specific problem of reference exes as this is not considered good practice.
All the extensions should be made to your code or control libraries off a known interface or contract. Generally the process for extending applications like this is to use alternate or additional DLLs which are loaded at runtime.
Say you have an application called clock which is to display the time.
You can structure your application with a set of contracts (or interfaces) in a referenceable DLL "Clock.Contracts.dll":
public interface ITimeService
{
public string Name { get; }
public Date GetTime();
}
You then have each implementation of this in another DLL ("Clock.LocalComputer.dll", "Clock.InternetTime.dll"
public class LocalTime : ITimeService
{
public string Name
{ get { return "Local Time"; }}
public Date GetTime()
{ return Date.Now; }
}
In the UI/EXE you always reference the interface don't call the implementation.
How do you get an instance of the implementing class, using Reflection to identify if a class in a DLL implements the interface and Activator.CreateInstance to generate the class.
http://gsraj.tripod.com/dotnet/reflection.html
There are patterns like Inversion of Control and Dependency Injection which help to address these things in a standardized way in your application. 3rd party libraries like Castle Windsor, Spring can assist. A google search on these will give you some reading material.
I will say that it can take a while to fully get your head around these things.
ok i found a reasonable work around. Basically you add all the reused forms as existing items, but instead of just clicking add you click the drop down arrow and choose add as link.
It would be great to redesign as JTew suggested above but this gets me where i need to be without having to move code.
You can find more information here
Thanks for all your time looking this over and hopefully is helpful to more
Jeff Spo
We are adapting our client side relatively complicated application (ActiveX / .net / Delphi / C++ / COM ) to use SxS to achieve non admin deployment and isolation from older versions of our product.
We were able to achieve this goal for almost all our in proc components such as our .net ui, Delphi ui, and the COM servers we use in proc by composing a manifest file which described all the libraries used by our process, with no registration on the client of any of the components (almost).
And here comes the almost part:
At the moment, our application invokes (from it's c++ portion) an out of proc ActiveX server (Delphi ActiveX EXE), which in turn itself invokes another set of out of proc ActiveX servers (third party plugins, any thing goes here, Delphi, C++, any thing as long as it's out of proc ActiveX EXE and implements our interfaces).
As we know SxS does not support out of proc ActiveX servers. And we can't use these objects as in proc com servers in our main process because that would require a major rewrite of our application and even worst, a break of our public facing API which is used by third party tools and vendors, an api break which we can't allow.
We have stumbled on this article which describes how IHTMLDocument2 can be extracted from an Internet Explorer window running in a separate process. Which made us think of this approach:
We would create a secondary satellite application / process which will run the ActiveX as in process server.
Then we will use LresultFromObject and ObjectFromLresult to transfer a reference of the ActiveX object from the satellite application to the main application process. The satellite application will have it's own manifest file which will allow it to run in SxS mode.
Same approach will be taken to communicate between this Delphi ActiveX EXE and the third party AciveX EXE Plugins
There is an alternative solution, which for the moment we do not prefer over the proposed solution above which is to use .net remoting and .net com proxy classes to open the communication channel between the two processes, by translating the com request to .net remoting, and back to com on the second process.
So here comes the question:
What do you think about this approach ?
Do you see a better solution to the problem ?
It is possible to do. What is needed:
An application needs to start a server itself rather than relying on COM to do it. You don't need the extra indirection provided by the registry, just use CreateProcess().
A server should register its class factories in its main() method with CoRegisterClassObject().
Important: the CLSID it uses for each factory should be altered to be unique for each service instance. This ensures that the client connects to the correct server. I simply XOR the process ID with a class factory CLSID. The client knows the process ID as well so can make the same alteration.
The application should call CoCreateInstance() in a loop with a Sleep() call to wait for the object factory to appear. Don't declare failure until at least 60 seconds have passed (that bit me).
Both the application and the server need a manifest that contains a <file> element for each proxy/stub DLL and <comInterfaceExternProxyStub> elements for each interface that is remoted.
Alex,
nobugz is right, you can access the Running Object Table to create an instance of a COM Object from a currently running process of your Delphi automation exe.
However I have found a big issue that I cant explain. I can only access the object via the variant dispatch method when working this way.
Basically if my Active X exe is not registered, I get an "Interface Not Supported" error if I try to instance the object through interfaces for example:
WebUpdate : IAutomation;
WebUpdate := CoAutomation.Create; <-- Wont Work Error
WebUpdate : Variant;
WebUpdate := CreateOleObject('WebUpdate.Automation'); <-- Works Fine
If I register the active x exe using regserver the problem goes away!!
Go Figure!