0

I have a shell extension which allows users to right-click a folder and then passes the path as an argument to a utility.

To work in a network environment, it has to resolve any mounted drives. For example if the path were P:\projects\P123 it might resolve to \\server3\business\projects\P123

The following code from Stackoverflow has worked fine, but I now need to handle situations where the user right-clicks on the folder of a local drive. For example if the folder is c:\users\JohnDoe\documents I need it to return this very same path. Unfortunately for a path like this it returns \users\JohnDoe\documents which obviously won't work.

I'm a novice so if you can help, please could you spell out the advice so that someone with limited experience can understand it - thanks.

  public string GetUNCPath(string path)
        {
            string rval = path;
            string driveprefix = path.Substring(0, 2);
            string unc;

            if (driveprefix != "\\")
            {
                ManagementObject mo = new ManagementObject();
                try
                {
                    mo.Path = new ManagementPath(String.Format("Win32_LogicalDisk='{0}'", driveprefix));
                    unc = (string)mo["ProviderName"];
                    rval = path.Replace(driveprefix, unc);
                }
                catch
                {
                    throw;
                }
            }

            if (rval == null)
            { rval = path; }

            return rval;
        }
Max Headroom
  • 151
  • 7
  • Just to clarify, you have a Windows Shell Extension that is written in C# and it _somehow actually works_? (I'm asking because [it's well-accepted that you _cannot_ write a Win32 shell-extension in C#](https://stackoverflow.com/q/2194572/159145) - so I want to know how this code is even running...) – Dai Jul 01 '23 at 20:14
  • Hi Dai, yes it's in C# and it works well. We used SharpShell https://github.com/dwmkerr/sharpshell – Max Headroom Jul 01 '23 at 20:33

1 Answers1

0

In the end I worked it out myself. All I needed was to test whether the drive was local. Here's the working code:

 public string GetUNCPath(string path)
        {
            if (!IsNetworkDrive(path)) return path;   // If it's not a network path, just return the path unchanged

            string rval = path;
            string driveprefix = path.Substring(0, 2);
            string unc;

            if (driveprefix != "\\")
            {
                ManagementObject mo = new ManagementObject();
                try
                {
                    mo.Path = new ManagementPath(String.Format("Win32_LogicalDisk='{0}'", driveprefix));
                    unc = (string)mo["ProviderName"];
                    rval = path.Replace(driveprefix, unc);
                }
                catch
                {
                    throw;
                }
            }

            if (rval == null)
            { rval = path; }

            return rval;
        }
        public bool IsNetworkDrive(string path)
        {
            FileInfo f = new FileInfo(path);
            string driveRoot = Path.GetPathRoot(f.FullName); // Example return "C:\"
            // find the drive 
            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            foreach (var drive in drives)
            {
                string driveName = drive.Name; // C:\, E:\, etc:\
                if (driveName == driveRoot) // if this is the drive 
                {
                    System.IO.DriveType driveType = drive.DriveType;
                    if (driveType == System.IO.DriveType.Network) return true;
                }
            }
            return false; 
        }   
Max Headroom
  • 151
  • 7