The Windows Live ID Client SDK documentation shows you quite well how to sign in silently or with the built-in dialog - yet there is a small problem if you want to use this within a Powershell cmdlet, because the threading model has to be set to Single Threaded Apartment State (STA).
The Powershell Team Blog has a good entry on how to change the threading model.
To use the Windows Live Client SDK library within a powershell cmdlet you have to start another thread and set the apartmentstate to STA, here's how to do it:
ExecutionResult class:
internal class ExecutionResult
{
private object output;
private Exception error;
public Object Output
{
get { return output; }
set { output = value; }
}
public Exception Error
{
get { return error; }
set { error = value; }
}
}
PerformWindowsLiveClientLogin:
private void PerformWindowsLiveClientLogin(object outputToWriteTo)
{
ExecutionResult result = (ExecutionResult)outputToWriteTo;
WindowsLiveClientLogin(result);
if (null != waitHandle)
{
waitHandle.Set();
}
}
WindowsLiveClientLogin:
private void WindowsLiveClientLogin(ExecutionResult result)
{
try
{
oIDMgr =
IdentityManager.CreateInstance(
"Peter Schneider;ps@ugwa.net;Windows Live Powershell CmdLets",
"Windows Live Powershell CmdLets");
}
catch (WLLogOnException wlex) { result.Error = wlex; }
try
{
oID = oIDMgr.CreateIdentity(defaultUserName);
}
catch (WLLogOnException wlex) { result.Error = wlex; }
if (oID != null)
{
if (oID.SavedCredentials == CredentialType.UserNameAndPassword)
{
try
{
if (oID.Authenticate(AuthenticationType.Silent))
{
// User authenticated successfully
}
else
{
// Show Windows Live Client Login Dialog
oID.Authenticate();
}
}
catch (WLLogOnException wlex) { result.Error = wlex; }
}
else
{
// Insufficient credentials saved for user,
// show Windows Live Client Login Dialog
oID.Authenticate();
}
}
try
{
ticket = oID.GetTicket("https://cumulus.services.live.com/"
+ oID.UserName, "MBI", true);
}
catch (WLLogOnException wlex) { result.Error = wlex; }
}
BeginProcessing:
protected override void BeginProcessing()
{
ExecutionResult result = new ExecutionResult();
Thread executionThread =
new Thread(new ParameterizedThreadStart(PerformWindowsLiveClientLogin));
executionThread.SetApartmentState(ApartmentState.STA);
waitHandle = new ManualResetEvent(false);
executionThread.Start(result);
waitHandle.WaitOne();
string uri = @"https://cumulus.services.live.com/"+oID.UserName+"/LiveContacts/Contacts";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers.Add("Authorization", "WLID1.0 t=\"" + ticket +"\"");
request.AllowAutoRedirect = false;
request.UserAgent = "WindowsLive.Contacts Powershell CmdLets";
request.ContentType = "text/xml";
request.Pipelined = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
XmlDocument contacts = new XmlDocument();
contacts.LoadXml(new StreamReader(response.GetResponseStream()).ReadToEnd());
WriteObject(contacts);
}
You can download the whole source for the CmdLet here:
Install the
Windows Live Client SDK, compile the cmdlet and afterwards use:
installutil /i WindowsLive.Contacts
add-pssnapin WindowsLive.Contacts
to use the cmdlet in powershell. If installing on Vista, please remember to run powershell as Administrator.
Here are some sample scripts to get started:
Enumerate all WindowsLive Contacts using Windows Live Client SDK Login Dialog:
$result = get-windowslivecontact
$result.Contacts.Contact | select WindowsLiveId
Enumerate all WindowsLive Contacts using Silent Login:
$result = get-windowslivecontact -WindowsLiveId "your@liveid.com"
$result.Contacts.Contact | select WindowsLiveId
Show WindowsLiveId from several Windows Live Accounts using SilentLogin
"first@live.com", "second@live.com" | % { get-windowslivecontact -WindowsLiveId $_ } | select WindowsLiveId
The Cmdlet returns the XmlDocument, which can easily be accessed via dot notation:
$result = get-windowslivecontact
$result.Contacts.Contact[0].Profiles.Personal
If you don't want to use the Windows Live Client SDK, take a look at this sample, which uses a RPS ticket for authentication - you can easily adopt the sample.
There are many things you could add to this sample. Use it as a starting point - yet I would be happy to here from extensions.. 