My Thoughts On IT…

Brian Lewis's Thoughts on all things Information Technology related

powershell2-300x300My Father introduced me to computers when I was in high school and one of his favorite tools he would add to his workstation was a DOS tool called “whereis.exe”. The whereis name comes from a Unix command but that is not what I like about it. The executable my Dad  had was a great search tool in the old days, long before search was built into the OS and I want a tool like that.

I have looked for this tool and been disappointed with most things I have found. So, when I was brushing up on my PowerShell I looked for an equivalent way to search. I did find the PowerShell standard command for this – get-childitem, but it left me wanting more. Then I found this old article by Tim Bolton: It is about a PowerShell script called whereis.ps1 and it looked promising. It was very well written and commented by Bill Stewart.

I made some changes to the script to ignore errors and change the output to make it fit my wants better. I also made a few changes to the self help to give the syntax of more complicated commands. Now it is exactly what I was looking for! Let me know if you need help getting this to work for you!



Here is the code:

# Whereis.ps1
# Origionally Written by Bill Stewart (
# Updated by Brian Lewis (
# Searches for files and/or directories.

param ($Name,
       [Switch] $OneLevel,
       [Switch] $Files,
       [Switch] $Dirs,
       [Switch] $Force,
       [Switch] $DefaultFormat,
       [Switch] $Help)

# Displays a usage message and ends the script.
function usage {
  $scriptname = $SCRIPT:MYINVOCATION.MyCommand.Name

  ”    $scriptname”
  ”    Searches for files and/or directories.”
  ”    $scriptname -name <String[]> [-path <String[]>]”
  ”    [-lastwritetimerange <DateTime[]> [-sizerange <UInt64[]> [-onelevel]”
  ”    [-files] [-dirs] [-force] [-defaultformat]”
  ”   set-alias whereis ./whereis.ps1      # if you set the alias you can just type ‘whereis’ instead of .\whereis.ps1 :)”
  ”             whereis blewis.txt”
  ”             whereis blewis.txt -path c:\users”
  ”             whereis blewis.txt c:\users -Force”
  ”             whereis *blewis* -path c:\users -SizeRange 55000,10000000″
  ”             whereis blewis* -path c:\users -LastWriteTimeRange 4/18/2014,6/18/2014″
  ”    -name <String[]>”
  ”        Searches for items that match the specified wildcard pattern(s).”
  ”    -path <String[]>”
  ”        Searches for items in the specified location(s). If not specified, the”
  ”        default is to search all local fixed drives.”
  ”    -lastwritetimerange <DateTime[]>”
  ”        Limits output to items matching a date range. A single value means”
  ”        “”items modified from the specified date and later.”” An array is”
  ”        interpreted as an inclusive date range where the first element is the”
  ”        earliest date and the second element is the latest date. A zero for the”
  ”        first element means “”no earliest date.”””
  ”    -sizerange <UInt64[]>”
  ”        Limits output to files matching a size range. A single value means”
  ”        “”files must be at least the specified size.”” An array is interpreted as”
  ”        an inclusive size range where the first element is the smallest size”
  ”        and the second element is the largest size.”
  ”    -onelevel”
  ”        This parameter limits searches to the specified path(s). Subdirectories”
  ”        are not searched.”
  ”    -files”
  ”        Searches for files. This is the default. To search for both files and”
  ”        directories, specify both -files and -dirs.”
  ”    -dirs”
  ”        Searches for directories. To search for both files and directories,”
  ”        specify both -files and -dirs.”
  ”    -force”
  ”        Expands the search to find items with hidden and system attributes.”
  ”    -defaultformat”
  ”        Outputs items using the default formatter instead of formatted”
  ”        strings.”


# Returns whether the specified value is numeric.
function isNumeric($value) {
  [Decimal], [Double], [Int32], [Int64],
  [Single], [UInt32], [UInt64] -contains $value.GetType()

# Outputs the specified file system item. With -defaultformat,
# output the item using the default formatter; otherwise, output a
# formatted string.
function writeItem($item) {
  if ($DefaultFormat) {
    “{0} {1:yyyy-MM-dd HH:mm} {2,15:N0} {3}” -f $item.Mode,
      $item.LastWriteTime, $item.Length, $item.FullName
  else {
   $item | Select-Object Name,Directory

function main {
  # If -help is present or the -name parameter is missing, output
  # the usage message.
  if (($Help) -or (-not $Name)) {

  # Convert $Name to an array. If any array element contains *,
  # change the array to $NULL. This is because
  #   get-childitem c:\* -include *
  # recurses to one level even if you don’t use -recurse.
  $Name = @($Name)
  for ($i = 0; $i -lt $Name.Length; $i++) {
    if ($Name[$i] -eq “*”) {
      $Name = $NULL

  # If no -path parameter, use WMI to collect a list of fixed drives.
  if (-not $Path) {
    $Path = get-wmiobject Win32_LogicalDisk -filter DriveType=3 | foreach-object {

  # Convert $Path into an array so we can iterate it.
  $Path = @($Path)

  # If a path ends with “\”, append “*”. Then, if it doesn’t end with
  # “\*”, append “\*” so each path in the array ends with “\*”.
  for ($i = 0; $i -lt $Path.Length; $i++) {
    if ($Path[$i].EndsWith(“\”)) {
      $Path[$i] += “*”
    if (-not $Path[$i].EndsWith(“\*”)) {
      $Path[$i] += “\*”

  # If no -LastWriteTimeRange parameter, assume all dates.
  if (-not $LastWriteTimeRange) {
    $LastWriteTimeRange = @([DateTime]::MinValue, [DateTime]::MaxValue)
  else {
    # Convert $LastWriteTimeRange to an array (if it’s not already).
    $LastWriteTimeRange = @($LastWriteTimeRange)
    # If only one element, add max date as second element.
    if ($LastWriteTimeRange.Length -eq 1) {
      $LastWriteTimeRange += [DateTime]::MaxValue
    # Zero for first element means [DateTime]::MinValue.
    if ($LastWriteTimeRange[0] -eq 0) {
      $LastWriteTimeRange[0] = [DateTime]::MinValue
    # Throw an error if [DateTime]::Parse() fails.
    trap [System.Management.Automation.MethodException] {
      throw “Error parsing date range. String not recognized as a valid DateTime.”
    # Parse the first two array elements as DateTimes.
    for ($i = 0; $i -lt 2; $i++) {
      $LastWriteTimeRange[$i] = [DateTime]::Parse($LastWriteTimeRange[$i])

  # Throw an error if the date range is invalid.
  if ($LastWriteTimeRange[0] -gt $LastWriteTimeRange[1]) {
    throw “Invalid date range. The first date is greater than the second.”

  # If no -sizerange parameter, assume all sizes.
  if (-not $SizeRange) {
    $SizeRange = @(0, [UInt64]::MaxValue)
  else {
    # Convert $SizeRange to an array (if it’s not already).
    $SizeRange = @($SizeRange)
    # If no second element, add max value as second element.
    if ($SizeRange.Length -eq 1) {
      $SizeRange += [UInt64]::MaxValue

  # Ensure the elements in the size range are numeric.
  for ($i = 0; $i -lt 2; $i++) {
    if (-not (isNumeric $SizeRange[$i])) {
      throw “Size range must contain numeric value(s).”

  # Throw an error if the size range is invalid.
  if ($SizeRange[0] -gt $SizeRange[1]) {
    throw “Invalid size range. The first size is greater than the second.”

  # If both -files and -dirs are missing, assume -files.
  if ((-not $Files) -and (-not $Dirs)) {
    $Files = $TRUE

  # Keep track of the number of files and their sizes.
  $count = $sizes = 0

  # Use the get-childitem cmdlet to search the file system, and use
  # the writeItem function to output matching items. For files, check
  # the date and size ranges. For directories, only the date range is
  # meaningful.
  get-childitem $Path -include $Name -ErrorAction SilentlyContinue -force: $Force -recurse: (-not $OneLevel) | foreach-object {
    if ($Files -and (-not $_.PsIsContainer)) {
      if (($_.LastWriteTime -ge $LastWriteTimeRange[0]) -and ($_.LastWriteTime -le $LastWriteTimeRange[1]) -and
          ($_.Length -ge $SizeRange[0]) -and ($_.Length -le $SizeRange[1])) {
        $sizes += $_.Length
        writeItem $_
    if ($Dirs -and ($_.PsIsContainer)) {
      if (($_.LastWriteTime -ge $LastWriteTimeRange[0]) -and ($_.LastWriteTime -le $LastWriteTimeRange[1])) {
        writeItem $_

  # Output statistics if not using -defaultformat.
  if (-not $DefaultFormat) {
    “Found {0:N0} item(s), {1:N0} byte(s)” -f $count, $sizes



More info on PowerShell can be found here:

Running Windows PowerShell Scripts


Keeping Aliases Around

USBwarningOk, once again we have a very scary computer security / insecurity revelation. USB drives are horribly insecure!

We have known to be concerned of devices that map directly to memory, like FireWire. They can access the computer ram and read it or write it without restriction. USB always seemed to be more secure than these devices because they didn’t have direct access to ram. The only thing we thought we needed to worry about with USB was either malicious files on the USB stick or if it was a keyboard entry stick like the rubber ducky stick.

Well now we have more to worry about. Because those USB drives also have a firmware section that make them work. Now researchers have found that you can put exploit code into the firmware. This is a section that is not scanned by antivirus and not normally visible to the operating system.

For more on the dangers:

Hackers can tap USB devices in new attacks, researcher warns–finance.html

USB: The ultimate hacking tool?

What are the Dangers of using an untrusted USB drive? (Before the new firmware exploits)

Chicago-BeanTechEd Part Duex… Plus (the plus is more)
Last month Microsoft announced a new huge event we will be hosting in Chicago the week of May 4th 2015.

The unified “Microsoft commercial technology event” as it is currently called will combine 5 different conferences into one!

The five Microsoft conferences that are now being merged into one Gigantic Conference are:

  • SharePoint Conference
  • Lync Conference
  • Exchange Conference
  • Project Conference
  • TechEd North America Conference

Whatever the name of this event, “Microsoft’s unified technology event for enterprises” or “unified Microsoft commercial technology event”,  my idea “Tech-Ed Plus” Smile, or something completely different, it promises to be a great conference and I hope to see you there.


More information about the event can be found in the Microsoft official announcements here:

Julie White’s Blog – Microsoft’s unified technology event for enterprises

Channel 9 – Announcing: Microsoft’s Unified Technology Event for Enterprises

Steve Guggenheimer’s Blog – Announcing: Microsoft’s Unified Technology Event for Enterprises


Just when I thought I knew all about creating Virtual Machines up on Microsoft’s Azure public cloud platform a new way has released this past Monday. (The wonderful thing about working in technology is that you are always learning) Smile

As of this past Monday the Azure Preview Portal now has the ability to create, manage, and monitor Virtual Machines. I was originally worried about the new portal as I have spent the last year in the standard Azure Portal and know how to do things there. However, in the short time I have been using the new portal I find the improvements are so dramatic that I don’t think it will be hard to switch over to the new portal completely when it comes out of preview.

Why don’t you take a look at Azure today and see what the future of Server computing looks like. You can get a 30 day free trial of Azure just go the and click on “try it”.

Want to learn more about Azure and Hybrid Cloud?

To continue your learning on Microsoft Azure and Hybrid Cloud, be sure to join our FREE Hybrid Cloud study track in our online Early Experts study group!

Ofc365_Orng166_rgbCustomers often want to know what is coming in the next versions of a Microsoft product or service. The Office 365 group understands this and has programmatically added it to their process. With online services product groups at Microsoft are continually adding new functionality into the offerings. As opposed to a traditional software product which bundles all the updates into a new version every year and a half or so. I see having a published roadmap as a much appreciated addition to the services model.

The Office 365 team just launched an Office 365 Business Roadmap site. Unveiled yesterday, June 19th, in a blog post. You can see the announcement here:

One of the things I like about the site is how they separate the information into four main buckets and then go into detail on the specific features.

The Roadmap Site’s 4 buckets are:

  • What’s has Launched
  • What’s Rolling Out
  • What’s In Development
  • What’s Canceled

Check it out for yourself and see what we have planned for you.

The Office 365 for business roadmap is available here:

imageOne of the questions customers often ask is what the heck does the new /vm switch do in Sysprep.exe. Well here is the secret…

What the /mode:vm switch does
Running SYSPREP removes unique information, such as the SID and GUID, but it also resets the hardware drivers information. When you run Sysprep with the /mode:vm switch you don’t remove the hardware information. This means the machine doesn’t need to redetect hardware on it’s first boot enabling a faster process when creating new VMs.

Command Line Only
VM mode is available only through the command line. It is also supported only when you run it from inside a virtual machine and deploying to a virtual machine of the same type. (i.e. Hyper-v Gen1 to Hyper-v Gen1 or Hyper-v Gen2 to Hyper-v Gen2)

Here is a side note…
I spent a good half hour a few years ago looking for the Sysprep.exe download on the internet. Guess what? You won’t find a sysprep download as it is already in all Windows installs. Ouch – it still kinda stings…

To Run Sysprep
Open a Command Prompt window as an administrator. Change to the C:\windows\system32\sysprep directory. Type:

Command Description
Sysprep /generalize /shutdown /oobe Standard command for real hardware
Sysprep /generalize /shutdown /oobe /mode:vm Command for a Virtual Machine


For more info on Sysprep see the Technet article here:

imageHave you heard of HDbaseT?
I currently use HDMI to connect my flat-panel TV to my Bose system which uses HDMI to connect to a bunch of other devices. (Xbox, Cable, Roku, Apple TV, PS3) It sure would be nice to be able to use a CAT5 cable to connect these devices instead of HDMI. That is what the HDBaseT standard is meant to do.

HDBaseT not only caries the transmission of uncompressed high-definition video and audio like HDMI but it also adds power, home networking, and some control signals all over a common cable with a standard connector. This could be the next connection technology you use to connect your systems together. I hope so!

HDBaseT spec 1.0 was finalized in June of 2010 and a 2.0 spec is expected. It is supported by the HDBaseT Alliance. This is an alliance of electronic industry companies such as Samsung, LG, Sony, Panasonic, Creston, and many others. To find out more about the HDBaseT alliance and technology visit the alliance website:

Hopefully we will see this technology in our home electronics soon!

For more info on HDBaseT watch this video from Infocomm 2012

hadoop_azureI have often been asked “Does Microsoft have a Hadoop strategy?” The answer is, Yes! The easiest way to get this to work is in Microsoft Azure using the HDInsight feature.

As businesses seek ways to store, manage and analyze their ever-increasing amounts of data, they have looked for tools to capitalize on this wealth of data. The tool that has emerged as the predominant Big Data analysis tool is Apache Hadoop, an open source software allowing multiple servers to mine data in parallel.

Microsoft has built HDInsight in Azure as part of our comprehensive data platform to facilitate large data analysis.  It includes Hadoop and SQL Server technology to offer an easy to use Big Data platform.

To setup a cluster of servers is now an easy task with HDInsight in Azure. From the Azure portal you select to create an HDInsight Cluster and choose from 1 to 32 servers. Azure will provision your cluster in just a few minutes and it will be configured with Hadoop and YARN. YARN is the cluster resource management sub-project introduced in Hadoop 2.0.

The HDInsight service also has an easy-to-use Web interface that gives users the ability to create interactive queries over the Hive, the Hadoop component that provides large data set querying and management capabilities.

If you are interested in mining your data for those golden nuggets a fast, easy, and less expensive way is to use the HDInsight tool in Azure. Give it a try today!


For More Information:

Reveal new insights with Big Data

Microsoft updates its Hadoop cloud solution ( provides up to 100x performance improvements)

4353_Figure-3---Secured-boot-path-with-UEFI_7BBA93DAWhat is Secure Boot?
Secure Boot is a security standard developed by members of the PC industry to help make sure that your PC boots using only software that is trusted. This is a technology to prevent Rootkits. Windows 8 and above supports Secure Boot as does Windows Server 2012 and above.

How does it work? (High Level)
When the PC starts, the firmware checks the signature of each piece of boot software, including firmware drivers (Option ROMs) and the operating system. If the signatures are good, the PC boots, and the firmware gives control to the operating system.

How do I tell if it is working?
Just because you have new hardware that has a UEFI BIOS and you are running a version of Windows that supports Secure Boot doesn’t mean that you are running it. It is a bit more complicated than that.

1 Open a PowerShell Command Prompt and run as Administrator image
2 Run command:

Possible Cmdlet Returns:

True – All good! Your PC supports Secure Boot and Secure Boot is enabled
False – PC supports Secure Boot but Secure Boot is disabled (you may have a watermark on your desktop warning you of this)
Cmdlet not supported on this platform – This PC does not support Secure Boot or is setup in a Compatibility Support Module (CSM) Legacy BIOS mode.


For a good overview on what Secure Boot is see Steven Sinofsky’s old blog post:
Protecting the pre-OS environment with UEFI

For information on installing Windows to Support Secure boot see my previous post:
Installing Windows 8.1 from a USB Stick under a UEFI BIOS and Secure Boot

Windows-8_1Installing Windows 8.1 from a USB Stick under a UEFI BIOS and Secure Boot.
When Building a Windows UEFI system there are a few things to know that are different from when building an old BIOS based machine. First your USB install stick has be be formatted with FAT32 and Not NTFS. Second your UEFI motherboard probably has a Compatibility Support Module (CSM) mode that is set for BIOS compatibility. You need to turn that off if you want to enable UEFI, Secure Boot, and booting from a GPT partitioned disk.

The 11 steps for manually preparing / building a USB Disk to be a bootable Win 8.1 Install.
This bootable USB stick will work for both older BIOS installs as well as the newer UEFI installs.

1. Diskpart (Run from a CMD prompt)
2. List Disk
3. Select Disk # (Where # is the number of your USB disk)
4. Clean (removes any partitions on the USB disk, including any hidden sectors)
5. Create Partition Primary (Creates a new primary partition with default parameters)
6. Select Partition 1 (Focus on the newly created partition)
7. Active (Sets the selected partition to an active valid system partition state)
8. Format FS=fat32 quick (Formats the partition with the FAT32 file system. FAT32 is needed instead of NTFS so that it can load under the secure boot UEFI BIOS.)
9. Assign (Assigns the USB drive a drive letter)
10. Exit
11. Copy all the files from the Windows 8.1 DVD to the USB Stick.


For More information on on UEFI and Installing Windows to these machines here are some links:
Happy System Building! –Brian

For more information on UEFI BIOS and Secure Boot in Windows 8.1

Installing Windows on UEFI-based Computers