Проверка эквивалентных общих папок в .net - PullRequest
1 голос
/ 04 ноября 2008

Есть ли способ в рамках .net проверить, действительно ли две разные общие папки указывают на один и тот же физический каталог? У каталогов в Windows есть какой-то уникальный идентификатор? Google-фу подводит меня.

(я имею в виду, кроме записи временного файла в один и проверки, появляется ли он в другом)

Редактировать: Я думаю, что нашел то, что мне нужно, благодаря Броди, который указал мне правильное направление в пространстве имен System.Management.

Ответы [ 4 ]

1 голос
/ 05 ноября 2008

Если вы не используете WMI, неуправляемый вызов будет NetShareEnum с именем сервера NULL (локальный компьютер) и уровнем 502 для получения структуры SHARE_INFO_502 . Локальный путь находится в shi502_path.

P / Invoke info , как всегда, закончено на pinvoke.net.

0 голосов
/ 05 ноября 2008

Я думаю, что .NET Framework не предоставляет информацию, необходимую для сравнения двух каталогов ... Вы должны принять неуправляемый подход. Вот как я это сделал:

class Program
{
    struct BY_HANDLE_FILE_INFORMATION
    {
        public uint FileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
        public uint VolumeSerialNumber;
        public uint FileSizeHigh;
        public uint FileSizeLow;
        public uint NumberOfLinks;
        public uint FileIndexHigh;
        public uint FileIndexLow;
    }

    //
    // CreateFile constants
    //
    const uint FILE_SHARE_READ = 0x00000001;
    const uint FILE_SHARE_WRITE = 0x00000002;
    const uint FILE_SHARE_DELETE = 0x00000004;
    const uint OPEN_EXISTING = 3;

    const uint GENERIC_READ = (0x80000000);
    const uint GENERIC_WRITE = (0x40000000);

    const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
    const uint FILE_READ_ATTRIBUTES = (0x0080);
    const uint FILE_WRITE_ATTRIBUTES = 0x0100;
    const uint ERROR_INSUFFICIENT_BUFFER = 122;
    const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;


    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        IntPtr lpSecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        IntPtr hTemplateFile);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);

    static void Main(string[] args)
    {
        string dir1 = @"C:\MyTestDir";
        string dir2 = @"\\myMachine\MyTestDir";
        Console.WriteLine(CompareDirectories(dir1, dir2));
    }

    static bool CompareDirectories(string dir1, string dir2)
    {
        BY_HANDLE_FILE_INFORMATION fileInfo1, fileInfo2;
        IntPtr ptr1 = CreateFile(dir1, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING,  FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);
        if ((int)ptr1 == -1)
        {
            System.ComponentModel.Win32Exception t = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            Console.WriteLine(dir1 + ": " + t.Message);
            return false;
        }
        IntPtr ptr2 = CreateFile(dir2, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING,  FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);
        if ((int)ptr2 == -1)
        {
            System.ComponentModel.Win32Exception t = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            Console.WriteLine(dir2 + ": " + t.Message);
            return false;
        }
        GetFileInformationByHandle(ptr1, out fileInfo1);
        GetFileInformationByHandle(ptr2, out fileInfo2);

        return ((fileInfo1.FileIndexHigh == fileInfo2.FileIndexHigh) &&
            (fileInfo1.FileIndexLow == fileInfo2.FileIndexLow));
    }
}

Это работает! Надеюсь, это поможет.

Приветствие.

0 голосов
/ 05 ноября 2008

Я считаю, что использование запросов WMI позаботится о том, что мне нужно сделать:

Connection options = new ConnectionOptions();
ManagementScope scpoe = new ManagementScope("\\\\Server\\root\\cimv2", options);
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Share WHERE Name = '" + name +"'")

ManagementObjectSearcher searcher = new ManagementObjectSearch(scope, query);
ManagementObjectCollection qc = searcher.Get();

foreach (ManagementObject m in qc) {
    Console.WriteLine(m["Path"]);
}

А атрибут Path даст мне физический путь к общей папке, которую я могу использовать для сравнения двух общих папок.

0 голосов
/ 05 ноября 2008

Вы можете проверить само определение общего ресурса, используя пространство имен System.Management, но его нелегко использовать.

начинается что-то вроде

ManagementClass management = new ManagementClass("\\\\.\\root\\cimv2", "Win32_Share", null)

И после этого становится намного хуже. Я использовал это, чтобы создать акцию. Надеюсь, вы сможете использовать его для пути к каждой акции и сравнить.

...