NetworkChange.NetworkAddressChanged event does not fire - c#

I am developing a windows phone 7 app which is required to work with network.
I wanted my application to connect when NetworkAddress is changed that it becomes available. So I used NetworkChange.Networkaddresschanged. I was testing my app on emulator. It fires up first time but as there is no network I do nothing. This NetworkAddresschanged does not fire up the second time when network is available.
My code is
public void OnNetworkDownEvent()
{
lock (_networkChange)
{
var handler =_OnNetworkDown;
if (handler != null)
{
_OnNetworkDown();
}
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
NetworkChange.NetworkAddressChanged -= OnNetworkChange;
NetworkChange.NetworkAddressChanged += OnNetworkChange;
});
_connectionDown = true;
Monitor.Wait(_networkChange);
OnNetworkUpEvent();
}
}
public void OnNetworkUpEvent()
{
var handler = _OnNetworkUp;
if (handler != null)
{
_OnNetworkUp();
}
}
private void OnNetworkChange(object sender, EventArgs e)
{
lock(_networkChange)
{
if(NetworkInterface.GetIsNetworkAvailable())
{
if (_connectionDown)
{
_connectionDown = false;
Monitor.Pulse(_networkChange);
//OnNetworkUpEvent();
}
}
}
}
I call Networkdownevent() when network is down.And at that time I attach a delegate to NetworkAddressChange.
I do not know why this is happening.

The phone will see the USB connection to the host PC as it's primary connection so changes to the network connection of the attached PC will not have an impact on the phone.
This is one scenario where you can't test with the debugger attached. You'll have to store/display your debug output on the device with it not attached.
For testing I recommend having the phone connect to WiFi only and then controlling the connection state by turning the access point on or off. (This is the simplest technique I'm aware of for such a situation.)

Related

DeviceWatcher Updated and Removed events never fire

I am trying to use a DeviceWatcher to listen for a usb device. If the device is plugged in when my app starts, the Added event fires just fine and I can connect. But if I plug the device in after my app starts, or if I unplug the device, no other events fire. I have added callbacks to Added, Removed, and Updated, which is what the documentation said needed to have callbacks for the thing to work. What am I missing?
private void Watcher_DeviceAdded(DeviceWatcher sender, DeviceInformation deviceInfo) {
// Watcher may have stopped while we were waiting for our chance to run.
if (IsWatcherStarted(sender)) {
_resultCollection.Add(deviceInfo);
RaiseDeviceChanged(sender, deviceInfo.Id);
}
}
private void Watcher_DeviceUpdated(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
// Watcher may have stopped while we were waiting for our chance to run.
if (IsWatcherStarted(sender)) {
// Find the corresponding updated DeviceInformation in the collection and pass the update object
// to the Update method of the existing DeviceInformation. This automatically updates the object
// for us.
foreach (var deviceInfoDisp in _resultCollection) {
if (deviceInfoDisp.Id == deviceInfoUpdate.Id) {
deviceInfoDisp.Update(deviceInfoUpdate);
RaiseDeviceChanged(sender, deviceInfoUpdate.Id);
break;
}
}
}
}
private void Watcher_DeviceRemoved(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
// Watcher may have stopped while we were waiting for our chance to run.
if (IsWatcherStarted(sender)) {
// Find the corresponding DeviceInformation in the collection and remove it
foreach (var deviceInfoDisp in _resultCollection) {
if (deviceInfoDisp.Id == deviceInfoUpdate.Id) {
_resultCollection.Remove(deviceInfoDisp);
break;
}
}
RaiseDeviceChanged(sender, deviceInfoUpdate.Id);
}
}
I realized I had passed the wrong VID and PID to the watcher. I am using the Windows.Devices.SerialCommunication.SerialDevice class to get the device selector, and I passed the wrong IDs to the static method.

How to detect network change events asynchronously in UWP apps

I am building a UWP app where I am trying to detect different type of network event changes asynchronously.
Where user can make network changes and see the effect of their changes promptly.
For example -
Airplane Mode ON/OFF detect asynchronously
Bluetooth ON/OFF detect asynchronously
Network connectivity ON/OFF detect asynchronously
I was able to detect Airplane Mode ON/OFF detect synchronously using following code
public bool isConnectedToNetwork()
{
return NetworkInformation.GetInternetConnectionProfile()?.NetworkAdapter != null;
}
private void checkAirplaneMode()
{
if(isConnectedToNetwork())
{
airplaneText.Text = "AirplaneMode: OFF";
}
else
{
airplaneText.Text = "AirplaneMode: ON";
}
}
But I wanna (I would like to) do it asynchronously as network event changes.
So, User don't have to run the app again and again to see the changes.
UWP provides specific events to notify these changes, such as NetworkInformation.NetworkStatusChanged Event ,BluetoothDevice.ConnectionStatusChanged Event.
If you want to detect network change events, you could register for notifications of connection state change events.
// register for network status change notifications
networkStatusCallback = new NetworkStatusChangedEventHandler(OnNetworkStatusChange);
if (!registeredNetworkStatusNotif)
{
NetworkInformation.NetworkStatusChanged += networkStatusCallback;
registeredNetworkStatusNotif = true;
}
Then you could retrieve the connection state change information and add your trigger code.
async void OnNetworkStatusChange(object sender)
{
// get the ConnectionProfile that is currently used to connect to the Internet
ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
if (InternetConnectionProfile == null)
{
//add code about not connected
}
else
{
//add code about connected
}
}

Detect service shutdown from program

Is there a way to subscribe to an event when a given service is shut down.
My program occasionally sends commands to a third party windows service, but I have no way of knowing if it is up until I send my request, which then causes an exception since no one is listening.
So I would like to subscribe to an event if possible, to let my user know, that he can't interact with the service at the moment, rather than giving him an error when he tries.
I could have a timer that runs now and then which then checks if the PID is still alive, but I'd rather be told instantly by the OS.
You could try to implement the list of started services and look for yours in there so that you dont have to send and wait for an error or similar results.
On Windows (7 and higher) you should get an almost complete list of running services by accessing the local or remote servicecontroller.
Here is more: https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicecontroller.getservices?view=netframework-4.8
https://answers.unity.com/questions/971269/subscribing-to-event-from-external-class.html
I ended up with this class, if it can be useful to someone else
public class ExternalProcessMonitor
{
Process process;
Action action;
string name;
public ExternalProcessMonitor(string _name, Action _action)
{
action = _action;
name = _name;
}
public bool StartMonitor()
{
if (process != null)
process.Exited -= Process_Exited;
var list = Process.GetProcesses().OrderBy(r => r.ProcessName);
process = Process.GetProcessesByName(name).FirstOrDefault();
if (process != null)
{
process.Exited += Process_Exited;
process.EnableRaisingEvents = true;
}
return process != null;
}
private void Process_Exited(object sender, EventArgs e)
{
action();
}
}

BLE advertisement UWP application

Im trying to make a program that can scan for BLE advertisements. I have been looking at the Windows-universal-samples, more precisely the sample called BluetoothAdvertisement. I want to make a simple UWP application that can scan for BLE advertisements and show them in a listbox. But my application can't find anything at all and I'm totally lost.
namespace BleDiscAdv2
{
public sealed partial class MainPage : Page
{
// The Bluetooth LE advertisement watcher class is used to control and customize Bluetooth LE scanning.
private BluetoothLEAdvertisementWatcher watcher;
public MainPage()
{
this.InitializeComponent();
// Create and initialize a new watcher instance.
watcher = new BluetoothLEAdvertisementWatcher();
//Set the in-range threshold to -70dBm. This means advertisements with RSSI >= -70dBm
//will start to be considered "in-range"
watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;
// Set the out-of-range threshold to -75dBm (give some buffer). Used in conjunction with OutOfRangeTimeout
// to determine when an advertisement is no longer considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75;
// Set the out-of-range timeout to be 2 seconds. Used in conjunction with OutOfRangeThresholdInDBm
// to determine when an advertisement is no longer considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Attach a handler to process the received advertisement.
// The watcher cannot be started without a Received handler attached
watcher.Received += OnAdvertisementReceived;
}
private void btStart_Click(object sender, RoutedEventArgs e)
{
watcher.Start();
}
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
DateTimeOffset timestamp = eventArgs.Timestamp;
string localName = eventArgs.Advertisement.LocalName;
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
lbModtaget.Items.Add("Name of device: " + localName + "\t" + "Time for advertisement: " + timestamp.ToString("hh\\:mm\\:ss\\.fff"));
});
}
}
}
Can someone tell me what is wrong?
I'm new to BLE and I haven't been coding for a while.
Best regards
Christian
But my application can't find anything at all and I'm totally lost.
Please ensure that your app has enable Bluetooth capability in the Package.appxmanifest. See Basic Setup for details.
Please ensure the Bluetooth radio of running device was turn on and available.
There're devices are advertising and meet the filter. You can run the Scenario 2 of the Bluetooth advertisement official sample on another device to ensure that.
By testing on my side, your code snippet can scan the BLE advertisements well. In your code snippet, you didn't listen to the Stopped event handle of the watcher which is for notification to the app that the Bluetooth LE scanning for advertisements has been cancelled or aborted either by the app or due to an error. If the watcher is force stopped it will not get any advertisements.
You can add the Stopped event handle to check if there is a BluetoothError.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Attach a handler to process the received advertisement.
// The watcher cannot be started without a Received handler attached
watcher.Received += OnAdvertisementReceived;
watcher.Stopped += OnAdvertisementWatcherStopped;
}
private async void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args)
{
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
txtresult.Text = string.Format("Watcher stopped or aborted: {0}", args.Error.ToString());
});
}
For example, RadioNotAvailable may be caused by the running device is not enable the Bluetooth, OtherError may be caused by Bluetooth capability doesn't enabled. If the watcher is not stopped and there're advertisements, your app should work.

Windows 10 Bluetooth Low Energy Connection c#

For a project I need to get some data from a Bluetooth device on windows 10 using C#. I'm not too familiar with the Bluetooth API and can't figure out why the following is not working:
Using the BluetoothLEAdvertisementWatcher I search for advertisements, which works fine. I do receive the advertisement from the device (local name fits) as well as it's ServiceUuids. Next I try to connect to the device using the BluetoothAddress received together with the advertisement:
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
ulong blAdress = eventArgs.BluetoothAddress;
BluetoothLEDevice blDevice = await
Windows.Devices.Bluetooth.BluetoothLEDevice.FromBluetoothAddressAsync(blAdress);
}
However, doing so results in an exception:
Element not found. (Exception from HRESULT: 0x80070490).
Is this the correct way to read data from the device? Are other options available to read the data from the services? Manually pairing the device in windows is not really an option and also seems to fail.
/Edit 1: I check for the local name of the device to make sure I only try to connect to the right one. So I guess there is a problem with connecting to this specific device, still I have no idea how to work around that. The service data was succesfully read on iOS, so it should be possible.
Until MS fixes this problem the only reliable solution to this I have found to connect to a BLE device is to ask the registry for a list of paired BLE devices and compare the bluetooth address in the advert with with registry list of paired able devices. My experience is that when FromBluetoothAddressAsync is called on an unpaired device Windows throws an exception and kills the watcher thread. I have some C++ code that I am happy to share that reads the registry and creates a list of paired BLE devices.
Hopefully MS will take the time to fully support BLE in the same manner Apple does.
Here is a reference from MS (https://social.msdn.microsoft.com/Forums/vstudio/en-US/e321cb3c-462a-4b16-b7e4-febdb3d0c7d6/windows-10-pairing-a-ble-device-from-code?forum=wdk). It seems that to use this BluetoothLEDevice.FromBluetoothAddressAsync we have to handle the exception when the device is advertising and not yet paired.
I got the same issue when I using the BluetoothLEAdvertisementWatcher directly.
Then I tested the different addresses listed by the watcher. I found it is related to the Bluetooth devices.
After adding the filter as following, I can connect to GATT device (TI Sensor Tag) successfully.
public sealed partial class MainPage : Page
{
private BluetoothLEAdvertisementWatcher watcher;
public MainPage()
{
this.InitializeComponent();
// Create and initialize a new watcher instance.
watcher = new BluetoothLEAdvertisementWatcher();
// Part 1B: Configuring the signal strength filter for proximity scenarios
// Configure the signal strength filter to only propagate events when in-range
// Please adjust these values if you cannot receive any advertisement
// Set the in-range threshold to -70dBm. This means advertisements with RSSI >= -70dBm
// will start to be considered "in-range".
watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;
// Set the out-of-range threshold to -75dBm (give some buffer). Used in conjunction with OutOfRangeTimeout
// to determine when an advertisement is no longer considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75;
// Set the out-of-range timeout to be 2 seconds. Used in conjunction with OutOfRangeThresholdInDBm
// to determine when an advertisement is no longer considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
// By default, the sampling interval is set to zero, which means there is no sampling and all
// the advertisement received is returned in the Received event
// End of watcher configuration. There is no need to comment out any code beyond this point.
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
watcher.Received += OnAdvertisementReceived;
watcher.Stopped += OnAdvertisementWatcherStopped;
App.Current.Suspending += App_Suspending;
App.Current.Resuming += App_Resuming;
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
App.Current.Suspending -= App_Suspending;
App.Current.Resuming -= App_Resuming;
watcher.Stop();
watcher.Received -= OnAdvertisementReceived;
watcher.Stopped -= OnAdvertisementWatcherStopped;
base.OnNavigatingFrom(e);
}
private void App_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
{
// Make sure to stop the watcher on suspend.
watcher.Stop();
// Always unregister the handlers to release the resources to prevent leaks.
watcher.Received -= OnAdvertisementReceived;
watcher.Stopped -= OnAdvertisementWatcherStopped;
}
private void App_Resuming(object sender, object e)
{
watcher.Received += OnAdvertisementReceived;
watcher.Stopped += OnAdvertisementWatcherStopped;
}
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
var address = eventArgs.BluetoothAddress;
BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(address);
var cnt =device.GattServices.Count;
watcher.Stop();
}
/// <summary>
/// Invoked as an event handler when the watcher is stopped or aborted.
/// </summary>
/// <param name="watcher">Instance of watcher that triggered the event.</param>
/// <param name="eventArgs">Event data containing information about why the watcher stopped or aborted.</param>
private void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementWatcherStoppedEventArgs eventArgs)
{
}
private void start_Click(object sender, RoutedEventArgs e)
{
watcher.Start();
}
}
Just a guess, but maybe you need this:
watcher.ScanningMode = BluetoothLEScanningMode.Active;
and in the OnAdvertisementReceived event
if (e.AdvertisementType == BluetoothLEAdvertisementType.ScanResponse)
{
BluetoothLEDevice blDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(e.BluetoothAddress);
}
If this is a UWP project, ensure you enable Bluetooth capabilities.
To do so in Visual Studio solution explorer double click the *.appxmanifest, choose the 'Capabilities' tab and ensure that 'Bluetooth' is checked.
It will add some xml not unlike the following;
<Capabilities>
<Capability Name="internetClientServer" />
<DeviceCapability Name="bluetooth" />
</Capabilities>
This Question is over 3 years old, but because it has over 13000 views, I will answer.
The reason for Element not found is that Windows.Devices is not aware of advertising Ble-devices until they are paired or connected.
Instead in the OnAdvertisementReceived just use:
var device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
I also have a very simple uwp example on github, it has no controls to keep it as simple as possible. All the results are shown in the debug output window.
The most usefull info is in MainPage.xaml.cs
check it out: https://github.com/GrooverFromHolland/SimpleBleExample_by_Devicename

Categories