For various reasons involving out testing framework, I found myself needing to get the full command-line of the current executing assembly. However, our development environment uses the DOS SUBST command to map a virtual drive letter for our dev files, so we have a consistent environment for all development machines. This is problematic, since I need this command-line to be launched in a different user context, where this SUBST mapping doesn't exist. In short, I needed a way to get the real path to a file beyond the SUBST illusion.
The answer turned out to be surprisingly easy, and required only a tiny bit of P/Invoking. I've included the signature here and also updated it on pinvoke.net, where it was using a more complicated signature using IntPtr that is only required if we want more than one return value for the function.
Make sure the ucchMax parameter you pass the function is the same size as you initialize the StringBuilder's buffer:
private static string GetRealPath(string path)
string realPath = path;
StringBuilder pathInformation = new StringBuilder(250);
string driveLetter = Path.GetPathRoot(realPath).Replace("\\", "");
QueryDosDevice(driveLetter, pathInformation, 250);
// If drive is substed, the result will be in the format of "\??\C:\RealPath\".
// Strip the \??\ prefix.
string realRoot = pathInformation.ToString().Remove(0, 4);
//Combine the paths.
realPath = Path.Combine(realRoot, realPath.Replace(Path.GetPathRoot(realPath), ""));
static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);