[Windows Mobile Software Development] mligor:
here is my code snippet - it is not guaranteed that is compilable, because I took parts from my application.... but should be enough to get overview what you have to do to make it to work.

About managed code.. I didn't try it.. somehow for me is still easier to write C++ code :p

static const DWORD maxMsgQueueMsgSize = sizeof(POWER_BROADCAST_POWER_INFO) + sizeof(POWER_BROADCAST) + MAX_PATH;

// create stop event
HANDLE hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

// create event for GPS change
HANDLE hDeviceStateChanged = CreateEvent(NULL, FALSE, FALSE, NULL);

// Create message queue
MSGQUEUEOPTIONS msgQueueOptions;
ZeroMemory(&msgQueueOptions, sizeof(msgQueueOptions));
msgQueueOptions.dwSize = sizeof(msgQueueOptions);
msgQueueOptions.dwFlags = MSGQUEUE_NOPRECOMMIT ;
msgQueueOptions.cbMaxMessage = maxMsgQueueMsgSize;
msgQueueOptions.bReadAccess = TRUE;

HANDLE hMsgQueue = ::CreateMsgQueue(NULL, &msgQueueOptions);
HANDLE hPowerNotification = ::RequestPowerNotifications(hMsgQueue, PBT_POWERINFOCHANGE | PBT_TRANSITION);

// opening GPS device
HANDLE hGPSDevice = ::GPSOpenDevice( 0, hDeviceStateChanged, NULL, 0);

bool bRun = true; // run loop
bool bHasSignal = false;

// change power requirement for GPS device and SD card
HANDLE hGPSPowerReq = ::SetPowerRequirement(L"GPS0:", D0, POWER_NAME|POWER_FORCE, NULL, NULL);
HANDLE hPowerReq = ::SetPowerRequirement(L"DSK1:", D0, POWER_NAME|POWER_FORCE, NULL, NULL);

// change to Unattended mode
::PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

// LOOOP
HANDLE events[3] = {hDeviceStateChanged, hStopEvent, hMsgQueue} ;
while (bRun)
{
DWORD dwWaitRes = ::WaitForMultipleObjects(3, events, FALSE, 1000 ); // read every 1. sec.
switch (dwWaitRes)
{
case WAIT_OBJECT_0:
// device status changed
{
GPS_DEVICE dev;
ZeroMemory(&dev, sizeof(dev));
dev.dwVersion = GPS_VERSION_1;
if (ERROR_SUCCESS == ::GPSGetDeviceState(&dev))
{
// do something...
}
}
break;
case WAIT_OBJECT_0+1:
// exit requested from exit event.. this is done from other thread by calling SetEvent(hExitEvent)
bRun = false;
break;
case WAIT_OBJECT_0+2:
// if we are on low power, stop monitoring
{
// there is a message in EventQueue.. read queue
BYTE buffer[maxMsgQueueMsgSize];
DWORD NumberOfBytesRead = 0;
ZeroMemory(buffer, maxMsgQueueMsgSize);

DWORD dwFlags;
if (::ReadMsgQueue(m_hMsgQueue, buffer, maxMsgQueueMsgSize,&NumberOfBytesRead, 0, &dwFlags ) && NumberOfBytesRead>=sizeof(POWER_BROADCAST))
{
POWER_BROADCAST* pPwrBrodcast = (POWER_BROADCAST*)(buffer);
switch(pPwrBrodcast->Message)
{
case PBT_POWERINFOCHANGE:
{
// if battery level is to low, finish with GPS reading
POWER_BROADCAST_POWER_INFO* pPowerInfo = (POWER_BROADCAST_POWER_INFO*)pPwrBrodcast->SystemPowerState;
if ((pPowerInfo->bBatteryFlag==2 || pPowerInfo->bBatteryFlag==4) && (pPowerInfo->bACLineStatus==0))
bRun = false;
}
break;
case PBT_TRANSITION:
{
std::wstring powerState = pPwrBrodcast->SystemPowerState;
// handle power states
if (powerState==L"resuming")
::PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE); // basicaly should never happen, because we do not allow to go in
if (powerState==L"unattended")
SystemIdleTimerReset();
}
break;
default:
ASSERT(!"Unknown message");
}

}
break;
case WAIT_TIMEOUT:
// new location
break;
}
// DO SOMETHING... e.g. Read position from GPS PORT
}
// ENDLOOP

::PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE); // Leave unattended mode
::ReleasePowerRequirement(hGPSPowerReq);	// allow GPS device to go in sleep
::ReleasePowerRequirement(hPowerReq);

::GPSCloseDevice(hGPSDevice); // close GPS device

StopPowerNotifications(hPowerNotification);
CloseMsgQueue(hMsgQueue);
CloseHandle(hPowerNotification);
CloseHandle(hMsgQueue);