如何摆脱 Drive is not ready 消息框?

How to get rid of Drive is not ready message box?

我有一个出现故障的 U 盘,它一直保持连接和断开连接,间隔大约 500 毫秒,为了保存文件,我编写了一个逐字节复制文件的软件,每当 U 盘断开连接时,软件都会等待然后一次又一次地尝试。

它有效,但有时 Windows 会显示一个消息框,询问它无法访问驱动器以及它应该做什么,我想知道我是否可以以某种方式阻止显示此消息以便我的应用程序无论如何都能继续工作?

您可以从存储库下载代码: https://github.com/movsar/copynomatterwhat

这是源代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Diagnostics;

namespace CopyNoMatterWhat
{
    public class Program
    {
        private static DriveInfo di;
        private static int DELAY = 250;

        private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
        {
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs;

            TryAgain:
            try {
                dirs = dir.GetDirectories();
                // If the destination directory doesn't exist, create it.
                if (!Directory.Exists(destDirName)) {
                    Directory.CreateDirectory(destDirName);
                }

                // Get the files in the directory and copy them to the new location.
                FileInfo[] files = dir.GetFiles();
                foreach (FileInfo file in files) {
                    string temppath = Path.Combine(destDirName, file.Name);
                    if (!(new FileInfo(temppath).Exists)) copy(file.FullName, temppath, file.Length);
                }

                // If copying subdirectories, copy them and their contents to new location.
                if (copySubDirs) {
                    foreach (DirectoryInfo subdir in dirs) {
                        string temppath = Path.Combine(destDirName, subdir.Name);
                        DirectoryCopy(subdir.FullName, temppath, copySubDirs);
                    }
                }

            } catch (Exception ex) {
                Thread.Sleep(DELAY);
                Debug.WriteLine("Get Files Fail");
                goto TryAgain;
            }
            Debug.WriteLine("Done");
        }


        static void Main(string[] args)
        {
            di = new DriveInfo("f:");
            DirectoryCopy(@"F:\", "out", true);
        }

        private static void copy(string path, string name, long fileLength)
        {
            byte[] data = null;
            byte[] chunk = null;
            int bufferSize = 1024;


            Console.WriteLine("Copying " + path);

            FileStream fin;
            long index = 0;

            TryAgain1: try {
                fin = new FileStream(path, FileMode.Open);
                using (BinaryReader binReader = new BinaryReader(fin, new ASCIIEncoding())) {
                    while (data == null || (data.Length < fileLength)) {
                        binReader.BaseStream.Position = index;
                        chunk = binReader.ReadBytes(bufferSize);
                        if (data == null) data = chunk; else data = CombineByteArrays(data, chunk);
                        index = binReader.BaseStream.Position;
                        Console.Write("\r{0} / {1}", data.Length, fileLength);

                    }
                }
            } catch (IOException ex) {
                Debug.WriteLine("TA 1: " + ex.Message);
                Thread.Sleep(DELAY);
                goto TryAgain1;
            }

            File.WriteAllBytes(name, data);

            fin.Close();
            Console.Write(" ... OK");
            Console.WriteLine();
        }


        public static byte[] CombineByteArrays(byte[] first, byte[] second)
        {
            byte[] ret = new byte[first.Length + second.Length];
            Buffer.BlockCopy(first, 0, ret, 0, first.Length);
            Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
            return ret;
        }
    }
}

如果不知道对话框的外观,就很难准确猜出发生了什么。我的建议是禁用严重错误对话框:

[DllImport("kernel32.dll")]
static extern ErrorModes  SetErrorMode(ErrorModes uMode);

[Flags]
public enum ErrorModes : uint {
    SEM_FAILCRITICALERRORS     = 0x0001,
    SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
    SEM_NOGPFAULTERRORBOX      = 0x0002,
    SEM_NOOPENFILEERRORBOX     = 0x8000
}

...

var em = ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOOPENFILEERRORBOX;
SetErrorMode(SetErrorMode(em) | em);

(调用两次就是important)