「C#言語でWin32 API」の編集履歴(バックアップ)一覧はこちら

C#言語でWin32 API」(2008/01/04 (金) 01:38:52) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

大抵の場合は、Win32 APIを使用しなくても済んでしまうのですが、たまに必要なときがあります。 **ファイルIO .NET FrameworkのSystem.IOクラスでは、「\\.\physicaldrive0」などの物理ドライブに対するアクセスが出来ないので、CreateFile APIを使用する事になります。 参考資料は、[[Windows の ReadFile 関数を使用する>http://msdn2.microsoft.com/ja-jp/library/2d9wy99d(vs.80).aspx]]で、ポイントは、 -DllImportでDLLとAPIを指定する -プロジェクトのビルドプロパティで、「アンセーフコードの許可」をチェック となります。 ただし、MSのサンプルでは、CreateFileメソッドの返却値が0以外のときは成功としているのですが、無効なドライブを指定した時は、0xffffffffが返され、正常終了扱いとなってしまいます。 なお、「\\.\c:」の様な、論理ドライブに対する処理は、System.IO.DriveInfoクラスを使用すれば可能です。 System.IO.DriveInfo = new System.IO.DriveInfo("c"); Console.WriteLine(string.Format("{0} {1} {2}Byte(s)", info.ToString(), info.DriveFormat, info.TotalSize)); 全てのドライブを取得するには、staticメソッドのGetDrivesを使用します。 foreach (System.IO.DriveInfo info in System.IO.DriveInfo.GetDrives()) { Console.WriteLine(string.Format("{0} {1} {2}Byte(s)", info.ToString(), info.DriveFormat, info.TotalSize)); } MSの[[Windows の ReadFile 関数を使用する>http://msdn2.microsoft.com/ja-jp/library/2d9wy99d(vs.80).aspx]]の、CreateFileのエラー判定処理を修正すると共に、ドライブの容量を取得するDeviceIoControl処理を追加した、C#のコンソールアプリケーションベースのコードをメモとして載せておきます。 なお、DeviceIoControl処理の詳細は、Microsoft Platform SDKのWinIoCtl.hを見るのが一番かもしれません。 class FileReader { const uint GENERIC_READ = 0x80000000; const uint FILE_SHARE_WRITE = 0x00000002; // 物理ディスクを指定する場合、OPEN_EXISTINGを指定しなければいけないらしい const uint OPEN_EXISTING = 3; System.IntPtr handle; [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] static extern unsafe System.IntPtr CreateFile ( string FileName, // file name uint DesiredAccess, // access mode uint ShareMode, // share mode uint SecurityAttributes, // Security Attributes uint CreationDisposition, // how to create uint FlagsAndAttributes, // file attributes int hTemplateFile // handle to template file ); [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] static extern unsafe bool ReadFile ( System.IntPtr hFile, // handle to file void* pBuffer, // data buffer int NumberOfBytesToRead, // number of bytes to read int* pNumberOfBytesRead, // number of bytes read int Overlapped // overlapped buffer ); [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] static extern unsafe bool CloseHandle ( System.IntPtr hObject // handle to object ); // ドライブの容量を取得するためにDeviceIoControlを使用する const uint IOCTL_DISK_GET_LENGTH_INFO = 0x7405c; [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] static extern unsafe bool DeviceIoControl( System.IntPtr hFile, // handle to file uint dwIoControlCode, // 実行する動作の制御コード void* lpInBuffer, // 入力データを供給するバッファへのポインタ uint nInBufferSize, // 入力バッファのバイト単位のサイズ void* lpOutBuffer, // 出力データを受け取るバッファへのポインタ uint nOutBufferSize, // 出力バッファのバイト単位のサイズ uint* lpBytesReturned, // バイト数を受け取る変数へのポインタ int Overlapped // overlapped buffer ); public bool Open(string FileName) { // open the existing file for reading handle = CreateFile ( FileName, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ); // 物理ドライブ処理のエラーは、0xffffffffとなる if (handle != System.IntPtr.Zero && (uint)handle.ToInt32() != (uint)0xffffffff) { return true; } else { return false; } } public unsafe int Read(byte[] buffer, int index, int count) { int n = 0; fixed (byte* p = buffer) { if (!ReadFile(handle, p + index, count, &n, 0)) { return 0; } } return n; } public bool Close() { return CloseHandle(handle); } // ディスクの容量を取得する public unsafe long GetDiskSize() { long lDiskSize = 0; uint nBytes = sizeof(long); bool bResult = DeviceIoControl(handle, IOCTL_DISK_GET_LENGTH_INFO, null, 0, &lDiskSize, nBytes, &nBytes, 0); return lDiskSize; } } class Program { static void Main(string[] args) { FileReader fr = new FileReader(); for (int i = 0; i <= 9; i++) { string sDrivePath = string.Format(@"\\.\physicaldrive{0}", i); if (fr.Open(sDrivePath)) { long lDiskSize = fr.GetDiskSize(); fr.Close(); double dSize = lDiskSize / 1000000; if (dSize > 1000) { dSize /= 1000; System.Console.WriteLine( string.Format("Drive{0} {1,7:F1}GB", i, dSize)); } else System.Console.WriteLine( string.Format("Drive{0} {1,7:F1}MB", i, dSize)); } } return; } } **レジストリ .NET Frameworkでは、Microsoft.Win32.Registryからルートレジストリをアクセスできます。 たとえば、ADO.NET 2.0では、Microsoft Data Access Components(MDAC)2.8以降のバージョンが必要とされています。 MDACのバージョンは、レジストリのHKEY_LOCAL_MACHINE\Software\Microsoft\DataAccess\FullInstallVerを取得する事で確認できます。 そこで、MDACのバージョンを確認するメソッドは、 private bool ChkMDAC() { string sFullVer = (string)Microsoft.Win32.Registry.GetValue (@"HKEY_LOCAL_MACHINE\Software\Microsoft\DataAccess", "FullInstallVer", ""); bool bResult = false; if (!string.IsNullOrEmpty(sFullVer)) { string[] sVer = sFullVer.Split('.'); int iVer1 = Convert.ToInt16(sVer[0]); int iVer2 = Convert.ToInt16(sVer[1]); if (iVer1 < 2 || (iVer1 == 2 && iVer2 < 80)) bResult = false; else bResult = true; } return bResult; } の様になります。 ※ マイクロソフトのサポート情報では、レジストリ上のバージョン情報はあてにならない場合があるので、Component Checkerというツールを使って確認する事を推奨していますが、不特定多数のユーザ向けのソフトウェアの場合、Component Checkerツールのインストールも要求するような事は非現実的だと思います。 また、レジストリのバージョン情報を参照するときも、FullInstallVer値と、Version値の両方の値を確認するように推奨していますが、手元のマシンの場合、 FullInstallVer: "2.81.1117.0" Version: "2.0.0" となっています

表示オプション

横に並べて表示:
変化行の前後のみ表示: