Windows IOT UWP - Relay - c#

Good Evening,
I’m doing some troubleshooting on the beginning of my home automation system. I am trying to toggle a relay using a Raspberry PI 3 and Windows IOT in C#. I’ve been playing with the code and I can see the relay toggle once or twice, but then the app crashes. I’m an IOT Noob, so is there something wrong with this code? (Variable names are defined elsewhere and the weird variable names I have below are for my WIP project... I prefer troubleshooting in English)....
private void BtnTempFan_Click(object sender, RoutedEventArgs e)
{
if (BtnTempFan.IsChecked == true)
{
TogglePin(TempFan, TempFan_PIN, BtnTempFan, GpioPinValue.High);
}
else
{
TempFan.Dispose();
}
}
private void TogglePin(GpioPin PinName, int PinNumber, ToggleButton Name, GpioPinValue value)
{
int pinnumber = PinNumber;
GpioPinValue pinvalue;
var gpio = GpioController.GetDefault();
PinName = gpio.OpenPin(pinnumber);
if (gpio == null)
{
PinName = null;
LblError.Text = "We can't find the controller on the device" + PinName;
LblError.Visibility = Visibility.Visible;
return;
}
if (PinName == null)
{
LblError.Text = "We can't find the pin on the device. Pin number " + PinNumber + "does not exist";
LblError.Visibility = Visibility.Visible;
return;
}
if (Name.IsChecked == true)
{
pinvalue = value;
PinName.Write(pinvalue);
PinName.SetDriveMode(GpioPinDriveMode.Output);
}

You don't say what the exception is. However, I believe you are supposed open a GPIO pin only once per app:
var gpio = GpioController.GetDefault();
PinName = gpio.OpenPin(pinnumber);
You have it in a method which is called once per button click. By opening the pin more than once, you are encountering that the pin is already open, and I believe this is what throws an exception and crashes the app.
In my code, I handle pin states in a "driver" class, and have a method called Connect which I call once when starting the application. For example:
public async Task Connect()
{
var gpioController = await GpioController.GetDefaultAsync();
try
{
_openPin = gpioController.OpenPin(_doorMotorOpenPin);
_closePin = gpioController.OpenPin(_doorMotorClosePin);
}
}
This encapsulates the 2 pins: _openPin and _closePin into a class that I can manage the lifecycle of.

Codekaizen is correct. I separated out opening the pin into a method that only gets called once and problem solved.
private void BtnTempFan_Click(object sender, RoutedEventArgs e)
{
if (BtnTempFan.IsChecked == false)
{
TogglePin(TempFan, TempFan_PIN, BtnTempFan, GpioPinValue.High);
}
if (BtnTempFan.IsChecked == true)
{
TogglePin(TempFan, TempFan_PIN, BtnTempFan, GpioPinValue.Low);
}
}
private void InitializePins()
{
var gpio = GpioController.GetDefault();
// Show an error if there is no GPIO controller
if (gpio == null)
{
TempFan = null;
LblError.Text = "We can't find the controller on the device";
LblError.Visibility = Visibility.Visible;
return;
}
TempFan = gpio.OpenPin(TempFan_PIN);
TempFan.SetDriveMode(GpioPinDriveMode.Output);
}
private void TogglePin(GpioPin PinName, int PinNumber, ToggleButton Name, GpioPinValue value)
{
int pinnumber = PinNumber;
GpioPinValue pinvalue;
pinvalue = value;
PinName.Write(pinvalue);
}

Related

Xamarin Android C# Start Service 'else' not called

I have buttons that give the ability to start or stop the app's background service, but for some reason my 'else' call in the button's click event isnt being activated if the service is already running.
Heres the whole button code, hope someone knows why it doesnt call:
private void StartServiceButton_Click(object sender, EventArgs e)
{
if (Application.Context.GetSystemService("com.prg.NotificationService") == null)
{
Application.Context.StartService(intent);
}
else
{
Toast.MakeText(this, "Service already running", ToastLength.Long).Show();
}
}
im caching intent in OnCreate, here is the setup:
intent = new Intent(Application.Context, typeof(NotificationService));
Here is about the GetSystemService method, this method is to get system service not to get your custom service. You need use ActivityManager to get all service which is running on your device and find which one is what you want to start or stop.
Please use the under code to achieve your goal:
private void StartServiceButton_Click(object sender, System.EventArgs e)
{
MyService myService = new MyService();
if (!isServiceRun("MyService"))
{
Toast.MakeText(this, "Service not running", ToastLength.Long).Show();
Application.Context.StartService(intent);
}
else
{
Toast.MakeText(this, "Service already running", ToastLength.Long).Show();
StopService(new Intent(this,typeof(MyService)));
}
}
public bool isServiceRun( string className)
{
bool isRun = false;
ActivityManager activityManager = (ActivityManager)this.GetSystemService(Context.ActivityService);
IList<ActivityManager.RunningServiceInfo> serviceList = activityManager.GetRunningServices(40);
int size = serviceList.Count;
for (int i = 0; i < size; i++)
{
Android.Util.Log.Error("Service Name=====", serviceList[i].Service.ClassName);
if (serviceList[i].Service.ClassName.Contains(className) == true)
{
isRun = true;
break;
}
}
return isRun;
}
Note:
Here is the usage about Service in Xamarin.Android, please don't forget add [Service] attribute.

Why value does not fall within the expected range when setting Value Changed for Gatt Characteristic

I would like to keep on reading characteristic/set value changed event handlers for characteristics from my BLE 4.0 device, by using the ValueChanged callback in Universal Windows Platform C# in Visual Studio 2017.
I followed some tutorial from these sites: Damian Blog's Windows Universal with BLE, Bluetooth Gatt's Git Hub, Bluetooth Generic Attribute Profile - Heart Rate Service and Dr. Jukka's mobile Blog on BLE. All of them are using ValueChanged and I have tried to follow what they did.
Unfortunately, instead of ValueChanged being triggered, I receive the following error when using the ValueChanged callback.
System.ArgumentException: 'Value does not fall within the expected range.'
This line of code is producing the error:
characteristic.ValueChanged += Oncharacteristic_ValueChanged;
Here is more details of my source code:
NOTE: I am using COM 7 for my dongler and my program could discover the BLE's device name, and could discover the Uuid of the services and characteristics.
public List<string> serviceList = new List<string>();
public List<string> characteristicList = new List<string>();
public BluetoothLEDevice myDevice { get; set; }
public MainPage()
{
this.InitializeComponent();
}
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
// Find the com port
string selector = SerialDevice.GetDeviceSelector("COM7");
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(selector);
if (devices.Count > 0)
{
var dialog = new MessageDialog("Com Device found");
await dialog.ShowAsync();
DeviceInformation deviceInfo = devices[0];
SerialDevice serialDevice = await SerialDevice.FromIdAsync(deviceInfo.Id);
serialDevice.BaudRate = 9600;
serialDevice.DataBits = 8;
serialDevice.StopBits = SerialStopBitCount.One;
serialDevice.Parity = SerialParity.None;
}
else
{
MessageDialog popup = new MessageDialog("Sorry, no device found.");
await popup.ShowAsync();
}
// After com port is found, search for device
foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id);
// Display BLE device name
var dialogBleDeviceName = new MessageDialog("BLE Device Name " + bleDevice.Name);
await dialogBleDeviceName.ShowAsync();
myDevice = bleDevice;
}
// Check device connection
myDevice.ConnectionStatusChanged += OnConnectionStatusChanged;
foreach (var service in myDevice.GattServices)
{
serviceList.Add(service.Uuid.ToString());
// Verify if service is discovered by displaying a popup
MessageDialog serviceUuidPopUp = new MessageDialog("Adding Service Uuid to list " + service.Uuid.ToString() );
await serviceUuidPopUp.ShowAsync();
foreach (var characteristic in service.GetAllCharacteristics())
{
var characteristicUuid = characteristic.Uuid.ToString().ToLowerInvariant();
characteristicList.Add(characteristicUuid);
// Verify if characteristic is discovered by displaying a popup
MessageDialog charUuidPopUp = new MessageDialog("Adding characteristic Uuid to list " + characteristicUuid);
await charUuidPopUp.ShowAsync();
// set value changed event handlers for characteristics
characteristic.ValueChanged += Oncharacteristic_ValueChanged;
}
}
}
private void OnConnectionStatusChanged(BluetoothLEDevice sender, object args)
{
if (sender.ConnectionStatus == BluetoothConnectionStatus.Connected)
{
System.Diagnostics.Debug.WriteLine("Connected");
}
else
{
System.Diagnostics.Debug.WriteLine("Disconnected");
}
}
private void Oncharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
byte[] data = new byte[args.CharacteristicValue.Length];
DataReader.FromBuffer(
args.CharacteristicValue).ReadBytes(data);
string text = Encoding.UTF8.GetString(data, 0, data.Length);
}
UPDATE 1
I tried to check Characteristic Properties before set value changed event handlers for my characteristics by following the answer given by rudi belt on SO.
if (characteristic.CharacteristicProperties == (GattCharacteristicProperties.Read | GattCharacteristicProperties.Notify))
{
characteristic.ValueChanged += Oncharacteristic_ValueChanged;
}
Unfortunately, this IF statement is not executed.
UPDATE 2
I have tried to remove ALL the codes inside Oncharacteristic_ValueChanged method. But it still gives me the same error
System.ArgumentException: 'Value does not fall within the expected range.'
I have been spending a lot of time trying to solve this problem. I will be very happy if anyone can help me on this. Thank you!
Reading your efforts in the former question I can provide a working example, but first some explanation.
myDevice.ConnectionStatusChanged is not needed, it is only used to notice a connection is lost or connected. You have to connect to your device first and handle things in the connection method.
After you have succeeded in connecting you have to get the service that contains the characteristic you want to use for read, write, notify or indicate.
When you have selected the service You can get the characteristics of that service.
Select the characteristic by Uuid, or in my example with CharacteristicProperties.HasFlag.
This flag in my example is Notify.
In the code comments you find extra info.
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;
namespace App1
{
public sealed partial class MainPage : Page
{
GattDeviceServicesResult serviceResult = null;
private BluetoothLEDevice myDevice;
private GattCharacteristic selectedCharacteristic;
public MainPage()
{
this.InitializeComponent();
ConnectDevice();
}
private async void ConnectDevice()
{
//This works only if your device is already paired!
foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id);
// Display BLE device name
var dialogBleDeviceName = new MessageDialog("BLE Device Name " + bleDevice.Name);
await dialogBleDeviceName.ShowAsync();
myDevice = bleDevice;
}
if (myDevice != null)
{
int servicesCount = 3;//Fill in the amount of services from your device!!!!!
int tryCount = 0;
bool connected = false;
while (!connected)//This is to make sure all services are found.
{
tryCount++;
serviceResult = await myDevice.GetGattServicesAsync();
if (serviceResult.Status == GattCommunicationStatus.Success && serviceResult.Services.Count >= servicesCount)
{
connected = true;
Debug.WriteLine("Connected in " + tryCount + " tries");
}
if (tryCount > 5)//make this larger if faild
{
Debug.WriteLine("Failed to connect to device ");
return;
}
}
if (connected)
{
for (int i = 0; i < serviceResult.Services.Count; i++)
{
var service = serviceResult.Services[i];
//This must be the service that contains the Gatt-Characteristic you want to read from or write to !!!!!!!.
string myServiceUuid = "0000ffe0-0000-1000-8000-00805f9b34fb";
if (service.Uuid.ToString() == myServiceUuid)
{
Get_Characteriisics(service);
break;
}
}
}
}
}
private async void Get_Characteriisics(GattDeviceService myService)
{
var CharResult = await myService.GetCharacteristicsAsync();
if (CharResult.Status == GattCommunicationStatus.Success)
{
foreach (GattCharacteristic c in CharResult.Characteristics)
{
if (c.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
{
selectedCharacteristic = c;
break;
}
}
try
{
// Write the ClientCharacteristicConfigurationDescriptor in order for server to send notifications.
var result = await selectedCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
if (result == GattCommunicationStatus.Success)
{
var dialogNotifications = new MessageDialog("Successfully registered for notifications");
await dialogNotifications.ShowAsync();
selectedCharacteristic.ValueChanged += SelectedCharacteristic_ValueChanged;
}
else
{
var dialogNotifications = new MessageDialog($"Error registering for notifications: {result}");
await dialogNotifications.ShowAsync();
}
}
catch (Exception ex)
{
// This usually happens when not all characteristics are found
// or selected characteristic has no Notify.
var dialogNotifications = new MessageDialog(ex.Message);
await dialogNotifications.ShowAsync();
await Task.Delay(100);
Get_Characteriisics(myService); //try again
//!!! Add a max try counter to prevent infinite loop!!!!!!!
}
}
else
{
var dialogNotifications = new MessageDialog("Restricted service. Can't read characteristics");
await dialogNotifications.ShowAsync();
}
}
private void SelectedCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
}
}
}
If you have problems with this code feel free to ask in comments.

Receiving Notfication when app is running

In fear of asking a question that might have been asked before, but my search skills did not able me to find. Okay, so here goes.
I have Windows Phone 8 App, where I can receive TileUpdates and Notifications, when My app is not running in the foreground. This I did by following http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202940(v=vs.105).aspx
In that link I learned that for getting notifications when app is running I should simply attach an event for the reception case. This I did in my AcquirePushChannel() function, which looks as follows:
public static void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
if (!CurrentChannel.IsShellToastBound)
{
CurrentChannel.BindToShellTile();
}
CurrentChannel.BindToShellToast();
CurrentChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(Push_NotificationRecieved);
}
if (!CurrentChannel.IsShellTileBound)
{
CurrentChannel.BindToShellToast();
CurrentChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(Push_NotificationRecieved);
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Push_NotificationChannelChanged);
}
I have implemented CurrentChannel.ChannelUriUpdated, for the case that channelUri changes and I execute some code to also changes my ChannelsTable in the Cloud.
My Push_NotificationRecieved looks like:
private static void Push_NotificationRecieved(object sender, NotificationEventArgs e)
{
StringBuilder message = new StringBuilder();
string relativeUri = string.Empty;
message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
// Parse out the information that was part of the message.
foreach (string key in e.Collection.Keys)
{
message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
if (string.Compare(
key,
"wp:Param",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.CompareOptions.IgnoreCase) == 0)
{
relativeUri = e.Collection[key];
}
}
// Display a dialog of all the fields in the toast.
MessageBox.Show(message.ToString());
//Dispatcher.BeginInvoke((message) => MessageBox.Show(message.ToString()));
}
I cannot see why the notification is not registered. Since in my log in the cloud I receive that the Toast Notification was received?
Any Ideas? Furthermore can I display the toast from the code or something similar, as far as I have read it is not possible?
Extra
Have tried changing the functions to public but did not help with the problem.
Anybody have an Idea to why the event is not firing.
The answer you posted is almost correct. From the previous you have:
public static void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
if (!CurrentChannel.IsShellToastBound)
{
CurrentChannel.BindToShellTile();
}
CurrentChannel.BindToShellToast();
}
if (!CurrentChannel.IsShellTileBound)
{
CurrentChannel.BindToShellToast();
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Push_NotificationChannelChanged);
CurrentChannel.ShellToastNotificationReceived += CurrentChannel_ShellToastNotificationReceived;
}
And to that you have to add:
private static void CurrentChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
StringBuilder message = new StringBuilder();
string relativeUri = string.Empty;
message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
// Parse out the information that was part of the message.
foreach (string key in e.Collection.Keys)
{
message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
if (string.Compare(
key,
"wp:Param",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.CompareOptions.IgnoreCase) == 0)
{
relativeUri = e.Collection[key];
}
}
// Display a dialog of all the fields in the toast.
MessageBox.Show(message.ToString());
}
So all you send is inside the e.collection. So you can from the server send all kind of parameters.
Of course just after I set a bounty to run I got it working. So here is the updated code.
public static void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
if (!CurrentChannel.IsShellToastBound)
{
CurrentChannel.BindToShellTile();
}
CurrentChannel.BindToShellToast();
}
if (!CurrentChannel.IsShellTileBound)
{
CurrentChannel.BindToShellToast();
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Push_NotificationChannelChanged);
CurrentChannel.ShellToastNotificationReceived += CurrentChannel_ShellToastNotificationReceived;
}
Okay so the reason for this, is that you need to set the events on every startup. Then you will get the wished properties. Then you have to create your own code for getting what you want :)

Exception while tracking location in Windows Phone 8

When I try to track location it works perfectly but when i add service reference to it it throws an exception
when I try the same program without adding location only add service reference it works perfectly
My code is here below while copy from How to continuously track the phone's location for Windows Phone 8
public partial class MainPage : PhoneApplicationPage
{
Geolocator geolocator = null;
bool tracking = false;
ServiceReference2.GetPositionClient client = new ServiceReference2.GetPositionClient();
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (IsolatedStorageSettings.ApplicationSettings.Contains("LocationConsent"))
{
// User has opted in or out of Location
return;
}
else
{
MessageBoxResult result =
MessageBox.Show("This app accesses your phone's location. Is that ok?",
"Location",
MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
IsolatedStorageSettings.ApplicationSettings["LocationConsent"] = true;
}
else
{
IsolatedStorageSettings.ApplicationSettings["LocationConsent"] = false;
}
IsolatedStorageSettings.ApplicationSettings.Save();
}
}
private void TrackLocation_Click(object sender, RoutedEventArgs e)
{
if ((bool)IsolatedStorageSettings.ApplicationSettings["LocationConsent"] != true)
{
// The user has opted out of Location.
return;
}
if (!tracking)
{
geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
geolocator.MovementThreshold = 100; // The units are meters.
geolocator.StatusChanged += geolocator_StatusChanged;
geolocator.PositionChanged += geolocator_PositionChanged;
tracking = true;
TrackLocationButton.Content = "stop tracking";
}
else
{
geolocator.PositionChanged -= geolocator_PositionChanged;
geolocator.StatusChanged -= geolocator_StatusChanged;
geolocator = null;
tracking = false;
TrackLocationButton.Content = "track location";
StatusTextBlock.Text = "stopped";
}
}
void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
string status = "";
switch (args.Status)
{
case PositionStatus.Disabled:
// the application does not have the right capability or the location master switch is off
status = "location is disabled in phone settings";
break;
case PositionStatus.Initializing:
// the geolocator started the tracking operation
status = "initializing";
break;
case PositionStatus.NoData:
// the location service was not able to acquire the location
status = "no data";
break;
case PositionStatus.Ready:
// the location service is generating geopositions as specified by the tracking parameters
status = "ready";
break;
case PositionStatus.NotAvailable:
status = "not available";
// not used in WindowsPhone, Windows desktop uses this value to signal that there is no hardware capable to acquire location information
break;
case PositionStatus.NotInitialized:
// the initial state of the geolocator, once the tracking operation is stopped by the user the geolocator moves back to this state
break;
}
Dispatcher.BeginInvoke(() =>
{
StatusTextBlock.Text = status;
});
}
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
client.getPosCompleted += new EventHandler<ServiceReference2.getPosCompletedEventArgs>(sendData);
client.getPosAsync(11,11);
Dispatcher.BeginInvoke(() =>
{
LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00");
LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00");
});
}
public void sendData(object sender, ServiceReference2.getPosCompletedEventArgs e)
{
dd.Text = e.Result;
}
}
you have
client.getPosCompleted += new EventHandler<ServiceReference2.getPosCompletedEventArgs>(sendData);
but you haven't given Client any values anywhere else, I assume that you are getting a null Reference exception, and that this is why.
It just resolved it , just the fault of setting of IIS because mobile and pc are on different network so the communication is not possible .i just the forward the port in router setting –

facebook desktop app C#

I am trying to build a desktop app to use facebook api and get data from friends.
Anyways I am stuck in the log in stage.
I have used some advice and made the log in to facebook with WebBrowser. It works great.
I am stuck at trying to make it give me status = Failed or success
I tried doing it like this at the end of the button_1 method
if (!w.DocumentText.Contains(#"<div class=""linkWrap noCount"">Messages</div>"))
{
w.Navigate(#"http://www.facebook.com/login.php");
MessageBox.Show("Login error. Wrong username or password!");
}
else
{
MessageBox.Show("Logged in successfully");
}
the < div class=""linkWrap noCount"">Messages< /div> is only shown while logged in so thats why I use it to see if a user is logged in
but the problem is it always gives me an error (wrong user and pass) becasue it reads it before the browser finishes to navigate to the page. I tried threads and thread sleep and even timers but it doesnt seem to work
an ideas?
here is the code:
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(WorkThreadFunction));
thread.Start();
string email = textBox1.Text;
string password = textBox2.Text;
// create a new browser
WebBrowser w = new WebBrowser();
w.Dock = DockStyle.Fill;
this.Controls.Add(w); // you may add the controll to your windows forms if you want to see what is going on
// latter you may not chose to add the browser or you can even set it to invisible...
// navigate to facebook
w.Navigate(#"http://www.facebook.com/login.php");
// wait a little
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(10);
System.Windows.Forms.Application.DoEvents();
}
HtmlElement temp=null;
// while we find an element by id named email
while (temp == null)
{
temp = w.Document.GetElementById("email");
System.Threading.Thread.Sleep(10);
System.Windows.Forms.Application.DoEvents();
}
// once we find it place the value
temp.SetAttribute("value", email);
temp = null;
// wiat till element with id pass exists
while (temp == null)
{
temp = w.Document.GetElementById("pass");
System.Threading.Thread.Sleep(10);
System.Windows.Forms.Application.DoEvents();
}
// once it exist set its value equal to passowrd
temp.SetAttribute("value", password);
// if you already found the last fields the button should also be there...
var inputs = w.Document.GetElementsByTagName("input");
int counter = 0;
bool enableClick = false;
// iterate through all the inputs in the document
foreach (HtmlElement btn in inputs)
{
try
{
var att = btn.GetAttribute("tabindex");
var name = btn.GetAttribute("id");
if (enableClick)// button to submit always has a differnt id. it should be after password textbox
{
btn.InvokeMember("click");
counter++;
}
if (name.ToUpper().Contains("PASS") || att=="4")
{
enableClick = true; // button should be next to the password input
}
// try a max of 5 times
if (counter > 5)
{
break;
}
}
catch
{
}
}
}
Checkout the facebook-sharp SDK for Windows forms:
https://github.com/facebook-csharp-sdk/facebook-winforms
I recommend you use Facebook C# SDK. It uses the OAuth protocol, for user-authentication.
Down an code example how to get user friends with Facebook-C#-SDK:
using Facebook; //add reference to facebook dll for it work
declare the fields:
private FacebookOAuthResult result;
private FacebookOAuthClient OAuth;
and
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser1.Url.AbsolutePath == "/login.php")
{
// do login..
}
if (FacebookOAuthResult.TryParse(e.Url, out result))
{
if (result.IsSuccess)
{
FacebookClient fbClient = new FacebookClient(result.AccessToken);
dynamic friends = fbClient.Get("/me/friends"); //User friends
// do something..
}
else
{
string errorDescription = result.ErrorDescription;
string errorReason = result.ErrorReason;
string msg = String.Format("{0} ({1})", errorReason, errorDescription);
MessageBox.Show(msg, "User-authentication failed!");
}
}
}
and then for start user-authentication:
//..
OAuth = new FacebookOAuthClient();
OAuth.AppId = appId; // see link above,you can find how to get it
OAuth.AppSecret = appSecret; // see link above,you can find how to get it
Uri loginUrl = OAuth.GetLoginUrl(paramenters);
webBrowser1.Navigate(loginUrl.AbsoluteUri);

Categories