Reading Outlook contact in C# using any Microsoft Outlook version - c#

I have tried to read Microsoft Outlook contact using Microsoft Outlook 15.0 object library DLL, it works locally; when it comes to client, we do not know what version of Outlook is the client using. How to read if each client having different versions of Outlook?
I want to read the contact with any version of Microsoft Outlook Version using C#.
If you have any open source code, it helps a lot.
Please look at my code and help me where am doing wrong.
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Runtime.InteropServices;
using MsOutlook = Microsoft.Office.Interop.Outlook;
namespace Test
{
public class OutlookMailManager : IDisposable
{
public OutlookMailManager() { }
/// <summary>
/// Get MailContacts From Google (Gmail) using the provided username and password.
/// </summary>
/// <param name="maxEnries">Total number of entries to return</param>
/// <returns>The addressbook entries</returns>
public string GetOutlookMailContacts(int maxEnries)
{
MsOutlook.ApplicationClass OutlookApplication = new MsOutlook.ApplicationClass();
MsOutlook.NameSpace outlookNameSpace = OutlookApplication.GetNamespace("MAPI");
MsOutlook.MAPIFolder contactsCollection = outlookNameSpace.GetDefaultFolder(MsOutlook.OlDefaultFolders.olFolderContacts);
Microsoft.Office.Interop.Outlook.Items folderItems = contactsCollection.Items;
string rtnStr = "";
if (folderItems.Count > 0)
{
for (int i = 1; folderItems.Count >= i; i++)
{
object contactObj = folderItems[i];
if (contactObj is MsOutlook.ContactItem)
{
MsOutlook.ContactItem contact = (MsOutlook.ContactItem)contactObj;
rtnStr += contact.FullName + " (" + contact.BusinessTelephoneNumber + ")\n";
}
Marshal.ReleaseComObject(contactObj);
if (i == maxEnries) break;
}
}
Marshal.ReleaseComObject(folderItems);
Marshal.ReleaseComObject(contactsCollection);
Marshal.ReleaseComObject(outlookNameSpace);
return rtnStr;
}
}
}

You just need to use the PIAs corresponding the lowest Outlook version you need to support. Thus, you will be sure that only properties and methods existing in all Outlook versions are used. See C# app automates Outlook (CSAutomateOutlook) for the sample project.

Currently its working fine with my Outlook 2003 Version
CheckOut this code but i havent tested with different outlook version.but
Add Microsoft.Office.Interop.Outlook dll in reference
Microsoft.Office.Interop.Outlook.Items OutlookItems;
Microsoft.Office.Interop.Outlook.Application outlookObj;
MAPIFolder Folder_Contacts;
private void Form1_Load(object sender, EventArgs e)
{
outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Folder_Contacts = (MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
OutlookItems = Folder_Contacts.Items;
for (int i = 0; i < OutlookItems.Count; i++)
{
Microsoft.Office.Interop.Outlook.ContactItem contact = (Microsoft.Office.Interop.Outlook.ContactItem)OutlookItems[i + 1];
MessageBox.Show("FirstName:"contact.FirstName +" "+"LastName:"+contact.LastName +" "+"Emailid:"+contact.Email1Address);
}
}

Related

Optional Argument of COM Add-in vs Automation Add-in Written in C#

I am working on a library of COM Add-in and Excel Automation Add-in, whose core codes are written in C#. I'd like to set an optional argument for the function and I know that this is legal for both C# and VBA, and even Excel WorksheetFunction. But I find that finally the optional argument works exclusively for COM and Automation add-in, meaning that if one add-in is run first, then works well but the optional argument of the other one will not work.
Below please see the example:
In the VS 2013 solution, I have two projects: one is called TestVBA and another one is called TestExcel.
TestVBA is for the COM add-in and built through the "Excel 2013 Add-in" and there are two .cs files:
ThisAddIn.cs
This file is generated automatically and modified a little bit. The codes are
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
namespace TestVBA
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private ExcelVBA oExcelVBA;
protected override object RequestComAddInAutomationService()
{
if (oExcelVBA == null)
{
oExcelVBA = new ExcelVBA();
}
return oExcelVBA;
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
TestVBA.cs
This file is the main calculation file of COM add-in. The codes are
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
namespace TestVBA
{
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class ExcelVBA
{
public int TestAddVBA(int a = 1, int b = 1)
{
return a + b;
}
}
}
Another TestExcel is for the Excel Automation add-in and built through the C# "Class Library" and there are two .cs files either:
BaseUDF.cs
This file defines the decoration of two attributes. The codes are
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace BaseUDF
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public abstract class BaseUDF
{
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type)
{
// Add the "Programmable" registry key under CLSID.
Registry.ClassesRoot.CreateSubKey(
GetSubKeyName(type, "Programmable"));
// Register the full path to mscoree.dll which makes Excel happier.
RegistryKey key = Registry.ClassesRoot.OpenSubKey(
GetSubKeyName(type, "InprocServer32"), true);
key.SetValue("",
System.Environment.SystemDirectory + #"\mscoree.dll",
RegistryValueKind.String);
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type)
{
// Remove the "Programmable" registry key under CLSID.
Registry.ClassesRoot.DeleteSubKey(
GetSubKeyName(type, "Programmable"), false);
}
private static string GetSubKeyName(Type type,
string subKeyName)
{
System.Text.StringBuilder s =
new System.Text.StringBuilder();
s.Append(#"CLSID\{");
s.Append(type.GUID.ToString().ToUpper());
s.Append(#"}\");
s.Append(subKeyName);
return s.ToString();
}
// Hiding these methods from Excel.
[ComVisible(false)]
public override string ToString()
{
return base.ToString();
}
[ComVisible(false)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[ComVisible(false)]
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
TestExcel.cs
This file is the main calculation file of Excel Automation add-in. The codes are
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
using Extensibility;
namespace TestExcel
{
[Guid("7127696E-AB87-427a-BC85-AB3CBA301CF3")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class TestExcel : BaseUDF.BaseUDF
{
public int TestAddExcel(int a = 1, int b = 1)
{
return a + b;
}
}
}
After building, the two add-ins have been registered in the system and in Excel we can use them successfully.
For the Automation add-in, we call them in the spreadsheet as =TestAddExcel(2,3) and =TestAddExcel() both of them work very well and give the right result 5 and 2. However, when I try to call the COM add-in via
Sub TestVBA_Click()
Dim addIn As COMAddIn
Dim TesthObj As Object
Set addIn = Application.COMAddIns("TestVBA")
Set TestObj = addIn.Object
Range("Output").Value2 = TestObj.TestAddVBA(2, 3)
Range("Output").Offset(1, 0).Value2 = TestObj.TestAddVBA()
End Sub
The first call with all arguments existing works well, but for the second one with arguments missing shows the error Type mismatch.
The interesting thing is, when I close the test excel file and open it again, this time I test the COM add-in first, still via the above VBA codes, both two calls work very well. Then when I test the two spreadsheet functions which used to work well, only the first one is good, the second one with arguments missing =TestAddExcel() fails with #VALUE!.
It would be very nice if someone can help with this strange issue.
I am not sure how you Referenced the class library without Registering for COM? I see now, you're using Late Binding. I didnt know you could do that (didn't think it would let you) and suspect that is the problem, it also matches the Type mismatch error.
Follow the second solution in my canonical answer here on the 3 methods to call .Net from Excel or VBA and make sure you Register for COM:
Click on the Build tab and check the check box that says “Register for COM Interop”. At this point you have an extra step if you are running on Windows Vista or higher. Visual Studio has to be run with administrator privileges to register for COM Interop. Save your project and exit Visual Studio. Then find Visual Studio in the Start menu and right click on it and choose “Run as Administrator”. Reopen your project in Visual Studio. Then choose “Build” to build the add-in.
Optionally if the above doesn't work, follow the third solution in my answer and reference the Automation Add-In and use Early Binding, I've tested this and it works perfectly:
Sub TestVBA1_Click()
Dim addIn As COMAddIn
Dim TesthObj As Object
Set addIn = Application.COMAddIns("TestVBA")
Set TestObj = addIn.Object
Debug.Print TestObj.TestAddVBA(2, 3)
Debug.Print TestObj.TestAddVBA()
Dim dotNetClass As TestExcel.TestExcel
Set dotNetClass = New TestExcel.TestExcel
Debug.Print dotNetClass.TestAddExcel(7, 3)
Debug.Print dotNetClass.TestAddExcel()
End Sub
This is a total stab in the dark, but can you create overloaded versions of the method to mimic the way you would have accomplished this before C# had optional parameters and see if that would work?
public int TestAddExcel(int a, int b)
{
return a + b;
}
public int TestAddExcel(int a)
{
return a + 1;
}
public int TestAddExcel()
{
return 2;
}

How to get NickName property form a Saved Contact in Windows Phone

I want to show all contacts in my windows phone with their fields. (Eg: Name,DisplayName,NickName etc..)
I 'm able to get all properties from my Contact. But i'm unable to find 'NickName' property in my contact.
Please help me to get NickName property from a Contact.
please find this code for reference,
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel.Contacts;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Phone.PersonalInformation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
namespace ConatctsTestApp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
string searchText = "";
Windows.ApplicationModel.Contacts.ContactStore contactStore = await ContactManager.RequestStoreAsync();
IReadOnlyList<Contact> contacts = null;
if (String.IsNullOrEmpty(searchText))
{
// Find all contacts
contacts = await contactStore.FindContactsAsync();
}
else
{
// Find contacts based on a search string
contacts = await contactStore.FindContactsAsync(searchText);
}
for (int c = 0; c < contacts.Count; c++)
{
string impdate = "";
for (int i = 0; i < contacts[c].ImportantDates.Count; i++)
{
impdate = impdate + contacts[c].DisplayName + "\n";
ContactDateKind kind = contacts[c].ImportantDates[i].Kind;
impdate = impdate + kind.ToString() + "\n";
impdate = impdate + (contacts[c].ImportantDates[i].Day.Value + 1).ToString() +
"." + contacts[c].ImportantDates[i].Month.Value.ToString() +
"." + contacts[c].ImportantDates[i].Year.Value.ToString();
impdate = impdate + "\n";
}
for (int i = 0; i < contacts[c].Websites.Count; i++)
{
//Count 0
}
for (int i = 0; i < contacts[c].Addresses.Count; i++)
{
string addressKind = contacts[c].Addresses[i].Kind.ToString();
}
//MessageBox.Show(impdate);
}
}
}
}
Thanks and regards.
I was working on a Windows Phone 8.1 Runtime app recently and also came upon this same issue.
I just answered a similar older post here:
How to get Contact's Nickname Windows Phone 8.1 - Stack Overflow
It seems that the Nickname property of the Contact class has been documented by Microsoft, but not yet implemented into Visual Studio for other developers to use.
You can see all the properties for the Contact class here:
Contact class - Windows app development
And the details for Nickname property here:
Contact.Nickname | nickname property - Windows app development
Check the property page. A message says it's not released and the requirements are Windows 10.
It does seem strange that users can enter a Nickname in the People app, but we as other developers can't use it in our own apps. I guess that's just the way it is for now with Windows Phone 8.1 custom apps.

Does SharePoint 2007 has any Client SDK available?

We have a SharePoint server 2007 and we are trying to make few entries into the SharePoint using the c#.net code. I came to know that we can use the SharePoint Client SDK components. But no where I found the SDK for 2007 version of SharePoint .
Is it possible to use the SharePoint 2013 Client SDK components to access the SharePoint 2007 site and do all the get or update actions ?
I don't know if the 2013 SDK can be used for 2007 instances, but I know that the SharePoint 2007 SDK is available here.
Since SharePoint Client Components SDK consists of collection of client-side object model (CSOM) DLLs and CSOM is not supported in SharePoint 2007, there is no release of SharePoint Client SDK for 2007 version.
But you could utilize SharePoint 2007 Web Services for that purpose, the following example demonstrates how to consume SharePoint Web Services to create a List Item:
using System;
using System.Collections.Generic;
using System.Net;
using System.Xml;
namespace SharePoint.Client
{
public class ListsClient : IDisposable
{
public ListsClient(Uri webUri, ICredentials credentials)
{
_client = new Lists.Lists();
_client.Credentials = credentials;
_client.Url = webUri + "/_vti_bin/Lists.asmx";
}
public ListsClient(Uri webUri)
{
_client = new Lists.Lists();
_client.Url = webUri + "/_vti_bin/Lists.asmx";
}
/// <summary>
/// Create a List Item
/// </summary>
/// <param name="listName">List Name</param>
/// <param name="propertyValues">List Item properties</param>
/// <returns></returns>
public XmlNode CreateListItem(string listName,Dictionary<string,string> propertyValues)
{
var payload = new XmlDocument();
var updates = payload.CreateElement("Batch");
updates.SetAttribute("OnError", "Continue");
var method = payload.CreateElement("Method");
method.SetAttribute("ID", "1");
method.SetAttribute("Cmd", "New");
foreach (var propertyValue in propertyValues)
{
var field = payload.CreateElement("Field");
field.SetAttribute("Name", propertyValue.Key);
field.InnerText = propertyValue.Value;
method.AppendChild(field);
}
updates.AppendChild(method);
return _client.UpdateListItems(listName, updates);
}
public void Dispose()
{
_client.Dispose();
GC.SuppressFinalize(this);
}
protected Lists.Lists _client; //SharePoint Web Services Lists proxy
}
}
Usage
How to create a Task item:
using (var client = new SPOListsClient(webUrl, userName, password))
{
var taskProperties = new Dictionary<string, string>();
taskProperties["Title"] = "Order approval";
taskProperties["Priority"] = "(2) Normal";
var result = client.CreateListItem(listTitle, taskProperties);
}
References
SharePoint 2007 Web Services
Lists.UpdateListItems Method

How can I open AutoCAD 2015 through the .NET API

I've been browsing for a good hour and have yet to find something that would help with this. I'm working on opening AutoCAD from the .NET API in VS2013 using C#, but for some reason, I can never get AutoCAD to actually launch. I'm using the following code:
using System;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
namespace IOAutoCADHandler
{
public static class ACADDocumentManagement
{
[CommandMethod("ConnectToAcad")]
public static void ConnectToAcad()
{
AcadApplication acAppComObj = null;
// no version number so it will run with any version
const string strProgId = "AutoCAD.Application";
// Get a running instance of AutoCAD
try
{
acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId);
}
catch // An error occurs if no instance is running
{
try
{
// Create a new instance of AutoCAD
acAppComObj = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true);
}
catch //// STOPS HERE
{
// If an instance of AutoCAD is not created then message and exit
// NOTE: always shows this box and never opens AutoCAD
System.Windows.Forms.MessageBox.Show("Instance of 'AutoCAD.Application'" +
" could not be created.");
return;
}
}
// Display the application and return the name and version
acAppComObj.Visible = true;
System.Windows.Forms.MessageBox.Show("Now running " + acAppComObj.Name +
" version " + acAppComObj.Version);
// Get the active document
AcadDocument acDocComObj;
acDocComObj = acAppComObj.ActiveDocument;
// Optionally, load your assembly and start your command or if your assembly
// is demandloaded, simply start the command of your in-process assembly.
acDocComObj.SendCommand("(command " + (char)34 + "NETLOAD" + (char)34 + " " +
(char)34 + #"C:\Users\Administrator\Documents\All Code\main-libraries\IOAutoCADHandler\bin\Debug\IOAutoCADHandler.dll" + (char)34 + ") ");
acDocComObj.SendCommand("DRAWCOMPONENT");
}
}
Unfortunately, it always stops at the nested catch statement and always displays the popup box without opening AutoCAD. Any suggestions on how to at least make AutoCAD open for me?
EDIT: Error message
The issue is you're coding (correctly) to the AutoCAD interop interface. I recommend against that (due to potential version changes).
The other issue is that the documentation for AutoCAD plugins using the newer .net api is for plugins when AutoCAD is already running.
Final issue could be that the program Id of AutCAD is a mystery. I have resorted to making that a configurable setting, but default to "AutoCAD.Application", which will take the currently registered AutoCAD.Application on the production machine. If there are multiple versions installed on the machine and you want to be specific, then you could append the version number (which you'll need to research) to the ProgID like: "AutoCAD.Application.19", or "AutoCAD.Application.20" for 2015.
For the first issue, one technique is to use dynamics for the autoCad objects, particularly for creating instances. I have used the ObjectARX api for creating my application in a dummy project, and then switching to dynamics when I'm happy with the properties and method names.
In a standalone .Net application that starts AutoCAD you could use something like:
// I comment these out in production
//using Autodesk.AutoCAD.Interop;
//using Autodesk.AutoCAD.Interop.Common;
//...
//private static AcadApplication _application;
private static dynamic _application;
static string _autocadClassId = "AutoCAD.Application";
private static void GetAutoCAD()
{
_application = Marshal.GetActiveObject(_autocadClassId);
}
private static void StartAutoCad()
{
var t = Type.GetTypeFromProgID(_autocadClassId, true);
// Create a new instance Autocad.
var obj = Activator.CreateInstance(t, true);
// No need for casting with dynamics
_application = obj;
}
public static void EnsureAutoCadIsRunning(string classId)
{
if (!string.IsNullOrEmpty(classId) && classId != _autocadClassId)
_autocadClassId = classId;
Log.Activity("Loading Autocad: {0}", _autocadClassId);
if (_application == null)
{
try
{
GetAutoCAD();
}
catch (COMException ex)
{
try
{
StartAutoCad();
}
catch (Exception e2x)
{
Log.Error(e2x);
ThrowComException(ex);
}
}
catch (Exception ex)
{
ThrowComException(ex);
}
}
}
When there are several versions of AutoCAD installed on a computer, creating an instance with the ProgID "AutoCAD.Application" will run the latest version started on this computer by the current user. If the version of the Interop assemblies used does not match the version that is starting, you'll get a System.InvalidCastException with an HRESULT 0x80004002 (E_NOINTERFACE).
In your specific case, the {070AA05D-DFC1-4E64-8379-432269B48B07} IID in your error message is the GUID for the AcadApplicationinterface in R19 64-bit (AutoCAD 2013 & 2014). So there is an AutoCAD 2013 or 2014 that is starting, and you cannot cast this COM object to a 2015 type because 2015 is R20 (not binary compatible).
To avoid that, you can add a specific version to your ProgID (like "AutoCAD.Application.20" for AutoCAD 2015 (R20.0) to 2016 (R20.1)) to start the version matching your Interop assemblies or you can use late binding (eg. remove your references to Autodesk.AutoCAD.Interop* and use the dynamic keyword instead of the AutoCAD types).
In the last case, you will lost autocompletion, but your program will work with all the versions of AutoCAD.
Check also 32-bit vs 64-bit because TypeLib/Interop assemblies are not the same.
I open the application in a much straight-forward way. First, be sure to reference the correct type library. The one I am using is AutoCAD 2014 Type Library, located at:
c:\program files\common files\autodesk shared\acax19enu.tlb
To initialize the application:
using AutoCAD;
namespace test
{
class Program
{
static void Main(string[] args)
{
AutoCAD.AcadApplication app;
app = new AcadApplication();
app.Visible = true;
Console.Read();
}
}
}
Try this:
"sourcefile" is the original file
"newfile" is the new file
[CommandMethod("ModifyAndSaveas", CommandFlags.Redraw | CommandFlags.Session)]
public void ModifyAndSaveAs()
{
Document acDoc = Application.DocumentManager.Open(sourcefile);
Database acDB = acDoc.Database;
Transaction AcTran = acDoc.Database.TransactionManager.StartTransaction();
using (DocumentLock acLckDoc = acDoc.LockDocument())
{
using (AcTran)
{
BlockTable acBLT = (BlockTable)AcTran.GetObject(acDB.BlockTableId, OpenMode.ForRead);
BlockTableRecord acBLTR = (BlockTableRecord)AcTran.GetObject(acBLT[BlockTableRecord.ModelSpace], OpenMode.ForRead);
var editor = acDoc.Editor;
var SelectionSet = editor.SelectAll().Value;
foreach (ObjectId id in SelectionSet.GetObjectIds())
{
Entity ent = AcTran.GetObject(id, OpenMode.ForRead) as Entity;
//modify entities
}
AcTran.Commit();
}
}
acDB.SaveAs(newfile, DwgVersion.AC1021);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Tekkit
{
class Program
{
static void Main(string[] args)
{
//make sure to add last 2 using statements
ProcessStartInfo start = new ProcessStartInfo("calc.exe");
Process.Start(start);//starts the process
}
}
}

Geolocation.CivicAddress.City returns empty win8 metro app

I want to create a simple app that shows me the city of the current application.
When I tried the code that I will paste below it returns empty for city, and it returns for country =US, but I live in Belgium.
According to this link
It says:
The location services provides access to location functionality, such as cell triangulations, WiFi (through IP address), and GPS. Also great many modern devices supports resolving location in some way from mentioned before, application must handle the case where location services cannot resolve the location or user has disabled location services from the Control Panel.
My Laptop does not have GPS, but with the IP, it should know the city and country.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Geolocation;
using System.Threading.Tasks;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace AlarmPro
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
//InitializeLocationServices();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
TextBlock txt = new TextBlock();
var location = await InitializeLocationServices();
txt.Text = location;
Grid.SetRow(txt, 0);
Grid.SetColumn(txt, 1);
}
private async Task<string> InitializeLocationServices()
{
//Initialize geolocator object
Geolocator geoLocator = new Geolocator();
try
{
//Try resolve the current location
var position = await geoLocator.GetGeopositionAsync();
if (position !=null)
{
string city = position.CivicAddress.City;
string country = position.CivicAddress.Country;
string state = position.CivicAddress.State;
string zip = position.CivicAddress.PostalCode;
string msg = "I am located in " + country;
if (city.Length > 0)
msg += ", city of " + city;
if (state.Length > 0)
msg += ", " + state;
if (zip.Length > 0)
msg += " near zip code " + zip;
return msg;
}
return string.Empty;
}
catch (Exception)
{
//Nothing to do - no GPS signal or some timeout occured.n .
return string.Empty;
}
}
}
}
Fairly certain you'll need to wait for the Geolocator to actually get a position.
The naive way would be to just keep trying in a while loop to see if there's a new update.
You'll want to probably want to attach to the PositionChanged event handler and wait for that to tell you that you have new updates.
Here's some info and code examples straight from the source.
http://msdn.microsoft.com/en-us/library/windows/apps/br225534.aspx
I do believe there's also some accuracy (DesiredAccuracy property) settings in there, perhaps that could be useful as well in making it be a bit more specific.

Categories