.net フレームワーク内で、2 つの異なる共有フォルダーが実際に同じ物理ディレクトリを指しているかどうかを確認する方法はありますか? Windows のディレクトリには、ある種の一意の識別子がありますか? グーグルフーは私を失敗させています。
(つまり、一時ファイルを一方に書き込んで、それが他方に表示されるかどうかを確認することは別として)
編集: System.Management 名前空間で正しい方向を示してくれた Brody のおかげで、必要なものを発見したと思います。
.net フレームワーク内で、2 つの異なる共有フォルダーが実際に同じ物理ディレクトリを指しているかどうかを確認する方法はありますか? Windows のディレクトリには、ある種の一意の識別子がありますか? グーグルフーは私を失敗させています。
(つまり、一時ファイルを一方に書き込んで、それが他方に表示されるかどうかを確認することは別として)
編集: System.Management 名前空間で正しい方向を示してくれた Brody のおかげで、必要なものを発見したと思います。
WMIを使用しない場合、アンマネージ呼び出しは、サーバー名がNULL(ローカルコンピューター)でレベルが502のNetShareEnumであり、 SHARE_INFO_502構造体を取得します。ローカルパスはshi502_pathにあります。
P / Invoke情報は、いつものように、pinvoke.netで終了します。
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属性は、共有の物理パスを提供します。これを使用して、2つの共有を比較できます。
.NET フレームワークは、2 つのディレクトリを比較するために必要な情報を提供していないと思います。管理されていないアプローチを取る必要があります。これが私がやった方法です:
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));
}
}
できます!お役に立てれば。
乾杯。
System.Management 名前空間を使用して共有定義自体を調べることはできますが、使用は簡単ではありません。
それは次のようなものを開始します
ManagementClass management = new ManagementClass("\\\\.\\root\\cimv2", "Win32_Share", null)
そして、その後さらに悪化します。それを使用して共有を作成しました。うまくいけば、それを各共有のパスに使用して比較できます。