jump to navigation

Fun with Powershell – Network connection reset Tuesday, 04/02/2013

Posted by Percy in Fun with Powershell, Technology.
add a comment

I realized that I have never posted one of the Powershell commands (or scriptlets) that I use most often. I use a lot of VMs for my every day development work. Often, the virtualized network connection can get out of whack with my physical network connection. So, I find myself running these three commands over and over:

ipconfig /release
ipconfig /renew
ipconfig /flushdns

It’s somewhat of a “scorched earth” approach to network issues, but it’s short, quick and it seems to work fairly well. I realized that these three commands are the same except for the parameter passed into ipconfig. So, now I just fire up Powershell and fire off this one liner:

@("release", "renew", "flushdns") | % { ipconfig /"$_" }

I’ve turned this into a function in my profile (Reset-Network), but I often forget it’s there and just type the whole thing, since it’s so short.

Anyways, short and simple, but pretty effective. One more reason I’m enjoying playing with Powershell.

Advertisements

Extension methods – do or do not? Monday, 03/04/2013

Posted by Percy in Programming, Technology.
1 comment so far

I was in a recent code review at work, and we came across the following code which pre-dated the current release. So, it technically wasn’t up for review, but it sparked an interesting discussion.

public static class Extensions
{
    public static bool IsNullOrEmpty(this string input)
    {
        return string.IsNullOrEmpty(input);
    }
}

In the interest of full disclosure, I think that this method (along with a few others) should be part of the .NET framework. So, I’m actually a fan of having a method like this in the project I’m working on.

However, not everyone in the code review I was in was a fan of having a method like this. I think there are some valid concerns about the use of extension methods – just like with any tool out there. You can use a great tool in the wrong way and have disaserous results. So, what comes next, while a defense of this particular situation, may not apply to all use of extension methods.

As I’ve stated before, everyone is entitled to their opinion. I just like to back mine up with some of my reasoning. You’re welcome to agree or disagree.

Here’s my main contention – I think extension methods allow you to write code that is more readable, and also allows you to write less code by making reusable methods.

In this case, I think this extension method, while just really a wrapper around another method, actually makes the code more readable. It allows you to write code that can be easily read by those that might not even be developers. So, adding this extension method, you can do something like this:

string name = "My Name";
if(name.IsNullOrEmpty())
{
    // Do something
}

To me, that reads “If name is null or empty, do something” – fairly straightforward. Now, not having the extension method doesn’t add more lines of code. So, without it, you would have this:

string name = "My Name";
if(string.IsNullOrEmpty(name))
{
    // Do something
}

Honestly, I tried to come up with a simple sentence that follows that code layout, and I couldn’t. The best I could come up with is “If a string value is null or empty represented by the variable name, do something”. I’m not even sure if that’s grammatically correct. Again, the code doesn’t really function much differently. In this case it’s all just in how the code looks. However, I think the code with the extension method has an advantage over the one without.

There’s another example that we’ve used a lot. It’s an extension method that I’ve added to a number of projects, that I think should be part of the framework.

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    if(source != null && action != null)
    {
        foreach(T item in source)
        {
            action(item);
        }
    }
}

This allows you to do things like this:

IEnumerable customers = Customer.GetAll();
customers.ForEach(c => Console.WriteLine(c.Name));

Without the extension method, the same code would be:

IEnumerable customers = Customer.GetAll();
foreach(Customer c in customers)
{
    Console.WriteLine(c.Name);
}

So, it’s not a complex example, but two lines of code with the extension method become five without it. Even given that the bracket lines are unnecessary since you only have one line, that still is three lines of code against two in the original.

Also, one powerful feature that extension methods have over regular methods is that you can actually and successfully call extension methods “on” objects set to null. Since the method is actually static, and it’s not actually being called from code inside the object, you can do a null check on the “this” object and handle things appropriately. So, you can do something like this:

IEnumerable customers = null;
customers.ForEach(c => Console.WriteLine(c.Name));

In this case, the code just won’t do anything, but it won’t throw a null reference exception. Since I check for null in the extension method, it’s handled.

There are some downsides to Extension methods, however. I’m a believer that the benefits outweigh the issues, but I feel it’s at least appropriate to throw those out there.

So, it can get confusing that you’re calling methods that actually don’t exist within the object itself. You might think that the base string object always has an “IsNullOrEmpty” method, so any string in any project can use it and that might not be the case. It would only be available in those projects where the extension method is available and the namespace references. Also, in versions of C# 3.0 and higher, you can actually have instance methods and extension methods on the same object with the same signature. In that case, the instance method will be given priority. However, that could get confusing if you’re expecting the extension method to be called, and you can’t seem to figure out why it’s not being called.

I’m sure there are other issues with extension methods that I’m leaving out. What’s your opinion? Extension methods – do or do not?

How I Got Started in Computers and Programming Thursday, 02/28/2013

Posted by Percy in Personal, Programming, Technology.
Tags: ,
7 comments

After coming across this article, I started thinking about how I got set down the path I’m on. So, if for nothing that to help me remember one day, I thought I’d write it down.

I started playing with computers fairly early on. I’ve got two experiences that stick out in my mind as being formative for the young techie that I was back then. Sadly, I can’t remember which one came first though. So, I’ll just share both.

At some point in my early childhood, we got a Commodore 64. I had fun just playing games on it and such. Rich and I spent many (many, many) hours playing Willow Pattern Adventure But, I remember my Mom sitting down with a programming book, and making the dang thing play “When the Saints Go Marching In”. Now, it took a massive amount of coding to make it play a simple melody in BASIC, but something about seeing a machine do something you asked by typing in the right thing piqued my interest. I ended up finding the book that had the code in it, and started entering it myself. I had no idea what I was doing, but I think that’s where I started seeing what computers could do.

I think that happened around the same time as I started 5th grade, which is the other geek story I have. So, by that time Apple ][‘s were pretty ubiquitous in classrooms. Me and my old buddy GP (@zorbadgreek, about.me page) just started checking programming books out of the library and we’d use all our “activity time” typing the simple BASIC programs we found into it to see what would happen. We spent so much time on the computer that our teacher at the time (thank you Mrs. Chitwood) actually moved us to the back of the room so that we were the closest ones to the computer. That way, whenever we got done with our work and had some time, we could jump right on the computer and start to hack away. Who knew that almost 8 years later, GP and I would be rooming together and starting our Computer Science journey together at Georgia Tech?

There are a lot of events that have come along the path that have shaped my journey into this field, but those are the two earliest and foundational events.

So, what set you on your current path?

CSV to Dynamic Object List Tuesday, 05/29/2012

Posted by Percy in Programming, Technology.
1 comment so far

I’m working on importing some data from one system to another, and the output of the first program is a CSV. I want to clean up the data from the CSV and create some relationships out of the flat data. So, I was tossing around the idea of creating an object model, hydrating it by hand from the data, and then saving it to the database through some EF code first objects.

So, the first step would be to import the CSV data. I figured it would be easiest to try and import this data into a data table so that I can run queries on it to get at the data I was looking for. I came across this article in my search written by fellow Slalom-er Jim Wooley (@JimWooley). It goes a step further, but it got me thinking.

I’ve played around with dynamic objects some, and it occurred to me that a data row would be a great data backer for a dynamic object. Further, a data table could be then converted into a list of dynamic objects. Once that happens, using linq to query the objects would be easy.

So, first I wrote an extension method to convert a System.Data.DataTable to an IEnumerable. It requires the wrapping of the data row in an object that derives from System.Dynamic.DynamicObject. This is the first step:

public static class DataTableExtensions
{
    #region Inner Classes
    private class DataRowWrapper : DynamicObject
    {
        internal DataRow Data { get; set; }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            bool toReturn = false;
            result = null;

            if (this.Data != null
                && this.Data.Table.Columns.Contains(binder.Name))
            {
                result = this.Data[binder.Name];
                toReturn = true;
            }// if the parameter is set

            return toReturn;
        }// of bool TryGetMember(GetMemberBinder, out object)
    }// of class DataRowWrapper
    #endregion // Inner Classes

    public static IEnumerable<dynamic> ToDynamicCollection(this DataTable table)
    {
        List<DataRowWrapper> toReturn = new List<DataRowWrapper>();

        if (table != null)
        {
            foreach (DataRow row in table.Rows)
            {
                toReturn.Add(new DataRowWrapper() { Data = row });
            }// for each row
        }// if the table is set

        return toReturn;
    }// of IEnumerable<dynamic> ToDynamicCollection(this DataTable)
}// of class DataTableExtensions

Now, all I have to do is turn my CSV into a data table, and I’m moving right along. So, this is what I used to do that:

DataTable dataTable = new DataTable();

Microsoft.VisualBasic.FileIO.TextFieldParser parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(path);
parser.Delimiters = new string[] { "," };
int rowIdx = 0;
while (!parser.EndOfData)
{
    DataRow row = null;
    int colIdx = 0;
    parser.ReadFields().AsEnumerable<string>().ForEach(f =>
    {
        if (rowIdx == 0)
        {
            dataTable.Columns.Add(f.Replace(" ", "_").Replace("/", "_"));
        }// if this is the header row
        else
        {
            if (row == null) { row = dataTable.NewRow(); }
            row[dataTable.Columns[colIdx]] = f;
        }// if this is a data row
        colIdx++;
    });

    if (row != null) 
    { 
        dataTable.Rows.Add(row);
    }// if the row is set
    rowIdx++;
}// while we have line data

You can see that I’m also cleaning up the name of the column, because in my case some of the columns of the CSV contains spaces and slashes. There’s some other clean up I’ll probably need to do eventually.

So, now, I can read my CSV into a list, and the run queries on the objects. Like this:

string path = @"{Path to CSV}";
IEnumerable<dynamic> vals = DelimitedFileParser.ParseFile(path);
vals.OrderBy(v => v.Last_Name)
    .ForEach(v =>
    {
        Console.WriteLine(string.Format("{0} {1} ({2})", v.First_Name, v.Last_Name, v.Login_Name));
    });

So, now I can query the object, and hydrate my EF Code First objects based on the queries. I’m sure there are easier ways to parse data from a CSV file, but this way was a lot of fun. ūüôā

Fun with Powershell, Part 5 – Organizing pictures Saturday, 05/12/2012

Posted by Percy in Fun with Powershell, Technology.
2 comments

After the birth of my son recently, there were (as you can imagine) a lot of pictures taken. ¬†Luckily, my father-in-law loves to take pictures with his iPhone. ¬†So, in a week or so he’s taken almost 100 photos – which is awesome. ¬†Sarah and I have been so busy with just taking care of him, it’s been nice to have an extra pair of hands to take pictures. ¬†The issue has been on how to get the pictures from his iPhone or iPad (where he has his own iTunes account) onto our machines (where we have our own iTunes account). ¬†So, the syncing with iCloud just wasn’t going to work. ¬†I had his iPad, but most of the pictures were from his iPhone. ¬†So, the pictures weren’t physically on the iPad. ¬†I could have saved them from the photo stream, but I didn’t want to add any more files to his iPad than he already had. ¬†I tried a few ways of getting the files off (without paying for an app), and I finally settled on just e-mailing them to myself. ¬†Since gmail has a attachment limit, I could only send 15-20 pictures at a time. ¬†That resulted in almost 10 separate e-mails, which was fine. ¬†Gmail also has a feature that allows you to download all the attachments from an e-mail into a single zip file. ¬†So, now, I have about 10 zip files with 15-20 pictures a piece that I want to organize. ¬†Further, each file has a similar set of file names (image.jpeg, image_2.jpeg, image_3.jpeg, etc.).

Now, I have my own way of organizing my pictures. ¬†I have a folder of all my pictures with subfolders named “[Date in yyyy-mm-dd format] [Name of event]”. ¬†Then, each picture within the directory is named the same as the directory but with a number suffix – “[Date in yyyy-mm-dd format] [Name of event] ###.[Extension]”. ¬†You can see that here:

So, what I need is something that will do the following:

  1. Look through the list of zip files
  2. For each zip file, unzip the contents into a temporary folder
  3. For each image, find the date that the image was taken via the metadata
  4. If a directory of the format “[date] [name]” doesn’t exist, create it
  5. Copy the current image into the directory of the format “[date] [name] ###.[ext]” making sure to increment the ### correctly

I could do this all manually, but with ~10 zip files and ~100 images, that could take some time. ¬†What do I do, I start writing a PowerShell script! ¬†ūüôā

So, my first step is to throw all the zip files into a directory, and then just do a Get-ChildItem on them to iterate over each one individually.

Get-ChildItem {Path} -Filter *.zip |
% {
}

Ok, now I need to get a temp folder, and then unzip all of the contents of the current zip file into that temp folder. I found this article about how to unzip files using a powershell script. So, now, my script looks like this:

Get-ChildItem {Path} -Filter *.zip |
% {
	$tempFolder = Join-Path -Path $([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetRandomFileName()))
	if(!(Test-Path $tempFolder))
	{
		New-Item $tempFolder -Type Directory | Out-Null
	}
	
	$shellApp = New-Object -Com shell.application 
	$zipFile = $shellApp.namespace($_.FullName)
	$destination = $shellApp.namespace($tempFolder) 
	$destination.Copyhere($zipFile.items())
}

Ok, now I can loop through each file that I’ve unzipped. I just need some code that will pull the date taken from the image file itself. I found this article which links to this folder which contains a script called “ExifDateTime.ps1” that does what I need. So, adding that to my script, I now have this:

Get-ChildItem {Path} -Filter *.zip |
% {
	$tempFolder = Join-Path -Path $([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetRandomFileName()))
	if(!(Test-Path $tempFolder))
	{
		New-Item $tempFolder -Type Directory | Out-Null
	}
	
	$shellApp = New-Object -Com shell.application 
	$zipFile = $shellApp.namespace($_.FullName)
	$destination = $shellApp.namespace($tempFolder) 
	$destination.Copyhere($zipFile.items())

	Get-ChildItem $tempFolder | 
	% {
		$fileStream = New-Object System.IO.FileStream($_.FullName,
		                                            [System.IO.FileMode]::Open,
		                                            [System.IO.FileAccess]::Read,
		                                            [System.IO.FileShare]::Read,
		                                            1024,     # Buffer size
		                                            [System.IO.FileOptions]::SequentialScan
		                                           )
		$img = [System.Drawing.Imaging.Metafile]::FromStream($fileStream)
		$exifDT = $img.GetPropertyItem('36867') # Date taken
		$exifDtString = [System.Text.Encoding]::ASCII.GetString($ExifDT.Value)
		[datetime]::ParseExact($exifDtString,"yyyy:MM:dd HH:mm:ss`0",$Null)
}

Now, I throw in a little image manipulation via System.Drawing.Bitmap (rotate the image by 90 degrees, since most have been taking on a iPhone and they are vertical rather than horizontal), and then I copy the file to my custom output directory (creating the directory if it doesn’t exist). Finally, I delete the temporary folder. All in all, around 70 lines for doing some pretty hefty file organization is not a bad deal. Here’s the final output:

$root = [Root Directory]
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
Get-ChildItem $root -Filter *.zip |
% {
	$tempFolder = Join-Path -Path $([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetRandomFileName()))
	if(!(Test-Path $tempFolder))
	{
		Write-Host "Creating $tempPath"
		New-Item $tempFolder -Type Directory | Out-Null
	}
	
	Write-Host "Unzipping $($_.FullName) to $tempFolder"
	$shellApp = New-Object -Com shell.application 
	$zipFile = $shellApp.namespace($_.FullName)
	$destination = $shellApp.namespace($tempFolder) 
	$destination.Copyhere($zipFile.items())
	
	Get-ChildItem $tempFolder | 
	% {
		Write-Host "Getting date taken for $($_.FullName)"
		$fileStream = New-Object System.IO.FileStream($_.FullName,
		                                            [System.IO.FileMode]::Open,
		                                            [System.IO.FileAccess]::Read,
		                                            [System.IO.FileShare]::Read,
		                                            1024,     # Buffer size
		                                            [System.IO.FileOptions]::SequentialScan
		                                           )
		$img = [System.Drawing.Imaging.Metafile]::FromStream($fileStream)
		try
		{
			$exifDT = $img.GetPropertyItem('36867') # Date taken
			$exifDtString = [System.Text.Encoding]::ASCII.GetString($exifDT.Value)
			$dateTaken = [datetime]::ParseExact($exifDtString,"yyyy:MM:dd HH:mm:ss`0",$Null)
		}
		catch {}
		Write-Host "Date taken - $dateTaken"
		$prefix = [string]::Format("{0:yyyy-MM-dd} [Custom Format]", $dateTaken)
		$destinationPath = "$($root)\Output\$prefix"
		
		if(!(Test-Path $destinationPath))
		{
			Write-Host "Creating $destinationPath"
			New-Item $destinationPath -Type Directory | Out-Null
		}
		
		$fileWritten = $false
		$index = 1
		while(!$fileWritten)
		{
			$destinationFile = [string]::Format("{0}\{1} {2:000}{3}", $destinationPath, $prefix, $index, $_.Extension)
			if(!(Test-Path $destinationFile))
			{
				Write-Host "Copying to $destinationFile"
				$i = New-Object System.Drawing.Bitmap($_.FullName)
				$i.RotateFlip([System.Drawing.RotateFlipType]::Rotate90FlipNone)
				$i.Save($destinationFile)
				
				$fileWritten = $true
			}
			$index++
		}
		
		$fileStream.Close()
	}
	
	"Removing $tempFolder"
	Remove-Item $tempFolder -Force -Recurse
}

Enjoy!

Fun with Powershell, Part 4 – Enumerations as function parameters Friday, 05/11/2012

Posted by Percy in Fun with Powershell, Technology.
add a comment

So, a lot of you guys who are already using Powershell a decent amount might already know this, but it came as a surprise to me. One of those “wow, I can’t believe it actually works in this awesome way” surprises, but still I had no idea.

So, I was defining a custom function where one of the parameters was going to be an enumeration from a compiled object – in this case I was adding columns (fields) to a Sharepoint list in code, and my function parameter was the type, which is of type Microsoft.SharePoint.SPFieldType. When I then called the method, I thought I had to use the appropriate syntax to send in the appropriate value (-ParamName [Microsoft.SharePoint.SPFieldType]::Integer). However, when I ran my code, I got an error about that property not being of the right type. So, I deleted the setting, and started typing. What do you know, I got intellisense for the indivdual types. Apparently, Powershell is smart enough to interpret the parameter as an enum, and only make you choose the specific type. My parameter call then became -ParamName Integer.

Like I said, that may not be news for anyone else, but it rocked my world a bit.

Fun with Powershell, Part 3 – Searching a codebase Wednesday, 03/28/2012

Posted by Percy in Fun with Powershell, Programming, Technology.
add a comment

One of the neat things about having Powershell in your toolkit is that it becomes an option when you need to solve a problem. This is a fairly simple code example, but I think it’s one that a lot of developers could use.

So, here’s the problem – we’ve got a fairly massive codebase. Some of it is “core” and some of it is client-specific. The “core” (we call product) is fairly complicated and has about a dozen “packages”, which each contain anywhere from about 5 to 30 assemblies/projects. So, when we’re trying to trace a code problem through it’s different levels, we may be opening a handful of solutions. That either requires multiple instances of Visual Studio to be open at the same time, or to only have one but loosing track of where you are in the stack.

Most of the time, you just want to figure out where a certain method is defined or where a certain class is used and pouring through the different code files/projects/solutions can become tedious. Too, it can be hard to locate a class given it’s name and namespace. For example, we have a “Components” package, but the class CIS.Components.Maintenance is actually in the “Services” package – for various reasons.

So, what can you do to find what you’re looking for easily? If you have all of the code downloaded on your machine, it’s as simple as a string search in a list of files – some people know it as “grep”. Powershell has a cmdlet that functions just like grep – Search-String. Combine that with a “Get-ChildItems -Recursive” command, and you can find anything in any file. Now, if I sprinkle in a little grouping and selecting so that we just get back a list of files containing the search string I get this:

Get-ChildItem {Code Root Directory} -Recursive -Include *.cs | Select-String "{Method or Class Name}" | Group-Object Path | Select-Object Name

Voilà! I can quickly find where things are located, then just peek in that file rather than pouring through projects and solutions.

Enjoy!

Fun with Powershell, Part 2 – Investigating code Issues Tuesday, 02/21/2012

Posted by Percy in Fun with Powershell, Programming, Technology.
Tags: , ,
add a comment

Since I missed posting something last week, I’m putting out two this week to keep up with my resolution. ¬†This is the second post in a series of posts about the fun I’m having with Powershell.

Part of me putting this series of posts out there is to help people look at Powershell in a different light – as a developer tool. I think it gets labeled as a SysAdmin tool, which it definitely is. However, I’m finding more and more that when I turn to Powershell to help me, I end up getting the info I need quicker and easier and I write less code. This is another one of those issues.

So, I picked up an unfinished project for a client recently. The project is in the process of being QAed, but there were issues that had been found along the way. The original developer had since left the company, so it was up to me to figure it all out. One of these issues had to do with the rendering of a DataDynamics Active Report. The error that was being thrown had to do with displaying a logo. Basically, it was instantiating a Bitmap object using a stream from an embedded resource, but the stream was returning as null.

new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("{SupposedlyValidReference}")); 

So, I started thinking about how I could look into what was causing this issue. I could set up the web application where this issue was being thrown and go straight to debugging. However, in this case, that was a bit more complicated than it sounded. Also, the issue was in a compiled assembly that wasn’t specifically part of the website. I could write a harness to call this report and debug that way. I actually already have something like this written and shared with some co-workers, but even that was a bit more complicated then I wanted. Too, I didn’t need to test the entire report, just this one line. I could write a console app, and pull this code out to see what’s going on. Yea, I could do that somewhat quickly, but not as quickly as I could write some Powershell scripts to see what’s going on. So, that’s what I did.

Here’s the script I whipped up somewhat quickly:

cls 
$assemblyPath = "{PathToAssembly}" 
$assembly = [System.Reflection.Assembly]::LoadFile($assemblyPath) 
$stream = $assembly.GetManifestResourceStream("{ValidPath}") 
$stream | Get-Member 

Since that was basically the part of the code that was throwing the error. Running that script threw the following error: “Get-Member : No object has been specified to the get-member cmdlet.” That tells me the same thing the error message from the app tells me – my stream object is null. So, I started looking at the path to the resource, and the actual file name. It turns out the file was named ####_Logo.gif, while the resource referenced ####_logo.gif. So, just to see if that was the issue, I changed my script to have the capital L in the resource path. Running that script gave me a valid System.IO.UnmanagedMemoryStream object for $stream.

That’s it. It was just a letter casing issue. However, instead of firing up a new instance of Visual Studio, creating a new console app, adding a reference to this assembly, writing the code and stepping through it, all I had to do was write a simple 5 line script. Really, it could have been 2 lines (Load the assembly, and get the stream).

If you missed out on Part 1,  here it is.

Thoughts on Windows 8 Monday, 01/30/2012

Posted by Percy in Technology.
Tags: ,
1 comment so far

I’ve been using Windows 8 on my three year old “tablet” PC (i.e. laptop with touchscreen that spins around) off and on for the past few weeks or so. So far, I’ve been pretty impressed with it – to the point that I’m seriously considering going Windows Phone when it comes time to replace my trusty iPhone 4. Too, if the new tablets are priced right and not as heavy as the prototypes I saw at Tech-Ed, one might be coming home at some point.

With Windows 8 (non-server since I haven’t tried the server version), I think there are some strengths and weaknesses which I’ll throw out.

Strengths
Backward compatibility with Windows 7 – apps still run

While I haven’t found any metro apps to install (the app store isn’t available for the dev preview), I have been able to install some of my favorite apps without issue – Evernote, Dropbox, Chrome, Firefox, etc. ¬†And, so far as I can tell, they all run like they should. ¬†You don’t get the full-screen Metro UI or a neat tile to go along with them, but they open in the “Desktop” section of the UI and run just fine. ¬†I haven’t installed a ton of apps since I’m limiting myself to a 60 GB VHD, but except for a few specific instances I’m planning on using it for my main OS on my laptop – at least until the preview expires.

Metro UI makes sense

From the first time I saw the new UI running on my machine, it was usable. ¬†There were a few little quirks I had to figure out, but for the most part, it made sense. ¬†Having a touch screen really helped, though. ¬†The first time it booted up, I just swiped through the apps with my finger, and moved a few icons around. ¬†I even found the menu at the right by myself, just by swiping at the edge of the screen. ¬†I can’t seem to get the multi-touch working on my machine right now, so I can’t do all the neat tricks. ¬†All in all, though, once you see it, you know how it works.

Tiles are really cool

I really am enjoying the “tile” interface, especially those that are larger and can report back info. ¬†I can see the reason for them very quickly, and I now get all the Windows Phone commercials about getting the info quick and getting out. ¬†Currently, if I want to check the weather, I have to pull out my phone, unlock it, go into the Weather group, open up my weather app (The Weather Channel), and let the app load to pull up data. ¬†I can see that if I had a Windows Phone with the weather tile expanded and set up correctly, all I would need to do is pull out the phone and unlock it. ¬†The information would be displayed for me very quickly. ¬†Theoretically, to get all the info I want from my device, I can see just unlocking it and scrolling through the tiles. ¬†If the apps are set up appropriately, I shouldn’t have to open any of them.

Waking from sleep is FAST

So, I’m running this on a laptop that’s three years old. ¬†It’s a dual core with 4Gb of RAM, so it’s not the top of the line, but it’s not completely ancient either. ¬†Waking from sleep on Windows 7 takes a good amount of time. ¬†It takes enough time that I really only use it when I’m done with using the computer for a while. ¬†I used my tablet at a local conference recently and I had forgotten to set the power settings like I prefer. ¬†So, a few minutes into a session, it went to sleep. ¬†I didn’t notice until I had something I wanted to put in a note in Evernote. ¬†My first thought was “Dang it, now I’ve got to wait for this to boot up and I’m going to miss the next few of this session. ¬†Maybe I should just load it up on my phone and take notes from there.” ¬†Then, I remembered seeing videos of people starting from a cold boot in less than a few seconds, so I gave it a shot. ¬†In a few seconds, I was at the welcome screen, and after putting in my PIN (more on that later) I was back taking notes. ¬†The whole experience reminded me of unlocking my phone (or, as an extension, an iPad) and was just as fast. ¬†Needless to say, I wasn’t worried about letting it go to sleep after that. ¬†In fact, I’ve changed my normal power setting to allow it to sleep much more quickly than I do in my Windows & instance. ¬†It really does give you the tablet feel in this respect.

PIN login

So, there are three “passwords” you can set up in Windows 8. ¬†The first is your usual alphanumeric pass phrase. ¬†The second is a picture “password” where you’re shown a picture, and you perform a pre-defined set of gestures to login (similar to the android “connect the dots” unlock screen). ¬†The third is using a PIN, much like on the iPhone or iPad. ¬†I have to admit, when my machine woke up from sleep and I was using it as a tablet (screen turned around so the keyboard was behind it), I thought it was going to be a pain to type in my password. ¬†However, I was asked for the PIN I set up, and just like on my phone I was able to quickly enter it and get on with what I was doing. ¬†I realize it’s probably the least secure of the three options, and I’ll probably set up the picture password soon, but it was really FAST.

Sync with Live account

I’ve only got one machine running this OS right now, but I can see this being a cool feature. ¬†I’m not sure what will be synced, but it did pull down my avatar which was a nice touch. ¬†I assume this will integrate with Office365 or Live Mesh in some way.

Touch is a first class citizen, but works well with mouse/keyboard input

When you first see the Metro desktop, you want to reach out and touch it. ¬†It just makes sense. ¬†Like I’ve said, I’ve had a touch enabled laptop for about three years now. ¬†With Windows 8 (and Vista before it), I might have used the touch features, but only on rare occasions or when I wanted to take notes using the stylus. ¬†With Windows 8, I end up using some of the touch features even when I’m using a more traditional mouse/keyboard application like Visual Studio. ¬†So, just by the nature of the UI, I’m using touch more, which is a neat experience. ¬†I’ve also found, though, that the “Desktop” portion of the UI is “traditional input friendly” (i.e. lends itself well to normal mouse/keyboard input). ¬†I didn’t feel that I was missing anything using the mouse and keyboard in this view.

Native ISO mounting

There’s no need for third party tools now to mount (or at least open) ISOs now.

Weaknesses:
AutoCorrect is missing

This is more of an issue with using the tablet PC features. ¬†When I was taking notes at the conference, I really missed having autocorrect. ¬†I would type a bunch of notes in a hurry, only to look back and have to correct a bunch of misspellings – most of which had to do with international characters (which I’ll go into more below).

Onscreen keyboard has some quirks – picks international characters

This may be just a setting I’ve gotten wrong, but there were some quirks when I was using the onscreen keyboard. ¬†Every so often, I’d get an international character thrown in. ¬†I’ve not spent a lot of time on this, but I’ve never see it anywhere else.

New apps automatically get a tile

This may be a setting somewhere, but it annoys me that every app I install gets a tile. ¬†I think when I originally thought of the “tile area”, I compared it to the desktop. ¬†For me, I have very few icons on my desktop. ¬†I think the “tile area” is more of the start menu, just flattened out. ¬†It would be nice, though, to have the ability to select which apps get icons and which don’t.

Indeterminite:
Metro UI’s useablility for business users

I’m still trying to understand if Metro really has a place in the business world. ¬†Now, with Win8, you can get to a desktop and run all your normal apps. ¬†So, just as much as Win7 has business use I think Win8 can. ¬†But, that’s completely bypassing the Metro UI.

We’ll see how things go as Windows 8 gets closer to release.

Fun with Powershell, Part 1 – Intro/Twitter API Monday, 01/09/2012

Posted by Percy in Fun with Powershell, Programming, Technology.
Tags: , , ,
1 comment so far

I’ve really been enjoying learning more about Powershell. ¬†I’ve actually gotten to the point that I think about using it first, and then writing a full-fledged application second. ¬†In the past, I’ve listed some of the things I’ve been able to do with Powershell, but I thought I might dig a little deeper and provide some more detailed info about the what and how of those kind of things. ¬†Too, whenever I talk to developers or technology folks about Powershell, they all have the same reaction – “Isn’t that more for system administrators than for developers?”. ¬†While I fervently agree that anyone administering any kind of system needs to know Powershell for their own sanity, it’s a great tool for developers as well. ¬†So, I thought I would highlight how developers can use Powershell by throwing out some real world examples of how I’ve used it. ¬†Also, I’m assuming that you know the basics of Powershell – declaring variables ($), calling methods on objects, piping input into commands, creating new objects, etc. ¬†If you need more clarification, please let me know.

I don’t know how long this series will be, but here we go with part 1.

I was reading through my twitter feed the other day, and I came across this post from The Oatmeal:

“Is there a way to sort my Twitter followers by the number of followers they have? (in descending order)”

My first thought was “I’m sure I can do that in Powershell”. ¬†Now, there are a number of web apps out there that will actually do this for you. ¬†I even think the next tweet points to¬†friendorfollow.com. ¬†However, I thought it would be a neat learning exercise. ¬†Before we begin, I figured I’d throw this out there – I honestly have no idea how this will work. ¬†I don’t have some stock twitter API in my back pocket ready to use. ¬†So, this will be “from scratch”. ¬†So, here’s how I did it.

First off, I’m assuming that there is a twitter API, so I go to twitter’s website, and I click the link at the bottom labeled “Developers” (hey, that’s me!). ¬†That takes me to dev.twitter.com, which has a link for Getting Started with the API. ¬†Bingo! ¬†After looking around there, I find that it’s just HTTP requests of the format “https://api.twitter.com/{Version}/{Controller}/{Action].{Format}?{Parameters}”. ¬†So, in this case, the first thing to do is get the followers for a particular user. ¬†So, the URL I’m going to use is¬†https://api.twitter.com/1/friends/ids.xml?screen_name={your user name}, since I want to use the XML format. ¬†That returns the list of all my followers. ¬†So, now I need to get this into Powershell by firing up my trusted Posh IDE – PowerGUI.

With Powershell, you have access to any .NET library, including the ones in the core. ¬†There’s a class called System.Net.WebClient that I think I can use. ¬†Let me see what options I have:

New-Object System.Net.WebClient | Get-Member 

There’s a method called DownloadString, that takes in a string address as a parameter. ¬†So, lets give this a try and see what happens:

$url = "https://api.twitter.com/1/friends/ids.xml?screen_name={your user name}" 
$wc = New-Object System.Net.WebClient 
$wc.DownloadString($url) 

That returns the XML response that I’m looking for. ¬†So, now I need to put that string into an xml object, and see what options I have.

[xml] $data = $wc.DownloadString($url)
$data | Get-Member 

Now, one of the properties is called “id_list”. ¬†If I look at the XML returned from the URL I passed in, that’s the root node. ¬† So, by putting it in the XML object, Powershell has effectively serialized my XML into an object tree. ¬†So, now I should be able to get each individual id.

$data.id_list.ids.id | 
% { 
	$_ 
} 

From that I can see the list of id’s. Alright, now I can loop through each one of my followers. So, the next step is getting the number of followers for each of those users. Luckily, there is another API call that can give us that information. ¬†So, now, for each one of these users I want to call a URL of the following format –¬†https://api.twitter.com/1/users/lookup.xml?user_id={User ID}&include_entities=true.

Note: The twitter API only allows 150 calls an hour per IP address. ¬†I found this one out the hard way. ¬†So, while you CAN¬†loop through all your friends, I wouldn’t recommend it if you have more than 150 people your are following.

So, now I can do something like this within the loop:

$userUrl = "https://api.twitter.com/1/users/lookup.xml?user_id=$($_)&include_entities=true"
[xml] $userData = $wc.DownloadString($userUrl)

A little more testing tells me that the user name of the current follower can be found at $userData.users.user.screen_name and the follower count can be found at $userData.users.user.followers_count. Now, I want to see this data as a simple data set so I can sort the data. There’s a neat little trick I picked up while reading this article. You can dynamically declare an object structure by using a command similar to this:

$newObj = "" | Select-Object Property1, Property2, Property3

If you then do something like this:

$newObj | Get-Member

You’ll see “NoteProperty” types that correspond to the properties you declared earlier. Too, instead of doing multiple set operations on separate lines, you can do multiple set operations on one line – as long as you get the order correct. So, once I get the data for the user, I can do something like this:

$outputItem = "" | Select-Object Name, ScreenName, FollowersCount
$outputItem.Name, $outputItem.ScreenName, $outputItem.FollowersCount = $userData.users.user.name, $userData.users.user.screen_name, [int] $userData.users.user.followers_count

Now, if I just put $outputItem on a line all by itself, it’ll be returned as a result of this iteration of the loop. So, now my loop returns a data set which contains all the data I want to see. Just to make it a bit nicer, I can pipe it out to Out-GridView. That allows me to see the data and play with it all I want. So, if I put it all together, I’ve got a script that hits the Twitter API and will return a grid view of all of the people that you are following and their follower count in a little over 10 lines of code (and some of that simply for formatting):

$url = "https://api.twitter.com/1/friends/ids.xml?screen_name={your twitter name}"
$wc = New-Object System.Net.WebClient
[xml] $data = $wc.DownloadString($url)
$data.id_list.ids.id |
% {
    $userUrl = "https://api.twitter.com/1/users/lookup.xml?user_id=$($_)&amp;include_entities=true"
    [xml] $userData = $wc.DownloadString($userUrl)
    $outputItem = "" | Select-Object Name, ScreenName, FollowersCount
    $outputItem.Name, $outputItem.ScreenName, $outputItem.FollowersCount = $userData.users.user.name, $userData.users.user.screen_name, [int] $userData.users.user.followers_count
    $outputItem    
} | Out-GridView

So, there is is. In the interest of full disclosure, here is my script, with the user limiter code included as well as some commented code I was using for testing purposes:

cls
# New-Object System.Net.WebClient | Get-Member
$url = "https://api.twitter.com/1/friends/ids.xml?screen_name=katman26"
$wc = New-Object System.Net.WebClient
[xml] $data = $wc.DownloadString($url)
$count = 0
$data.id_list.ids.id | 
% {
    if($count -lt 5)
    {
        $userUrl = "https://api.twitter.com/1/users/lookup.xml?user_id=$($_)&include_entities=true"
        [xml] $userData = $wc.DownloadString($userUrl)
        
        $outputItem = "" | Select-Object Name, ScreenName, FollowersCount
        $outputItem.Name, $outputItem.ScreenName, $outputItem.FollowersCount = $userData.users.user.name, $userData.users.user.screen_name, [int] $userData.users.user.followers_count
        $outputItem
    }
    $count++
} | Out-GridView

Let me know if you have any questions about this or any of the examples I’ve shown. I’m not a Powershell expert…yet. ūüôā

%d bloggers like this: