Peter Schneider


MCT, MCSD.NET, MCAD.NET, MCDBA

News

Locations of visitors to this page

  

Austrian .NET Community

Powershell CmdLet for LiveContacts Get-WindowsLiveContact

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.. smile_tongue

AtomSpacesPhotos Browser Sample Application

If you have seen Pablo Castro's MIX Session about accessing the Windows Live Services via Atom Publishing Protocol and want to play yourself with the protocol, I've built a quick and dirty WinForms app, which logs you in with your Windows Live ID and allows you to edit the request uri.

It doesn't use the Windows Live Client SDK, but uses a Rps ticket, which we get via SOAP request.

You should first add the photo module to your spaces account (http://spaces.live.com)

Afterwards you can connect with your Windows Live ID and password and examine your space...

CropperCapture[4]

 Download the sample application here:

 

Be aware that the sample application writes to C:\Temp and does not delete the downloaded information - so do yourself if you use the app on a different computer.

Background information:

The challenging part is more or less how to get authenticated within the winforms application. Most of the samples and documentation uses the delegated authentication model, which can only be used by webapplications.

For this browser I've used the TicketAcquirer class, which I found on MSDN Forums. At least I've found several versions, some working, some not. This one works, and I've slightly modificated it, so that you can pass your username and password along.

FYI: If you are behind a proxy you might want to add a new instance of a WebProxy class to the request...

public class TicketAcquirer
{
    private const string applicationId = "10"; 

    private string soapEnvelope = @"<s:Envelope
      xmlns:s = ""http://www.w3.org/2003/05/soap-envelope""
      xmlns:wsse = ""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""
      xmlns:saml = ""urn:oasis:names:tc:SAML:1.0:assertion""
      xmlns:wsp = ""http://schemas.xmlsoap.org/ws/2004/09/policy""
      xmlns:wsu = ""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd""
      xmlns:wsa = ""http://www.w3.org/2005/08/addressing""
      xmlns:wssc = ""http://schemas.xmlsoap.org/ws/2005/02/sc""
      xmlns:wst = ""http://schemas.xmlsoap.org/ws/2005/02/trust"">
      <s:Header>
       <wlid:ClientInfo xmlns:wlid = ""http://schemas.microsoft.com/wlid"">
         <wlid:ApplicationID>{0}</wlid:ApplicationID>
       </wlid:ClientInfo>
       <wsa:Action s:mustUnderstand = ""1"">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
       <wsa:To s:mustUnderstand = ""1"">https://dev.login.live.com/wstlogin.srf</wsa:To>
       <wsse:Security>
         <wsse:UsernameToken wsu:Id = ""user"">
           <wsse:Username>{1}</wsse:Username>
           <wsse:Password>{2}</wsse:Password>
         </wsse:UsernameToken>
       </wsse:Security>
     </s:Header>
     <s:Body>
       <wst:RequestSecurityToken Id = ""RST0"">
         <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
         <wsp:AppliesTo>
            <wsa:EndpointReference>
               <wsa:Address>http://live.com</wsa:Address>
            </wsa:EndpointReference>
         </wsp:AppliesTo>
         <wsp:PolicyReference URI = ""MBI""></wsp:PolicyReference>
      </wst:RequestSecurityToken>
     </s:Body>
     </s:Envelope>";

    public string GetTicket(string username, string password)
    {
        soapEnvelope = String.Format(soapEnvelope, "10", username, password);

        const string url = @"https://dev.login.live.com/wstlogin.srf";
        WebRequest request = WebRequest.Create(url);
        request.Method = "POST";
        request.ContentType = "application/soap+xml; charset=UTF-8";
        request.Timeout = 10 * 1000;
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(soapEnvelope);
        request.GetRequestStream().Write(bytes, 0, bytes.Length);
        request.GetRequestStream().Close();
        WebResponse response;
        response = request.GetResponse();
        string xml;
        using (System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream()))
            xml = reader.ReadToEnd();
        response.Close();
        XmlDocument document = new XmlDocument();
        document.LoadXml(xml);
        XmlNamespaceManager nsManager = new XmlNamespaceManager(document.NameTable);
        nsManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        XmlNode node = document.SelectSingleNode(@"//wsse:BinarySecurityToken/text()", nsManager);
        if (node == null)
            return null;
        else
            return node.Value;
    }

}

The usage of the class is really simple:

TicketAcquirer ta = new TicketAcquirer();
ticket = ta.GetTicket(txtUsername.Text, txtPassword.Text);

We can use the ticket in further requests:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers.Add("Authorization", "WLID1.0 t=\"" + ticket + "\"");
request.AllowAutoRedirect = false;
request.UserAgent = "AtomPub Sample";
request.ContentType = "text/xml";
request.Pipelined = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "GET";

Review the documentation at samples and documentation and play yourself.. smile_tongue

Posted: Mar 21 2008, 04:43 PM by pschneider | with 1 comment(s)
Filed under: ,
Planetary-Scale Views on an Instant-Messaging Network

Here's a link to a quite interesting study, you might be interested in. It actually presents a study of anonymized data capturing a month of high-level communication activities within the whole of the Microsoft Messenger instant-messaging system.

Quite funny: Which country do you think has the largest number of Messenger users?

Click here for the study

Posted: Mar 17 2008, 08:07 AM by pschneider | with no comments
Filed under:
Switch Right Windows and Right Alt Key

I've just bought a Apple Keyboard (USB) and wanted to switch the key mapping of the right windows and right alt key..

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,5c,e0,38,e0,38,e0,5c,e0,\
  00,00,00,00

To swap both the left and the right Windows and Alt Key use:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,07,00,00,00,37,e0,64,00,5b,e0,38,00,\
  38,00,5b,e0,5c,e0,38,e0,38,e0,5c,e0,47,e0,63,e0,00,00,00,00

Reboot or log off afterwards.

Open Url Activity for IE8

More or less often you find Url's in webpages (for example in forum comments) which are not hyperlinked.

You then Copy and Paste the Url into the Browser's address bar to open it. With this little IE8 activity you can open the Url via the activity smarttag.
OpenUrlActivity

As the {selection} variable is not accepted in the action attribute of the execute element, I've entered the [your domain] placeholder, which you might want to change to your domain to get the sample running.

<?xml version="1.0" encoding="UTF-8"?>
<openServiceDescription xmlns="
http://www.microsoft.com/schemas/openservicedescription/1.0">
<homepageUrl>
http://[your domain]</homepageUrl>
<display>
<name>Open URL in Browser</name>
<icon>
http://www.live.com/favicon.ico</icon>
</display>
<activity category="share">
  <activityAction context="selection">
    <preview action="
http://[your domain]/Redirect.aspx">
       <parameter name="url" value="{selection}"/>
    </preview>
    <execute action="
http://[your domain]/Redirect.aspx">
       <parameter name="url" value="{selection}"/>
    </execute>
  </activityAction>
</activity>
</openServiceDescription>

To get this sample running save the above code snippet to a XML file and upload it to [your domain] and save it as OpenUrlActivity.xml

You then need a little "install" routine:

<button onclick="window.external.addService('http://[your domain]/OpenUrlActivity.xml')">Add OpenUrl Activity
</button>

Needless to say that you also need the Redirect.aspx where you redirect the user to the value passed with the url parameter.

For a detailed description of the Activity XML Format see http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=ie8whitepapers&ReleaseId=566

Academic Community Launch 2008 Austria

Alex, Mario, Horst and Christian are organizing the so called “Academic Community Launch 2008″ in Austria. 8)

communitylaunch

The community launch is free for students and interested people (free as you don’t have to pay any entry fee and you get something to drink and eat for free). They are going to talk about the new features in Visual Studio 2008 (Mario), the new data features in .NET 3.5, SQL Server 2008 and beyond (Alex) and the new features in .NET 3.5 such as LINQ, anonymous types, lambda expressions, XML literals, own LINQ providers, … (Christian).

The talks are going to be in German and they will tour all Austria; including Salzburg, Linz, Hagenberg, Innsbruck, Wien, Graz and Klagenfurt.

Posted: Mar 03 2008, 12:58 PM by pschneider | with no comments
Filed under:
SQL Server 2008 gratis E-Book

Auf http://csna01.libredigital.com/?urss1q2we6 kann man zur Zeit die E-Book Version von Peter DeBetta's Buch "Introduction SQL Server 2008" herunterladen (Chapter 1: Declarative Management Framework). Für registrierte Benutzer gibt es ein zusätzliches Chapter (Transact-SQL Enhancement).

Für weitere E-Learning Angebote einfach auf http://www.microsoft.com/learning/sql/2008/default.mspx vorbeischauen...

Posted: Mar 03 2008, 07:03 AM by pschneider | with no comments
Filed under:
Silverlight Snow Effect

Old but nice effect. Download the source (see attachment of this post) and feel free to use it. Yet it comes without any warranty.. ;-)

Posted: Dec 06 2007, 02:57 PM by pschneider | with 2 comment(s)
Filed under:
Brainfuck Compiler and Interpreter in Powershell

Surley some of you know the Brainfuck programming language... there are many compilers and interpreters around, yet I haven't found some for powershell... so here we go:

Powershell Brainfuck Interpreter:

param ($i)

$t = @{ '>'='$p++;';
'<'='$p--;';
'+'='$m[$p]++';
'-'='$m[$p]--';
'.'='write-host $([char]$m[$p]) -n ';
','='$m[$p]=$host.ui.ReadLine() ';
'['='while ($m[$p] -ne 0) {';
']'='}';
}

$c = '$p=0;$m=new-object "byte[]" 32768'+"`n" ; gc $i -Enc Byte -r 1 | % {$c+=$t["$([char]$_)"]+"`n"}

invoke-expression $c

Powershell Brainfuck Compiler:

param ( [string] $infile = $(throw "Please specify input file (.b)"),
[string] $outfile = $(throw "Please specify output file (.cs)"),
[switch] $run = $false
)

$csc = (join-path ($env:windir) Microsoft.NET\Framework\v2.0.50727\csc.exe)

$transpose = @{'>' = 'p++;';
'<' = 'p--;';
'+' = 'm[p]++;';
'-' = 'm[p]--;';
'.' = 'Console.Write(m[p]);';
',' = 'm[p]=Console.ReadLine();';
'[' = "while (m[p]!=0) {"
']' = '}';
}

$header = @"
using System;
public class Program {
public static void Main() {
int p=0;
char[] m=new char[32768];
"@

if ($(test-path $outfile)) { rm $outfile | out-null }
$header | out-file $outfile -append

get-content $infile -encoding Byte -readcount 1 |
% { $transpose["$([char]$_)"] } | out-file $outfile -append

"}}" | out-file $outfile -append

& $csc `/target:exe $outfile | out-null

if ($run) {
$outfile = $outfile.Replace(".cs",".exe")
& .`/$outfile
}

You can find the both script files (compiler and interpreter) in the attachment of this post.

Have fun!

Posted: Apr 08 2007, 05:23 AM by pschneider | with 4 comment(s)
Filed under: ,
MSDN Briefing: MSBuild Unveiled

Am 28.2.2007 fand in Wien das MSDN Briefing mit dem Thema "MSBuild Unveiled" statt.

Ihr könnt die Präsentation hier im Anhang herunterladen.

Nach dem Briefing sind weitere Fragen aufgetaucht, unter anderem, wie kann man Solutions programmatisch builden und VC++ Projekte mit MSBuild erstellen lassen.

Hier ein kleines Code Snippet, um eine Solution mit der Build Engine in der Release Configuration für die X64 Platform zu builden:

Engine engine = new Engine(@"C:\Windows\Microsoft.NET\Framework\v2.0.50727");

Project solution = new Project(engine);
solution.Load(@"D:\Samples\SampleApplication.sln");

solution.SetProperty("Configuration", "Release");
solution.SetProperty("Platform", "X64");

solution.Build();

Benötigt wird lediglich eine Referenz auf Microsoft.Build.BuildEngine.

VC++ Projekte: Nicht bzw. nur teilweise machbar. Geplant ist das ganze erst nach dem Orcas (nächste Visual Studio Version) Release...

Es gibt jedoch einen VCBuild Task (siehe hierfür http://msdn2.microsoft.com/en-us/library/8xcy2245.aspx)
Für einfachere VC++ Projekte sollte das funktionieren...

Hier aber ein paar Links zum Weiterlesen:
http://msdn.microsoft.com/msdnmag/issues/06/06/InsideMSBuild/
http://msdn2.microsoft.com/en-us/library/0k6kkbsd.aspx
http://msbuildtasks.tigris.org/

Die Literatur zu MSBuild ist nicht gerade vielfältig, hier dennoch eine kleine Buchempfehlung:

Deploying .NET Applications: Learning MSBuild and ClickOnce (Expert's Voice in .Net)
by Sayed Y. Hashimi, Sayed Ibrahim Hashimi

Read more about this title...

Posted: Feb 28 2007, 10:15 PM by pschneider | with no comments
Filed under:
More Posts Next page »