I'm not sure if I'll be able to keep it up, but I'm going to see if I can make Monday "Little Programs" day, where I solve simple problems with little programs.

Today's little program is a script that goes through your Pictures folder and picks out your top-rated photos.

The key step here is extracting the rating, which goes by the name System.Rating in the shell property system. The method which does the extraction is Shell­Folder­Item.Extended­Property.

var shell = new ActiveXObject("Shell.Application");
var picturesFolder = shell.Namespace(39); // CSIDL_MYPICTURES
var items = picturesFolder.Items();
var SHCONTF_NONFOLDERS = 64;
items.Filter(SHCONTF_NONFOLDERS, "*.jpg");
for (var i = 0; i < items.Count; i++) {
  var item = items.Item(i);
  if (item.ExtendedProperty("System.Rating") >= 80) {
    WScript.StdOut.WriteLine(item.Path);
  }
}

Wow, that was way easier than doing it in C++!

That program searches one folder, but let's say we want to do a full recursive search. No problem. Take the code we wrote and shove it into a helper function process­Files­In­Folder, then call it as part of a recursive directory search.

function processFilesInFolder(folder) {
  var items = folder.Items();
  var SHCONTF_NONFOLDERS = 64;
  items.Filter(SHCONTF_NONFOLDERS, "*.jpg");
  for (var i = 0; i < items.Count; i++) {
    var item = items.Item(i);
    if (item.ExtendedProperty("System.Rating") >= 80) {
      WScript.StdOut.WriteLine(item.Path);
    }
  }
}

function recursiveProcessFolder(folder) {
  processFilesInFolder(folder);
  var items = folder.Items();
  var SHCONTF_FOLDERS = 32;
  items.Filter(SHCONTF_FOLDERS, "*");
  for (var i = 0; i < items.Count; i++) {
    recursiveProcessFolder(items.Item(i).GetFolder);
  }
}

var shell = new ActiveXObject("Shell.Application");
var picturesFolder = shell.Namespace(39);
recursiveProcessFolder(picturesFolder);

You can use this as a jumping-off point for whatever you want to do with your top-rated pictures, like copy them to your digital photo frame.