This tutorial is provided in the language. You can find the project files for this tutorial at the following location under the Microsoft Robotics Studio installation folder:
Samples\Technologies\Interop\ToasterList
Here are the steps we have to do:
Prerequisites
Software
The actual work with the WDK is outside the scope of this tutorial, instead we are going to take an existing part of the Toaster sample from WDK and turn it into a Microsoft Robotics Studio DSS service.
The Toaster sample that we are going to use is the “toaster” application, which lists the available toaster devices and their information, which is located in the “WinDDK\6000\src\general\toaster\exe\toast” directory of your Vista WDK installation. Refer to that location on documentation about the toaster application itself.
This sample is designed for use with Microsoft Visual C++/CLI 2005. (Note that this is incompatible with earlier, 2003 or before, edition of C++ with managed extensions) You can use:
- Microsoft Visual C++ 2005 Express Edition.
- Microsoft Visual Studio 2005 Standard Edition.
- Microsoft Visual Studio 2005 Professional Edition.
- or Microsoft Visual Studio 2005 Team System.
You will also need Microsoft Internet Explorer or another conventional web browser.
Getting Started
Step 1: Create a new DSS C++ service
>bin\dssnewservice.exe /service:myToasterSvc /language:cpp
This will create a folder with the service code in it. Open the solution from there with you Visual Studio 2005 C++ editor.
Step 2: Add toaster application code
Step 3: Configuring build
- Under C\C++ -> General add to Additional Include Directories the following folders: WinDDK\6000\src\general\toaster\inc and WinDDK\6000\inc\api from your WDK installation.
- Under Linker -> General add to Additional Library Directories the following folder from WDK: WinDDK\6000\lib\wnet\i386
- Under Linker -> Input add setupapi.lib to Additional Dependencies
- Under Configuration Properties -> General change Character Set property from Use Unicode Character Set to Use Multi-Byte Character Set.
After you add these setting you should be able to compile your project, and get a couple of code errors due to syntax change from c to c++ for the toast.cpp file.
Step 4: Fixing toast.cpp
- error C2440: ‘=’ : cannot convert from ‘void *’ to ‘PSP_DEVICE_INTERFACE_DETAIL_DATA’
c:\Microsoft Robotics Studio (1.5)\myToasterSvc\toast.cpp 155 - error C2664: ‘SetupDiGetDeviceInstanceIdW’ : cannot convert parameter 3 from ‘BYTE *’ to ‘PSTR’
c:\Microsoft Robotics Studio (1.5)\myToasterSvc\toast.cpp 306
The first problem can be fixed by just adding a cast:
deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc (predictedLength);
The second problem just needs the right cast:
fSuccess = SetupDiGetDeviceInstanceId(hdi, &deid,
(PSTR)currentToaster->szCompInstanceId,
MAX_PATH, NULL);
After these errors are fixed you should be able to compile your service without errors. The toaster code that we added does not do anything useful, because we need to add the integration between it and the service code.
Step 5: Integrating code
Drop main method
Define new header file
Specify header files in source files
Define new data structure
typedef struct TOASTER_INFO {
TOASTER_INFO(){nextToasterInfo= NULL;}
TOASTER_INFO* nextToasterInfo;
CHAR szCompInstanceId[MAX_PATH];
CHAR szCompDescription[MAX_PATH];
CHAR szFriendlyName[MAX_PATH];
} *P_TOASTER_INFO ;
Change function signature
BOOL PrintToasterDeviceInfo(P_TOASTER_INFO* pFirstToaster);
Add allocation logic
if(*ppFirstToaster == NULL) { *ppFirstToaster = new TOASTER_INFO; currentToaster = *ppFirstToaster; } else { currentToaster->nextToasterInfo = new TOASTER_INFO; currentToaster = currentToaster->nextToasterInfo; }
Populate the structure
Create new state
[DataContract] public ref class myToasterInfo { public : [DataMember] String^ FriendlyName; [DataMember] String^ CompDescription; [DataMember] String^ CompInstanceId; };
Now change the myToasterSvcState class so that it will only have a list of our toaster devices in it:
[DataContract] public ref class myToasterSvcState { public : myToasterSvcState(); [DataMember] List<myToasterInfo^>^ Toasters; };
Don’t forget to change the constructor of this class in myToasterSvcTypes.cpp so that it properly initializes that list:
myToasterSvcState::myToasterSvcState()
{
Toasters = gcnew List<myToasterInfo^>();
}
This should be enough to have the service state ready to be used for our needs.
Create new state renew method
myToasterSvcState^ myToasterSvc::RenewState()
Don’t forget to add it’s declaration to the myToasterSvc.h file, and change the two operations that we talked about above to use this function:
void myToasterSvc::GetHandler(Get^ get) { get->ResponsePort->Post(RenewState()); } void myToasterSvc::HttpGetHandler(HttpGet^ httpGet) { httpGet->ResponsePort->Post(gcnew HttpResponseType(RenewState())); }
The way our service works we do not need to support the Replace operation. Remove it from service operations in myToasterSvcTypes.h file:
public ref class Replace : Microsoft::Dss::ServiceModel::Dssp::Replace<myToasterSvcState^, PortSet<DefaultReplaceResponseType^, Fault^>^> { }; public ref class myToasterSvcOperations : PortSet<DsspDefaultLookup^, DsspDefaultDrop^, Get^, HttpGet^, Replace^> { };
And remove the handlers for it in the myToasterSvc.h and myToasterSvc.cpp files as well:
void ReplaceHandler(Replace^ replace); Arbiter::Receive<Replace^>(true, _mainPort, gcnew Handler<Replace^>(this, &myToasterSvc::ReplaceHandler)) void myToasterSvc::ReplaceHandler(Replace^ replace) { _state = replace->Body; replace->ResponsePort->Post(DefaultReplaceResponseType::Instance); }
Now everything is ready for the final step.
Add marshaling and cleanup logic to state renew method
myToasterSvcState^ myToasterSvc::RenewState()
{
// create a new empty state instance
myToasterSvcState^ _state = gcnew myToasterSvcState();
P_TOASTER_INFO currentToaster = NULL;
P_TOASTER_INFO previousToaster = NULL;
// call the native helper function
if(PrintToasterDeviceInfo(¤tToaster))
{
if(currentToaster == NULL)
{
LogInfo(LogGroups::Console,“Current Toaster empty!”);
}
while(currentToaster != NULL)
{
// populate the state, correctly marshal the strings
myToasterInfo^ toaster = gcnew myToasterInfo();
toaster->FriendlyName = Marshal::PtrToStringAnsi(
(System::IntPtr)currentToaster->szFriendlyName);
toaster->CompDescription = Marshal::PtrToStringAnsi(
(System::IntPtr)currentToaster->szCompDescription);
toaster->CompInstanceId = Marshal::PtrToStringAnsi(
(System::IntPtr)currentToaster->szCompInstanceId);
_state->Toasters->Add(toaster);
//clean up the allocated memory
previousToaster = currentToaster;
currentToaster = currentToaster->nextToasterInfo;
delete previousToaster;
}
}
else
{
LogInfo(LogGroups::Console,“No toaster devices found!”);
}
return _state;
}
Now that this is done you should be able to successfully compile your project.
Step 6: Try it out
>Enum.exe -p 8
to add a toaster device to you machine. When you have some Toaster devices you can run a command similar to this one:
DssHost.exe /p:50000 /t:50001 /m:"myToasterSvc\myToasterSvc.manifest.xml"
out of your Microsoft Robotics Studio Command Prompt. Once the DSS node starts up you can access the state of the service by going to the following URL in your browser:
http://localhost:50000/mytoastersvc
If you used a different name for your Toaster service, you URL will be different. The state you see will be similar to this:
<?xml version=”1.0″ encoding=”utf-8″ ?> <myToasterSvcState xmlns:s=”http://www.w3.org/2003/05/soap-envelope” xmlns:wsa=”http://schemas.xmlsoap.org/ws/2004/08/addressing” xmlns:d=”http://schemas.microsoft.com/xw/2004/10/dssp.html” xmlns=”http://schemas.tempuri.org/2007/08/mytoastersvc.html”> <Toasters> <myToasterInfo> <FriendlyName>ToasterDevice08</FriendlyName> <CompDescription>Microsoft Toaster With Coinstaller</CompDescription> <CompInstanceId>{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&431A56F&0&04</CompInstanceId> </myToasterInfo> </Toasters> </myToasterSvcState>
Summary
Here are the steps that we took:

1 comment
Comments feed for this article
juin 25, 2008 à 8:51
Hannes
This site is really superb!!! Thank you for you work! Good Luck