I have a VB.NET COM class with a Shared property, like ABC. The problem is the component is used by several C++ COM exe, so its my understanding that they each will get their own assembly load, and the Shared property will be unique to each EXE. Is there a way to get for this assembly a cross EXE shared property ?
Tx.
Create a Windows Service application and either register your shared singleton object in ROT or simply use RegisterActiveObject/RevokeActiveObject to register it with a unique guid.
Accordingly, use ROT or GetActiveObject to obtain a COM proxy to this object from any other place. You'd need to manually start the windows service if the object has not been registered.
Updated, it's also possible to implement IClassFactory on the singleton object (which would return itself). The service would register the singleton via CoRegisterClassObject, resembling the out-of-proc server behavior. The initial service activation would still be required.
Finally, perhaps the simplest solution is to register the assembly as an out-of-proc DLL surrogate. I haven't tried that, but it ought to be easy with [ComRegisterFunction] / [ComUnregisterFunction] custom interop registration.
Updated, here is an example of using a surrogate process.
What you are describing would be "easily" accomplished in native COM by creating an out-of-process COM server (also commonly referred to as an ActiveX EXE). As the name implies, an out-of-process COM server runs in its own process and serves it's methods via a COM interface. If multiple clients use the COM server simultaneously, they both share the same server process, so any global data within that process is shared between all of the clients.
Unfortunately, .NET does not provide any mechanism for creating an out-of-process COM server. All COM visible .NET assemblies act as in-process COM libraries, so each client using it has it's own set of global data within their own processes.
The only alternative is to create a standard in-process COM-visible library, but have it just be a pass-through wrapper which calls out to some other process. Inter-process communication in .NET is typically handled with WCF, so the typical solution would be to have a WCF service running in the back-end with which the COM-visible library communicates. If you don't want to use WCF, you could also look at .NET Remoting or raw TCP/IP sockets.
Here's a chicken-scratch diagram to help visualize what I mean:
Related
We've a WCF / ASP.NET hosted web service. The data types in the service contract use XSD.exe generated types, and hence are decorated with XmlSerialization attributes. We created a client for it using SvcUtil, including using the /ser:XmlSerializer parameter. Been working for many years.
We just upgraded our build scripts to use VS 2012, and the v 8.0A Windows/.NET SDK NETFX 4.0 Tools version of SvcUtil.exe (v 4.0.30319.17929).
We are now seeing a strange error message when our client (built w/ VS 2012 and the new 8.0A SvcUtil) attempts to call the WCF service:
Type 'System.Threading.Tasks.Task1[MyNamespace.MyClient.MyDataStructure]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
This error prevents our application from being able to call the WCF service, and we're stuck.
I note that we are not passing a parameter to SvcUtil for /async. I also note that the SvcUtil help for .NET SDK 8.0A (v 4.0.30319.17929) indicates that the default is to generate synchronous and task-based asynchronous method signatures. Is there some built-in disconnect between System.Threading.Task and XmlSerializer ?
Suggestions for how we can prevent the runtime from somehow thinking we're using DataContractSerialization when we intend XmlSerialization?
Have an answer from Microsoft, posted here.
Short is that /syncOnly will be needed if you intend to build with .NET 4.5 SvcUtil but target the .NET 4 runtime.
I have inherited an application that consists of a bunch of exe files that communicate using COM and COleDispatchDriver. There is one main "client" exe, and several "server" executables that provide services.
At the moment, the client process starts the servers using COleDispatchDriver::CreateDispatch(), passing an application ID that gets resolved to a class ID. The problem with this is that it relies on the COM server being registered (a potential point of failure). It can also be problematic if there are several different versions of the COM server exes on the machine.
I'd like to make this less fragile without having to completely rearchitect the application at this point. Is there any way to keep the same mechanism for communication, but explicitly start a specific server application? The client knows where the server apps are and what they are called (they are alongside the client in the same directory).
It's a bit more tricky but you can manually marshal the interfaces you need yourself. Get the client to fire the server up which creates the client object and marshalls an interface of it back to the client using CoMarshallInterface().
Once the client has marshalled the interface you should be able to get hold of a IDispatch interface with simply a call to QueryInterface.
In most examples of WCF services that use MSMQ transport it is always preferred to create a proxy manually using svcutil in Visual Studio command prompt rather than simply adding a Service Reference. When you can just reference the service by providing its endpoint address to the Add Service Reference dialog in visual studio why would you want to create a proxy with VS command prompt (since it is slightly more laborious)? I just came across this while reading WCF 4 Step by Step:
Note that you cannot easily use the Add Service Reference Wizard in
Visual Studio to add a reference to a WCF service that uses the MSMQ
transport.
Why exactly is it difficult? What exactly is the benefit (if any) of the former method of referncing a WCF service? It seems to me that creating a proxy manually is just unnecessarily complicating the task.
You don't need to pre-generate a proxy as long as you have a reference to the assemblies which define the service interface, operations, and data contracts. You can then create the proxy on the fly using ChannelFactory.
var factory = new ChannelFactory<IMyServiceInterface>("MyServiceNameInAppConfig");
var proxy = factory.CreateChannel();
This is far simpler than using svcutil. However, if the service is remote and you cannot get access to the type assemblies then you have no other choice but to generate a proxy.
Regarding your question about why it's easier to use svcutil instead of VS to generate the proxy code, without seeing the actual book it is hard to comment, but under the hood visual studio uses svcutil to generate the code anyway, so I can't see how it would be any better or worse. When you do this manually then you have more control over what gets generated I guess.
We have an EPOS system that is built in VB6. A client is using Microsoft Dynamics AX as a CRM system. A 3rd party has created the AX implementation for our client and they've exposed a set of WCF web services that we need to consume to synchronise data between the EPOS and the AX CRM. Knowing VB6 would have issues calling WCF services, I created the following components to handle the communication between the EPOS and the AX CRM.
VB6 EPOS which calls -->
1) VB6 DLL wrapper which calls... -->
2) .NET(3.5) COM Callable Proxy DLL wrapper which calls... -->
3) .NET(3.5) Web Service Handler (Where the web servicesw actually get called) -->
Microsoft Dynamics AX CRM.
I built a test console app in Vb.NET to simulate calls from VB6 to help with debugging, so that test console app calls component 2.
Whilst doing this I was getting the following exception:-
"(could not find default endpoint element that references contract 'X' in the servicemodel client configuration section. this might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.)"
I googled around and found that I had to copy the bindings and endpoints section from Component 3's app.config to a new app.config for my Test Console app. I don't know WCF and haven't got the time at the moment, to really learn it to the point where I understand why this fixed this error.
Now though, I'm trying to call the services from the VB6 EPOS and this error is popping up again. So I added an app.config to Component 2, thinking that as Component 2 is the first .NET(3.5) component in the chain, that is where the endpoint declaration should go, but No. The error is still popping up.
Does anyone have any ideas? Any programming heroes out there that can shed some light on this for a simpleton please??? Please don't ask why we don't re-write the EPOS. We will. just not yet. Theres over 3 million lines of spaghetti code in there and I've only been working on it for 8 months!!!
As an aside, Doesn't this scenario break one of the golden rules of OOP, i.e. encapsulation. Why should my VB6 EPOS need to know what endpoints Component 3 uses to access the WCF service???
Great question here...
Your problem is essentially coming from all the required configuration data needed to work with a WCF Service.
When dealing with .NET Windows or Web Applications the configuration data on both the client and server sides of WCF Services reside in the application configuration file. For a windows application this file will be app.config, whereas it will be a web.config for a web application.
In your case, you would like to put the proxy logic in some form of a COM-visible .dll.
This is going to cause you some grief...in the .NET platform, the .config file for top-level host application (web or windows) is the place where all configuration data is read. Even if your application leverages dozens of .NET assemblies (each with custom configuration needs), the runtime is going to expect those configuration elements to all reside in the top-most application configuration file.
To resolve your issue, you are going to need to communicate to a service that VB6 does have access to (think ASMX web services) and have that service forward your call along to the appropriate WCF service.
The other alternative is to pass configuration variables directly from your VB6 application to your Com-visible assembly so you can use the extensibility model of WCF to create proxies (overriding the default behavior to read configuration data from a file) with your passed-in configuration.
I would say that the latter scenario could go both ways as far as being a violation of SOA/OOP..depending on the situation it may/may not be appropriate for the VB6 application to know about/store configuration details for communicating with the (eventual) WCF endpoint
I have a server that needs to keep a small number of clients in sync. Whenever there is a change of state at the server, all the connected clients must be informed.
I am planning to use a “callback
contract”,
I can get hold of the
callback reference for each client on
the server by using
GetCallbackChanel().
I then need
to manage all these client channel
reference and call all of them when
needed.
So far so good however:
I don’t wish to block the server, so calls to the clients must be none blocking
Errors calling the client must be logged and coped with
Is there a standard WCF component to do this?
No, there is not a standard WCF component for this, at least through .NET 3.5. I can't speak to what may be available in .NET 4.0.
That said, there is a pretty straightforward way to do this. Juval Lowy, author of Programming WCF Services, describes how to do this using his WCF-based Publish-Subscribe Framework.
Basically, the idea is to create a separate WCF event service that resides in the same hosting application as your server (e.g., Windows service, IIS). When the state of your server changes, you publish the state change to the event service. The clients that need to be kept in sync subscribe to this same event via the event service. In effect, the event service becomes a broker for your server to notify clients of whatever events your server publishes.
The article I listed above has a code download, but you can also get the Publish-Subscribe Framework and a working example for free from his website, IDesign.net. Here is the link to the download. You may need to scroll your browser up just a little bit to see it as I believe their internal hyperlink is wrong.