This code sample is named WMBluetoothWrapper. It demonstrates simple Bluetooth device discovery via the Winsock 2 API, and provides a C# wrapper class for running the discovery. Both the names of the mobile devices and their addresses are retrieved and marshaled to C# data types. I provide both the Visual Studio 2010 DLL project WMBluetoothWrapper which present the WinSock 2 based discovery function as well as the C# file including the
DevicesDiscoveryWrapper wrapper class. Using the retrieved addresses, the current wrapper can be extended to include further functions, such as Bluetooth based connection and data exchanging functions.
As part of my plan to write a mobile social network application (coming soon) using Windows Mobile Bluetooth capable devices, I need a way to know what Bluetooth devices are near me. I'm developing a mobile social network application in C# using the .NET Compact Framework 3.5, and thus I was confronted with the need of writing the whole low level Bluetooth based functionalities in C++, compiling them into a DLL, and finally writing a C# wrapper class and using P/Invoke(s) in order to run the Bluetooth functions. Before going ahead with the development of the wrapper, I've tried to find third-party libraries in C# exposing Bluetooth discovery functionalities, and I found 32feet.NET which seems to be popular from what I've read; however, it seems to present some license limitations, and after all it is better to have the control on a simpler and customizable wrapper.
DevicesDiscoveryWrapper class is written in C#, and it uses P/Invoke to gain access to exported functions within the WMBluetoothWrapper DLL file. The latter is written in C++, and makes use of Bluetooth functionalities provided by the Winsock 2 API in order to build the devices discovery function.
Using the Code
In order to use the Bluetooth devices discovery wrapper when developing your application, you will just add the C# file DevicesDiecoveryWrapper.cs to your project and use the class
DevicesDiscoveryWrapper. For deployment, you should not forget to copy the DLL file WMBluetoothWrapper.dll into your project mobile working directory. Below, I provide a detailed description of both the devices discovery function written using the Bluetooth Winsock 2 API and the C# wrapper class.
The WMBluetoothWrapper DLL Code
extern "C" int DevicesDiscovery(wchar_t * devicesList);
extern "C" int DevicesDiscovery(wchar_t * devicesList)
WSAStartup (MAKEWORD(1,0), &wsd);
double __unused; };
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
DWORD dwSize = sizeof(buf);
wsaq.dwSize = sizeof(wsaq);
wsaq.dwNameSpace = NS_BTH;
wsaq.lpcsaBuffer = NULL;
if (ERROR_SUCCESS != WSALookupServiceBegin (&wsaq, LUP_CONTAINERS, &hLookup))
L"WSALookupServiceBegin failed %d\r\n", GetLastError());
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
int numberRetrivedDevices = 0;
while (ERROR_SUCCESS == WSALookupServiceNext (hLookup, LUP_RETURN_NAME
| LUP_RETURN_ADDR, &dwSize, pwsaResults))
if (pwsaResults->dwNumberOfCsAddrs != 1)
L"WSALookupServiceNext failed %d\r\n", GetLastError());
if(numberRetrivedDevices > 0)
BT_ADDR b = ((SOCKADDR_BTH *)pwsaResults->
bHaveName = pwsaResults->lpszServiceInstanceName &&
wsprintf (currentDev, L"%s%s%04x%08x%s\n", bHaveName ?
pwsaResults->lpszServiceInstanceName : L"",
bHaveName ? L"(" : L"", GET_NAP(b),
GET_SAP(b), bHaveName ? L")" : L"");
The DevicesDiscoveryWrapper Wrapper Class
Below you find the code for the wrapper class developed in C#. A common scenario for using this wrapper would be to periodically start a detached thread and to specify the
RunDevicesDiscovery method as its start point. Then, the managed thread will run a P/Invoke and call the unmanaged devices discovery function provided by the DLL file. Once done, the thread modifies the
numberDevices according to the found results. So, the user can retrieve the number and the list of available devices. I've also used the Singleton Design Pattern within the wrapper class in order to ensure that it will be instantiated only once.
private static extern System.Int32 DevicesDiscovery
([MarshalAs(UnmanagedType.LPWStr)] StringBuilder listDevices);
private static string devicesList;
private static int numberDevices;
private static DevicesDiscoveryWrapper _wrapper = null;
devicesList = null;
numberDevices = 0;
public static DevicesDiscoveryWrapper GetDevicesDiscoveryWrapper()
if(_wrapper == null)
_wrapper = new DevicesDiscoveryWrapper();
public string GetDevices
public int GetNumberOfDevices
public void RunDevicesDiscovery()
StringBuilder tmpListDevices = new StringBuilder();
tmpListDevices.Capacity = 1024;
int res = DevicesDiscovery(tmpListDevices);
if( res == -1)
("Error occurred while calling the
unmanaged DevicesDiscovery functions: " +
devicesList = tmpListDevices.ToString();
numberDevices = res;
Tools of Interest
The DLL Export Viewer tool was of great help to me for verifying/debugging the list of exported functions and their virtual memory addresses for the WMBluetoothWrapper DLL file. More details about this tool can be found at: http://www.nirsoft.net/utils/dll_export_viewer.html.
For bug reports and suggestions, feel free to contact me at email@example.com.
- 18th March, 2010: Initial post.