6

How can I figure out if a file is in a folder that has been SUBST'ed or is located in a user folder using C#?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
petejamd
  • 523
  • 1
  • 10
  • 14
  • 2
    I don't get what you mean by "subst'd" or "user folder" – simendsjo Jun 10 '10 at 16:13
  • `subst` is a dos command that will create an alias for a directory (eg. `subst T: C:\workareas` will create a new drive that points to C:\workareas) for user folder, i'm looking to find out if its in the `C:\Documents and Settings\%username%` cleanly. – petejamd Jun 10 '10 at 17:35

4 Answers4

3

I think you need to P/Invoke QueryDosDevice() for the drive letter. Subst drives will return a symbolic link, similar to \??\C:\blah. The \??\ prefix indicates it is substituted, the rest gives you the drive+directory.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
3

This is the code I use to get the information if a path is substed: (Some parts come from pinvoke)

using System.Runtime.InteropServices;

[DllImport("kernel32.dll", SetLastError=true)]
static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);

public static bool IsSubstedPath(string path, out string realPath)
{
    StringBuilder pathInformation = new StringBuilder(250);
    string driveLetter = null;
    uint winApiResult = 0;

    realPath = null;

    try
    {
        // Get the drive letter of the path
        driveLetter = Path.GetPathRoot(path).Replace("\\", "");
    }
    catch (ArgumentException)
    {
        return false;
        //<------------------
    }

    winApiResult = QueryDosDevice(driveLetter, pathInformation, 250);

    if(winApiResult == 0)
    {
        int lastWinError = Marshal.GetLastWin32Error(); // here is the reason why it fails - not used at the moment!

        return false;
        //<-----------------
    }

    // If drive is substed, the result will be in the format of "\??\C:\RealPath\".
    if (pathInformation.ToString().StartsWith("\\??\\"))
    {
        // Strip the \??\ prefix.
        string realRoot = pathInformation.ToString().Remove(0, 4);

        // add backshlash if not present
        realRoot += pathInformation.ToString().EndsWith(@"\") ? "" : @"\";

        //Combine the paths.
        realPath = Path.Combine(realRoot, path.Replace(Path.GetPathRoot(path), ""));

        return true;
        //<--------------
    }

    realPath = path;

    return false;
}
marsh-wiggle
  • 2,508
  • 3
  • 35
  • 52
  • be sure you have in your class using System.Runtime.InteropServices; Otherwise you will get error. – gg89 Sep 23 '16 at 05:11
1

If SUBST is run without parameters it produces a listing of all current substitutions. Get the list, and check your directory against the list.

There is also the issue of mapping a volume to a directory. I have never attempted to detect these, but the mount point directories do show up differently than regular directories, so they must have a different attribute of some kind, and that could be detected.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45
1

I think you have a few choices --

Via System.Management classes: http://briancaos.wordpress.com/2009/03/05/get-local-path-from-unc-path/

Or

Via P/Invoking this MAPI function: ScUNCFromLocalPath http://msdn.microsoft.com/en-us/library/cc842520.aspx

Bill
  • 131
  • 1
  • 5