2017-09-09 14 views
0

드라이브를 사용 중인지 확인하고 싶습니다. C#을 사용하여 일부 읽기/쓰기 작업이 진행되고 있다고 잘못 생각하지 않습니다. 나는 bash 스크립트를 사용하거나 C# 응용 프로그램에서 사용할 수 있기 때문에 비슷한 솔루션을 사용하지 않아도됩니다. 나는 이미 bash 스크립트 here에 관한 질문을 찾았지만 주어진 답을 가지고 나의 문제를 해결할 수 없었다.드라이브가 사용 중인지 평가하십시오

나는 이미 DriveInfo 클래스를 사용한다고 생각했지만, 나에게 도움이되는 것 같지 않았습니다. 나는 DriveInfo에서 IsReady 속성을 사용할 수 있었는지 궁금해했습니다. 읽기/쓰는 동안 준비가되지 않았을 것이라고 생각했기 때문입니다.하지만이 시도는 나에게 다소 힘이들 것 같습니다.

그러나 나는 아직도 그것을 시도 :

private static bool IsDriveInUse() 
{ 
    var drive = DriveInfo.GetDrives().FirstOrDefault(info => info.Name.StartsWith(DRIVE_LETTER.ToString())); 
    return drive != null && !drive.IsReady; 
} 

그러나 (내 드라이브에서 음악을 연주하면서 false를 반환) 작동하지 않았다.

나를위한 최적의 솔루션은 특정 시간대에 드라이브가 사용 중이라는 것을 알려주는 기능입니다 (이름은 IsDriveInUse). 즉, 시간이 예를 들어 60 초인 경우 IsDriveInUse은 드라이브에서 함수 호출 내용을 읽는 5 초 전에 true을 반환하고 전달 된 60 초 동안 읽기/쓰기 작업이 없으면 false을 반환해야합니다.


편집은, 내가 할 노력하고있어 설명하려고합니다 정확히 내가 사용에 뜻 지정합니다. 내가 유휴 상태이거나 키보드 단축키를 누르면 하드 드라이브가 자동으로 회전하는 도구를 쓰고 있습니다. 프로그래밍 방식으로 스핀 다운 할 수있었습니다 (Windows 통합 도구 나 다른 도구로도 가능했지만 다른 문제 임). 그러나 현재 사용 중인지 여부와 관계없이 매분마다 하드 드라이브가 회전합니다. 다시 말하면, 하드 드라이브에서 음악을 재생하면 여전히 소리가 나고 소리가 나지 않는 소리가 들려옵니다.

이 점이 분명 해졌기를 바랍니다.


편집 나는 지금 FSCTL_LOCK_VOLUME 제어 코드 (나는 IOCTL_DISK_PERFORMANCE에 대한 값을 찾을 수 없습니다)를 사용했지만, 내가 음악을 연주하는 동안 여전히 IsDriveInUse()에 대한 false를 반환했습니다. 더욱이, Windows가 드라이브를 사용하고 있다고 생각하여 Windows를 출시했기 때문에 Windows가 드라이브를 다시 회전시킬 때 창을 직접 회전 시켰습니다.

public class DriveManager 
{ 
    public const int FSCTL_LOCK_VOLUME = 0x00090018; 
    public const int FSCTL_UNLOCK_VOLUME = 0x0009001c; 

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

    [return: MarshalAs (UnmanagedType.Bool)] 
    [DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern bool DeviceIoControl (
     [In] SafeFileHandle hDevice, 
     [In] int dwIoControlCode, [In] IntPtr lpInBuffer, 
     [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, 
     [In] int nOutBufferSize, out int lpBytesReturned, 
     [In] IntPtr lpOverlapped); 

    public static SafeFileHandle CreateFileR (string device) 
    { 
     string str = device.EndsWith (@"\") ? device.Substring (0, device.Length - 1) : device; 
     return new SafeFileHandle (
      CreateFile (@"\\.\" + str, WinntConst.GENERIC_READ, WinntConst.FILE_SHARE_READ, IntPtr.Zero, 
         WinntConst.OPEN_EXISTING, WinntConst.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true); 
    } 

    internal class WinntConst 
    { 
     // Fields 
     internal static uint FILE_ATTRIBUTE_NORMAL = 0x80; 

     internal static uint FILE_SHARE_READ = 1; 
     internal static uint GENERIC_READ = 0x80000000; 
     internal static uint OPEN_EXISTING = 3; 
    } 

    public static bool IsDriveInUse (string deviceName) 
    { 
     var handle = CreateFileR (deviceName); 
     var buffer = Marshal.AllocHGlobal (sizeof (int)); 
     try 
     { 
      return 
       DeviceIoControl (handle, 
           FSCTL_LOCK_VOLUME, 
        IntPtr.Zero, 
        0, 
        buffer, 
        sizeof(int), 
        out var bytesReturned, 
        IntPtr.Zero 
       ); 
     } 
     finally 
     { 
      var sessionId = Marshal.ReadInt32 (buffer); 
      Marshal.FreeHGlobal (buffer); 
      handle.Close(); 
     } 
    } 

및 구현 : 아마 도움이

private static bool IsDriveInUse() => DriveManager.IsDriveInUse ([email protected]"{DRIVE_LETTER}:\"); 

는 부분이있는 나는 (나는 이것에 대한 Smartmontools 사용)뿐만 아니라 디스크를 회전하고있어 볼을 이것은 내가 뭘하려 :

internal static class Program 
{ 
    private const string PROGRAM_PATH = @"External\smartctl.exe"; 
    private const string ARGUMENTS_SHUTDOWN = @"-s standby,now {0}:"; 
    private const char DRIVE_LETTER = 'd'; 


    public static void Main (string [] args) 
    { 
     InitializeHotKey(); 
     Console.WriteLine ("Hotkey registered!"); 

     while (true) 
     { 
      Thread.Sleep (60000); 
      if (!IsDriveInUse()) 
       ShutDownDrive (true); 
     } 
    } 

    private static bool IsDriveInUse() => DriveManager.IsDriveInUse ([email protected]"{DRIVE_LETTER}:\"); 

    private static void InitializeHotKey() 
    { 
     HotKeyManager.RegisterHotKey (Keys.D, KeyModifiers.Alt | KeyModifiers.Control); 
     HotKeyManager.HotKeyPressed += HotKeyPressed; 
    } 

    private static void HotKeyPressed (object sender, HotKeyEventArgs hotKeyEventArgs) => ShutDownDrive (true); 

    private static void ShutDownDrive (bool withDialog = false) 
    { 
     Process process; 
     (process = new Process 
     { 
      StartInfo = new ProcessStartInfo 
      { 
       WindowStyle = ProcessWindowStyle.Hidden, 
       FileName = PROGRAM_PATH, 
       Arguments = string.Format (ARGUMENTS_SHUTDOWN, DRIVE_LETTER) 
      } 
     }).Start(); 

     process.WaitForExit(); 
     process.Close(); 

     if (withDialog) 
      Console.WriteLine ("Drive shut down!"); 
    } 
} 
+0

"사용 중"과 "준비 중"으로 정확히 무엇을 지정하십시오. 디스크는 스케줄링을 통해 한 번에 여러 가지 작업을 수행 할 수 있습니다. 워크 스테이션과 서버 하드 디스크에는 거의 항상 읽기 또는 쓰기가 진행됩니다. 정확히 어떤 문제를 해결하려고합니까? 컴퓨터, 이동식 드라이브 또는 네트워크 드라이브에 고정 된 드라이브입니까? – CodeCaster

+0

"InUse"에 대한 올바른 정보를 얻을 수 있다고 가정 해 보겠습니다. 행동을 취하기 전에 상태가 바뀔 수 있습니다. –

+0

@ L.B 저는 주로이 도구를 쓰고 있습니다. 하드 드라이브를 자주 사용하지 않기 때문에이 경우가 아니라고 약속 할 수 있습니다. – MetaColon

답변