Converting file names to the DOS 8.3 format using PowerShell

by Klaus Graefensteiner 24. June 2010 12:45

Introduction

I have been busy lately with writing lots of PowerShell scripts. One of the problems that gave me major headaches was passing path names that contain spaces like for example “C:\Program Files\My Tools\Make Me Rich.exe” from a PowerShell script to a console application. It seems like some tools can handle blanks and other’s don’t. I didn’t spent to much time doing a proper analysis, but this seemed to be an issue of the command line parsing routing that is being used in each of the utilities. I gave up trying to figure out how to pass the quotation marks to the console application and decided to go a different route.

GiantRubberDuck

Figure 1: Big rubber ducky

I created a little script that converts long path names to the short 8.3 DOS format before I passed it to the console application. This seemed to work.

To round this little script up I also added the reverse function to the library that would take a short 8.3 DOS file name and resolve it to its long path name.

By the way the P/Invoke code was copied from http://pinvoke.com.

The Script

$DebugPreference = "continue"

function Load-FileSystemHelper()
{
    $Code =
@"
using System;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Globalization;

public class FileSystemHelper
{
  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  private static extern int GetShortPathName(
      [MarshalAs(UnmanagedType.LPTStr)] string path,
      [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
      int shortPathLength);

  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  [return: MarshalAs(UnmanagedType.U4)]
  private static extern int GetLongPathName(
      [MarshalAs(UnmanagedType.LPTStr)]
            string lpszShortPath,
      [MarshalAs(UnmanagedType.LPTStr)]
            StringBuilder lpszLongPath,
      [MarshalAs(UnmanagedType.U4)]
            int cchBuffer);

  public static string GetShortPathName(string path)
  {
    StringBuilder shortPath = new StringBuilder(500);
    if (0 == GetShortPathName(path, shortPath, shortPath.Capacity))
    {
      if (Marshal.GetLastWin32Error() == 2)
      {
        throw new Exception("File does not exist!");
      }
      else
      {
        throw new Exception("GetLastError returned: " + Marshal.GetLastWin32Error());
      }
    }
    return shortPath.ToString();
  }


  public static string GetLongPathName(string shortPath)
  {
    if (String.IsNullOrEmpty(shortPath))
    {
      return shortPath;
    }

    StringBuilder builder = new StringBuilder(255);
    int result = GetLongPathName(shortPath, builder, builder.Capacity);
    if (result > 0 && result < builder.Capacity)
    {
      return builder.ToString(0, result);
    }
    else
    {
      if (result > 0)
      {
        builder = new StringBuilder(result);
        result = GetLongPathName(shortPath, builder, builder.Capacity);
        return builder.ToString(0, result);
      }
      else
      {
        throw new FileNotFoundException(
        string.Format(
        CultureInfo.CurrentCulture,
        null,
        shortPath),
        shortPath);
      }
    }
  }
}
"@
    
    Add-Type -TypeDefinition $Code
}


function Get-DOSPathFromLongName([string] $Path)
{
    Load-FileSystemHelper
    $DOSPath = [FileSystemHelper]::GetShortPathName($Path)
    Write-Debug $DOSPath
    return $DOSPath
}

function Get-LongNameFromDOSPath([string] $Path)
{
    Load-FileSystemHelper
    $LongPath = [FileSystemHelper]::GetLongPathName($Path)
    Write-Debug $LongPath
    return $LongPath
}

$DOSPath = Get-DOSPathFromLongName -Path "C:\Program Files (x86)\"
Explorer $DOSPath
$LongPath = Get-LongNameFromDOSPath -Path $DOSPath
Explorer $LongPath

The Download

The script can be downloaded here: ShortAndLongPathNames.zip

Ausblick

PowerShell gets an A+ for .NET interoperability. Seriously!

Tags: , , , , , , , ,

PowerShell | Tips & Tricks

Comments are closed

About Klaus Graefensteiner

I like the programming of machines.

Add to Google Reader or Homepage

LinkedIn FacebookTwitter View Klaus Graefensteiner's profile on Technorati
Klaus Graefensteiner

Klaus Graefensteiner
works as Developer In Test and is founder of the PowerShell Unit Testing Framework PSUnit. More...

Open Source Projects

PSUnit is a Unit Testing framwork for PowerShell. It is designed for simplicity and hosted by Codeplex.
BlogShell is The tool for lazy developers who like to automate the composition of blog content during the writing of a blog post. It is hosted by CodePlex.

Administration

About

Powered by:
BlogEngine.Net
Version: 1.6.1.0

License:
Creative Commons License

Copyright:
© Copyright 2014, Klaus Graefensteiner.

Disclaimer:
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Theme design:
This blog theme was designed and is copyrighted 2014 by Klaus Graefensteiner

Rendertime:
Page rendered at 9/23/2014 1:21:57 PM (PST Pacific Standard Time UTC DST -7)