如何摆脱驱动器没有准备消息框?

时间:2017-09-28 11:01:51

标签: c# winapi ioexception

我有一个故障的USB记忆棒,一直保持连接和断开状态,间隔时间大约为500毫秒,以保存文件,我写了一个逐字节复制文件的软件,每当USB记忆棒断开连接,软件等待然后一次又一次地尝试。

它有效,但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;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在不知道对话框的样子的情况下,很难准确猜出发生了什么。我的建议是禁用关键错误对话框:

[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