Find subfolders that lack a given file(name)

Our processing automation at work creates a number of files during processing. One way we can tell when the automation hasn’t completed successfully is when the processed files directory has been created, but the files that are created at the end of processing are missing from the directory.

Here’s a PowerShell script fragment to identify subfolders (two levels down) that lack a given file (target.txt in this example) :

PS > Get-ChildItem |
>>   ForEach-Object {
>>     Set-Location $_
>>     Get-ChildItem |
>>       Where-Object {!(Test-Path $_\target.txt)}
>>     Set-Location ..
>> }
>>

And here’s a one-liner version of the above:

PS > ls | %{ cd $_ ; ls | ?{!(test-path $_\target.txt)} ; cd ..}

It’s not perfect – if it encounters a file (rather than a subdirectory) one level down, it attempts to Set-Location to that filename and throws an error (because you can’t Set-Location to a file, only a folder). However, it seems to find all the folders missing the target.txt file before it attempts to Set-Location to that file.

PowerShell – Get-WmiObject vs. Get-CimInstance

A recent post on the Hey, Scripting Guy! blog showed how to use PowerShell to find a network adapter’s MAC address. The post provided two ways to get the information using WMI:

Get-WmiObject win32_networkadapterconfiguration | select description, macaddress

Get-CimInstance win32_networkadapterconfiguration | select description, macaddress

I wondered about the difference between GetWmiObject versus Get-CimInstance. Happily, while exploring older Hey, Scripting Guy! posts, I found one about simplifying PowerShell scripts that addressed the difference(s):

One of the first changes I make to a script, if I can, is I change Get-WmiObject to Get-CimInstance. Since Windows PowerShell 3.0, I can use Get-CimInstance. It is faster and more robust, and it permits lots of cool things for retrieving data (such as using Cim-Sessions).

Since most of our servers here are running PowerShell 2.0 right now, it will be a while before I can routinely use Get-CimInstance instead of Get-WmiObject — but it’s something for me to keep in mind for the future.

Scriptify – A navigation aid for SharePoint 2013 PowerShell Cmdlets

Via yesterday’s Hey, Scripting Guy! blog –

Scriptify – A navigation aid for SharePoint 2013 PowerShell Cmdlets is a web-based reference for PowerShell cmdlets related to SharePoint 2013. The cmdlets are divided into 36 categories – clicking on a category’s button takes you to a page of buttons to access the invidual cmdlets in that category. Clicking on a cmdlet’s button takes you to a page with parameters for the cmdlet and a link to its Technet homepage.

Accessing the Outlook Inbox – ‘NoCOMClassIdentified’ error

We get a lot of email where I work. A metric butt-ton.

One of the things I’d like to be able to do is access that email programmatically, in order to extract production processing reports for further analysis.

As a first step, I went looking for a way to access the Inbox using PowerShell. I found a post on Microsoft’s Hey, Scripting Guy blog: Use PowerShell to Data Mine Your Outlook Inbox.

There was just one problem – when I tried the steps to access the Inbox, I got a major error:

PS C:\Windows\system32> add-type -assembly “Microsoft.Office.Interop.Outlook”
PS C:\Windows\system32> $olFolders = “Microsoft.Office.Interop.Outlook.olDefaultFolders” -as [type]
PS C:\Windows\system32> $outlook = new-object -comobject outlook.application
new-object : Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)). At line:1 char:12 + $outlook = new-object -comobject outlook.application + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand

I searched for “NoCOMClassIdentified” and found a couple of references. I finally found one (I don’t have the link, alas) that helped me realize the problem was that I was running it from a PowerShell session that I’d opened as Administrator (for teh POWER!!!).

When I opened PowerShell as myself, I was able to complete the sequence to access the 60,000+ messages in my Inbox (did I mention we get a LOT of email here?), and use a quick pipe to Where-Object to extract just the emails I sent to myself:

PS P:\> Add-Type -Assembly “Microsoft.Office.Interop.Outlook”
PS P:\> $olfolders = “Microsoft.Office.Interop.Outlook.olDefaultFolders” -as [type]
PS P:\> $outlook = new-object -comobject outlook.application
PS P:\> $namespace = $outlook.GetNameSpace(“MAPI”)
PS P:\> $folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
PS P:\> $folder.items | Select-Object -Property Subject, ReceivedTime, Importance, SenderName |
>>  Where-Object {$_.SenderName -like “Spurlock*”}Subject ReceivedTime Importance SenderName
——- ———— ———- ———-
How to send an email from … 10/23/2014 7:01:29 PM 1 Spurlock, Edward (Austin)
RE: How to send an email f… 10/23/2014 7:06:15 PM 1 Spurlock, Edward (Austin)
PowerShell script to updat… 10/28/2014 6:17:21 PM 1 Spurlock, Edward (Austin)
RE: PowerShell script to u… 10/28/2014 6:25:15 PM 1 Spurlock, Edward (Austin)

Accessing email through Outlook works, but according to Bill Long’s Exchange Blog, using the Exchange Web Services (EWS) Managed API for PowerShell scripting offers a number of advantages. For one, you can access Exchange data from a system that does not have Outlook installed. Another advantage is being able to do “ranged retrievals” – accessing a subset of the data on each retrieval, rather than having to pull everything down at once and sort it out (as I did with Where-Object).

Happy Birthday, Windows!

Microsoft Interface Manager – excuse me, Windows 1.0 – was introduced to the world on November 10, 1983.

Version 1.0 wasn’t actually released to users until 1985, but Bill Gates showed the first version two years earlier at the Plaza Hotel in New York City.

In 1983, I was still trying to be the next great bicycle racer. By late 1985, I’d quit bicycle racing and started to ask myself what I would do next. I decided on electronic music (I should have gone back to college then, instead of waiting a couple of years) and bought my first keyboard (an inexpensive consumer-grade Casio) that year. I bought an Akai AX-80 analog hybrid synth and an Atari ST 520 in 1986, and started getting involved in the local Atari user group.

I bought a Zenith all-in-one PC that ran MS-DOS from floppies in 1988 (1987? 1989?), but I did a lot more with the Atari. My earliest memory of Windows was the announcement of Windows 3.0 in 1990, which happened at the same time as a tech show in Austin where our Atari user group set up a multiplayer MIDI Maze game. (MIDI Maze was an early “first-person shooter” (FPS) game that used the built-in MIDI ports on the Atari ST to network multiple machines)

I didn’t actually work on Windows machines until I started work at Dell in 1995. I started training in tech support the week before Windows 95 was released on August 24, 1995 – but I and the other first-level techs in my class didn’t get to use Win95 until 1996. My first Windows was Windows 3.1.

Doctor Who fans have a saying – “You always remember your first Doctor.” Similarly, I will always remember Windows 3.1 (but not fondly).

Business Insider has a retrospective on Windows through the years – that unfortunately neglects to mention Windows NT 3.51, Windows NT 4.0 and Windows 2000. It’s as though the first part of my tech career never existed.