WSDAPI 101 Part 4: The interfaces under the generated code


This is the fourth article in the WSDAPI 101 series.  You’ll learn the most by starting at the beginning, although it’s not required to understand the content in this article.


WSDAPI 101 Part 3 was all about that cool adapter layer that sits between your application and the underlying generic WSDAPI objects.  So now that we know how that adapter layer works, it’s time to talk about the generic messaging components.


How are these interfaces organized?
Before we dive into specifics, it’s important to understand how the most important WSDAPI interfaces are organized.




This diagram illustrates the five top-level WSDAPI interfaces, and how they relate to messaging and discovery.  So far, WSDAPI 101 has been focused almost entirely on the top row of objects: IWSDDeviceProxy, IWSDServiceProxy, and IWSDDeviceHost.  The first two interfaces are what you use when you want to control a device (e.g., tell a webcam to take a picture) and the last is the interface you use to create a virtual device.


I haven’t touched on the second row at all, but I’ll note them briefly at the end of this post and will explain them in detail in another article.


One last point is that only two of these five interfaces have anything to do with generated code (IWSDServiceProxy and IWSDDeviceHost).  Don’t take this to mean that you’ve only learned 40% of WSDAPI so far–instead, take it to mean that these two interfaces constitute the vast majority of all WSDAPI calls you’re likely to make.  In reality, we’ve already covered the majority of concepts in the WSDAPI world.


We’ll go through the interfaces in the order they’re presented above.


Client-side control: IWSDDeviceProxy and IWSDServiceProxy
If you’re using WSDAPI, odds are good that you’re building a client-side control program.  For these types of applications, the IWSDDeviceProxy and IWSDServiceProxy interfaces are the two WSDAPI objects you’ll use most.




IWSDDeviceProxy presents a client-side representation of the DPWS device to which you’re connecting.  It has two purposes: 1) to allow callers to retrieve metadata that describes the device and its services, and 2) to generate IWSDServiceProxy objects.


IWSDServiceProxy is the client-side representation of an individual service on a DPWS device.  The service proxy is what gets wrapped in generated code, and is responsible for performing the basic messaging to a service hosted on a device.  As you can see in the diagram, you may spin off multiple service proxies for a given device, as that device may host multiple services.


Service-side control and discovery: IWSDDeviceHost
WSDAPI allows you to build devices and to host services.  The only interface you need is IWSDDeviceHost–it hosts any service objects you create, publishes WS-Discovery on your behalf, and automatically responds to any metadata requests that come in.  So if you have an IWSDDeviceHost, you do not need an IWSDiscoveryPublisher (nor do you have to devise a way to handle metadata).




Unlike generated code on the client side, you won’t ever have to deal directly with generated code on the device host side.  The red squares in the diagram above are called stubs, and are used automatically by the device host to translate generic function calls into strongly typed service method calls.  The only interaction you should ever have with these stubs is to register them with the device host using IWSDDeviceHost::RegisterPortType or with IWSDDeviceHost::AddDynamicService.


Client-side discovery: IWSDiscoveryProvider
IWSDiscoveryProvider is used to search for services on the network, and to listen as services arrive and leave the network.  It can’t be used to get metadata (you need an IWSDDeviceProxy for that) nor can it be used to control services (you need IWSDServiceProxy).  More on IWSDiscoveryProvider in a later article.


Service-side discovery: IWSDiscoveryPublisher
IWSDiscoveryPublisher gives you manual control to publish a service on a network, and to respond to queries from WS-Discovery clients.  IWSDiscoveryPublisher doesn’t serve metadata for you, nor does it host any services.  The IWSDDeviceHost has an IWSDiscoveryPublisher built in, so you don’t need to create one if you already have a WSDAPI device host.  More on IWSDiscoveryPublisher in a later article.


One last note on object creation
You may be asking yourself, “this is great, but how do I create these objects?”  Well, don’t fear–it’s really straightforward.  In all cases, you can create the object with the appropriate WSDAPI factory function; in nearly all cases, these are of the form WSDCreate??? where ??? is the base object name, sans the interface prefix.  So WSDCreateDeviceProxy will get you an IWSDDeviceProxy.  The only exception is the IWSDServiceProxy, which can only be generated with IWSDDeviceProxy::GetServiceById and IWSDDeviceProxy::GetServiceByType.


Stay tuned for WSDAPI 101 Part 5, where I’ll describe the end-to-end flow for assembling an application on WSDAPI, from the WSDL, to the generated layer, and on to the actual application code!

Comments (4)

  1. Nitin says:

    Hi Dan,

    We have implemented push scan support from device. It is working fine with inbox scan driver.

    We are currently implementing WIA minidriver.

    For generation of code for WSDAPI, we have used scan service WSDL file from Microsoft.

    The generated interface for subscribing to ScanAvailableEvent is not taking any input parameter for ScanDestination. This data is required by the device for subscription for ScanAvailableEvent.

    How can I pass this data in SubscribeScanAvailableEvent ?

    Do I need to modify the WSDL file ?

    If yes, what do I need to modify?

    Please provide me some help what to do for this.

    Thanks,

    Nitin.

  2. dandris says:

    Hi Nitin-

    This is a great question–I’ll write a new blog post to address it shortly.

    –Dan

  3. Mridu says:

    Hi Dan,

    We have implemented a WSD Device with Print Service. It works fine with Windows Vista and Windows 7, but when we run WLK 1.5 WSDMon Printer Verification test, we get to see an error "Activate Print Proxy fail" HRESULT 0x80040154 "Class not registered".

    Could you please let us know what could be the problem?

    Thanks and regards,

    Mridu

  4. dandris says:

    Hello-

    Please see my response to your similar question at: http://blogs.msdn.com/dandris/archive/2009/07/01/ws-dd-v1-1-specs-are-now-standards.aspx

    –Dan