PowerShell Function to Fix System Path

Before Windows 7, max length of the PATH environment variable was 1024 chars. Many years ago, we found ourselves troubleshooting a huge problem in our environment that was caused by faulty install scripts that were appending the PATH variable many times taking the path length over the limit and causing all sorts of problems as PATH was cut at 1024.

Windows 7 increased the length but I've seen the same problem in other environments. I have seen a PowerShell question over at StackOverflow today, and apparently the person was running into the problem because the max path length was exceeded. When that happens, Windows just ignores the characters after the max length is reached.

I had written a PowerShell function that would search for and remove the duplicates that would increase the length of PATH unnecessarily. I put it up as a gist at github & sharing it here. Hopefully it helps someone.


ConvertFrom-String or Not

One of the new cmdlets in PowerShell v5 is ConvertFrom-String. It's using a Microsoft Research Technology called "FlashExtract", a machine learning technology. I was hoping that it would finally rescue us from RegEx! ~/Yay/Heh/g

I've seen several MVPs write about it, mostly before Microsoft released the final version but some recent as well:
The premise is that, you provide samples of the data and specify what you want to extract out of it, and FlashExtract engine is supposed to be smart enough to evaluate the template you provided and get the properties you want. If only life was that simple...

Alright here is our victim... Let's take a look at our WinSxS (component) folder. People always complain about how big it is and how unwieldy it gets over time as more and more patches come down. It's a tempting target to clean up old patches and other binaries but also the shortest path to breaking your Windows if you remove a needed file.

Anyway, I am more interested in creating an easy to read PowerShell object based database out of it.

They look like this:

Microsoft tells us how it is formatted - What's that awful directory name under Windows\WinSxS. Oh, it's supposed to be a 'friendly-name' with this format:


So, the name is separated by a bunch of underscore characters. This makes our life so easy to parse it, right? Wrong! "name" too can have "_", as well as a bunch of other chars like "." and "-".

Still, after two minutes of RegEx tinkering I got that function and it worked perfectly:

PS C:\Users\Adil> (Get-WinSxSRegex)[1,100,1000]

Processor      : amd64
Name           : 1394.inf
PublicKeyToken : 31bf3856ad364e35
Version        : 10.0.10586.0
Language       : none
Hash           : 87b4eef7b03f2543

Processor      : amd64
Name           : c_bluetooth.inf.resources
PublicKeyToken : 31bf3856ad364e35
Version        : 10.0.10586.0
Language       : en-us
Hash           : 14d0dc285c89e9ba

Processor      : amd64
Name           : microsoft-windows-b..iagnostic.resources
PublicKeyToken : 31bf3856ad364e35
Version        : 10.0.10586.0
Language       : hu-hu
Hash           : 2d6242e40cbc20a9

The example above is showing the 1st, 100th and 1000th records. Luckily, they are good examples to demonstrate the challenge that ConvertFrom-String cmdlet faces.

So, I took a couple of folder names and started to put the property names as I would like them.

This is supposed to collect the Processor, but if I do not use "*",  it does not work. It seems that when the first matching line is found, that becomes a record, and to be able to get more records, we need that * in there.

This will work, but only for some. See, because it starts with a number, without any other sample for Name, engine thinks we want something that starts with 'numbers', and gives us only matching folder names that has numbers in the 'name' section. so, we need to give different Name samples.

To a human eye, this is pretty easy to locate. It's a hex, and if we were using regex, we would use something like '[a-fA-F0-9]+', in other words one more numbers or characters that stops are between 'a' and 'f'. Well, we are not dealing with a human here.

OK, this must be the easiest to identify however you look at it. 4 digits with "." between them

Language is a bit tricky. It could be none or some international language designation like "en-us" for US English.

Finally, we have the hash, which is pretty much like the PublicKeyToken

I will leave it here. I tried a couple of alternatives in templates, and providing more was not getting me anywhere as I kept on getting error messages telling me ConvertFrom-String cmdlet could not come up with a way to extract data using my template and suggested I email Microsoft. I did, though I am not holding my breath on that.

I really like the concept of ConvertFrom-String, and in my opinion, It would be one of the most powerful features of PowerShell but to me, it feels like it is just not there YET.

Sample templates I used are below. If you will use the functions, pipe them to |out-gridview. It is pretty easy to detect problems that way.


Clear Recent Documents List on OS X

Remove the relevant .sfl file located under the following directory:
~/Library/Application Support/

- * -

It's Halloween! Time for scary stuff. As the tech admin of the house, my job tonight was to make sure a series of old scary movie classics, think of Poltergeist , can be streamed to TV.

I decided to clear the existing list of QuickTime Player's Recently Opened Files and pre-populate the list with the scary movies. This can be done from GUI:

QuickTime Player > File > Open Recent > Clear Menu

Nothing is wrong with that, but I wondered how I would do that from Command Line. Interestingly, I could not locate a setting in a .plist. If you Google, you will find suggestions similar to below, but on El Capitan (10.11), these settings did not exist

adil-imac-1:~ adil$ defaults read RecentDocuments
2015-10-31 23:35:21.932 defaults[12222:1913397] 

The domain/default pair of (/Users/adil/Library/Preferences/, RecentDocuments) does not exist

So, to find which file I needed to look at, I decided to use good old, 'find' command. The technique is well known:
  • First create a temporary file
  • Then take action (launch a movie) to cause a file change, as new movie is added to the recent items
  • Lastly do a find for all files newer than the temporary file we created

touch /private/var/tmp/now
sudo find / -newer /private/var/tmp/now

This, usually works, but file list could be larger. In my test, it returned 120 files in that short time frame.

There are other issues with this approach:
  • It's relatively slow!
  • If you have external drives mounted, you might need to try -x to avoid scanning them

There is a better way! Try Spotlight from command line: mdfind.  

Approach is pretty similar to find, except there is no need to create a temporary file. 
  • Make the change
  • Immediately run mdfind telling it to look for changes in the last, say 15secs.

mdfind 'kMDItemFSContentChangeDate>$'

k: kind
MD: Metadata
FS: File System
$Time variable is explained in the Apple Developer Documentation link below

Apple Developer documentation on MetaData Query Expression Syntax has some examples on using MetaData information. There are a few examples here as well.  

mdfind command pointed to this file:

~/Library/Application Support/

What's .sfl? Not exactly sure but it probably stands for 'Shared File List' and apparently is meant to hold "Bookmark Data".

The content of the .sfl file is kinda cryptic. Incidentally, I found a blog post from a couple of days ago that goes about Exposing "BookmarkData"

When you manually clear the Recent Documents, the .sfl file becomes shorter in size. However, as there does not seem to be a tool to manipulate the file yet, deleting the file seems like a safe way to clear bookmarks.

Just in case people are wondering, yes, VLC has 'org.videolan.vlc.sfl' located at the same folder, and removing that file cleared the VLC recent docs as well.