2008. 9. 5. 05:55

How do I find when active sync device has connected/disconnected- PC side

Very often there is a requirement that we should find out when an Windows Mobile device has connected with a PC.I know that I had one :-).

There are 3 ways,that I know of,using which we can achieve this objective.

1.First approach is registry based.There are two predefined events “AutoStartOnConnect” and “AutoStartOnDisconnect”. Both of these have associated registry key namely [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect] and [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AutoStartOnDisconnect]. You add an entry here which would enable your application to be executed when these events occur. To do this you simple need to add a new string value and data would be path and name of your application and command-line if any. e.g. MyApplication - “C:\Myapplication.exe”

2. Second approach is COM based. This needs more work but you are also rewarded with more functionality :-).

Two COM interfaces are used to register an application for the notification.IDccMan and IDccManSink. Of these IDccMan is implemented by Active sync connection manager so as an application developer you just need to implement IDccMan.(Note: there is another interface IDccManSink2 which extends IDccMan and provides support for IPv6).

eg:

//Declaration

classCMyDccManSink :publicIDccManSink

{

public:

CMyDccManSink (); ~CMyDccManSink ();HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID **ppvObject);ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release();HRESULT STDMETHODCALLTYPE OnLogIpAddr(DWORD dwIpAddr);HRESULT STDMETHODCALLTYPE OnLogTerminated();HRESULT STDMETHODCALLTYPE OnLogActive();HRESULT STDMETHODCALLTYPE OnLogInactive();HRESULT STDMETHODCALLTYPE OnLogAnswered();

HRESULT STDMETHODCALLTYPE OnLogListen();

HRESULT STDMETHODCALLTYPE OnLogDisconnection();

HRESULT STDMETHODCALLTYPE OnLogError();

private:

long  lRefCount;

};

//Implementation:

CMyDccManSink::CMyDccManSink()
{
}

CMyDccManSink::~CMyDccManSink()
{
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::QueryInterface(REFIID riid, void **ppvObject)
{
 if ( IID_IUnknown == riid || IID_IDccManSink == riid )
 {
  *ppvObject = (IDccManSink*)this;
  AddRef();
  return NO_ERROR;
 }
 else
 {
  *ppvObject = NULL;
  return E_NOINTERFACE;
 }
}

ULONG STDMETHODCALLTYPE CMyDccManSink::AddRef()
{
 return (ULONG)InterlockedIncrement(&lRefCount);
}

ULONG STDMETHODCALLTYPE CMyDccManSink::Release()
{
 ULONG nCount = (ULONG)InterlockedDecrement(&lRefCount);
 if ( !nCount )
 {
  delete this;
  return 0;
 }
 return nCount;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogIpAddr(DWORD dwIpAddr)
{
 //Indicates that an Internet Protocol (IP) address has
 //been established for communication between the
 //desktop computer and the target device
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogTerminated()
{
 //Indicates that Connection Manager has been shut down
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogActive()
{
 //Indicates that a connection is established between the
 //client application and Connection Manager
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogInactive()
{
 //Indicates a disconnection, or disconnected state,
 //between the desktop computer and the target device
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogAnswered()
{
 //Indicates that Connection Manager has detected
 //the communications interface
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogListen()
{
 //Indicates that a connection is waiting to be established
 //between the desktop computer and the target device
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CDevComDccSync::OnLogDisconnection()
{
 //Indicates that Connection Manager has terminated
 //the connection between the desktop computer and the target device
 return NO_ERROR;
}

HRESULT STDMETHODCALLTYPE CMyDccManSink::OnLogError()
{
 //Indicates that Connection Manager failed to start
 //communications between the desktop computer and the target device
 return NO_ERROR;
}

Now you would need to register with the connection manager:

CoInitialize(NULL);
HRESULT hResult;
IDccMan *pIDccMan = NULL;

CMyDccManSink MyDCCSink;
DWORD dwContext = 0;
hResult = CoCreateInstance(CLSID_DccMan,NULL,CLSCTX_SERVER,IID_IDccMan,(void**)&pIDccMan);

if(SUCCEEDED(hResult))

{

//Call the Advise method of IDccManSink to register for receiving the notification.

 pIDccMan->Advise(&MyDCCSink,&dwContext);

//Once you are done then you would need to call Unadvice () ,passing the context value returned in advise,to unregister for notification.

pIDccMan->Unadvise(dwContext);}3. There is a 3rd method using which you can get the Active-sync connect and disconnet events.Whenever any hardware device is connected on Desktop PC an event is fired to all the applications that have registered for the event.You can leverage this to get the notification. The function that you can use for this is RegisterDeviceNotification(). This functions registers the device/device type for which w windows will receive the notification.//sample code:GUID_DEVINTERFACE_USB_DEVICE={ 0xA5DCBF10, 0×6530, 0×11D2, { 0×90, 0×1F, 0×00, 0xC0, 0×4F, 0xB9, 0×51, 0xED } },

DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;

ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;

//First parameter is a handle to your applications window

HANDLE  hDevNotify = RegisterDeviceNotification(hWnd,&NotificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);

If the registration is successfull then return value is device handle and if it fails then it returns NULL. System sends WM_DEVICECHANGE notification to your window,you can handle this in your Wnd proc.

//WndProc

case WM_DEVICECHANGE:

if(wParam==DBT_DEVICEARRIVAL

{

//Device has been added

//You can find if it was active sync device by using SetUpDi set of functions and lParam.lParam contains the Dev Broad cast header.

//

}

else if(wParam==DBT_DEVICEREMOVECOMPLETE)

{

//Device has been removed  

//You can find if it was active sync device by using SetUpDi set of functions and lParam.lParam contains the Dev Broad cast header.

})//End of WndProcWhen you no longer need the notification then you must Unregister for the notification using UnRegisterDeviceNotification().UnRegisterDeviceNotification(hDevNotify )

출처 : http://amitranjan.wordpress.com/2007/04/23/how-do-i-find-when-active-sync-has-startedstopped-pc-side/