简体   繁体   English

我可以阻止 IOException 打开消息框吗?

[英]Can I prevent the IOException from opening the messagebox?

//Note1: some localized message was translated directly, so it will probably be diffferent on your computer, but the meaning is the same. //注1:有些本地化的消息是直接翻译的,所以在你的电脑上可能会有所不同,但意思是一样的。
//Note2: this program is build under .NET Framework 4.5, Release, x64. //注2:本程序是在.NET Framework 4.5, Release, x64 下构建的。
I am designing a program that can backup the flash drive silently and automatically.我正在设计一个可以静默自动备份闪存驱动器的程序。
In the copy method, I use code like:在复制方法中,我使用如下代码:

        //Note: the Cout(string) method is a logging method, acturally equivalent to Console.WriteLine(string)
        public void CopyMoveDisk(string fromdir, string todir, int times = 0)
        {
            try
            {
                if (PauseToken)
                {
                    Cout("Copy: paused");
                    STTimer t = new STTimer(o => { CopyMoveDisk(fromdir, todir, times); }, null, 5000, -1);
                    Thread.Sleep(6000);
                    t.Dispose();
                    return;
                }
                else
                {
                    try
                    {
                        if (!Directory.Exists(todir))
                            Directory.CreateDirectory(todir);
                        var filessmall = from f in Directory.GetFiles(fromdir)
                                         where new FileInfo(f).Length <= 100 * Math.Pow(2, 20)
                                         orderby new FileInfo(f).Length
                                         select f;
                        var filesbig = from f in Directory.GetFiles(fromdir)
                                       where new FileInfo(f).Length > 100 * Math.Pow(2, 20)
                                       orderby new FileInfo(f).Length
                                       select f;

                        Cout("Copy: small file region");
                        // Copy the small files (<= 100MiB)
                        foreach (string file in filessmall)
                        {
                            s.CopyingFile = todir + Path.GetFileName(file);
                            if (File.Exists(todir + Path.GetFileName(file)))
                            {
                                if (new FileInfo(file).Length != new FileInfo(todir + Path.GetFileName(file)).Length)
                                {
                                    Cout($"Copy true: {file} => {todir + Path.GetFileName(file)}: Length = {new FileInfo(todir + Path.GetFileName(file)).Length}");
                                    File.Copy(file, todir + Path.GetFileName(file), true);
                                }
                                else
                                {
                                    Cout($"Exist: {file} => {todir + Path.GetFileName(file)}: Length = {new FileInfo(todir + Path.GetFileName(file)).Length}");
                                }
                            }
                            else
                            {
                                Cout($"Copy: {file} => {todir + Path.GetFileName(file)}");
                                File.Copy(file, todir + Path.GetFileName(file), true);
                            }
                            s.CopyingFile = string.Empty;
                        }
                        Cout("Copy: small file region end");

                        Cout($"Copy: directory region: {times} time(s)");
                        // Copy the sub directories
                        foreach (string sub in Directory.GetDirectories(fromdir))
                        {
                            if (!sub.Contains("System Volume Information"))
                            {
                                Cout($"Copy: {sub + "\\"} => {todir + Path.GetFileName(sub) + "\\"}");
                                CopyMoveDisk(sub + "\\", todir + Path.GetFileName(sub) + "\\", times + 1);
                            }
                        }
                        Cout($"Copy: directory region end: {times} time(s)");

                        Cout("Copy: big file region");
                        // Copy the big files (> 100MiB)
                        foreach (string file in filesbig)
                        {
                            s.CopyingFile = todir + Path.GetFileName(file);
                            if (File.Exists(todir + Path.GetFileName(file)))
                            {
                                if (new FileInfo(file).Length != new FileInfo(todir + Path.GetFileName(file)).Length)
                                {
                                    Cout($"Copy true: {file} => {todir + Path.GetFileName(file)}: Length = {new FileInfo(todir + Path.GetFileName(file)).Length}");
                                    File.Copy(file, todir + Path.GetFileName(file), true);
                                }
                                else
                                {
                                    Cout($"Exist: {file} => {todir + Path.GetFileName(file)}: Length = {new FileInfo(todir + Path.GetFileName(file)).Length}");
                                }
                            }
                            else
                            {
                                Cout($"Copy: {file} => {todir + Path.GetFileName(file)}");
                                File.Copy(file, todir + Path.GetFileName(file), true);
                            }
                            s.CopyingFile = string.Empty;
                        }
                        Cout("Copy: big file region end");
                    }
                    catch (Exception ex)
                    {
                        Cout($"Copy: -----Exception {ex} {Environment.NewLine}----------");
                    }
                }
            }
            catch (Exception ex)
            {
                Cout($"Copy: -----Exception {ex} {Environment.NewLine}{s}{Environment.NewLine}----------");
            }
        }

After viewing the code, let's imagine a situation:查看代码后,我们来设想一种情况:
The user insert a SD Card reader.用户插入 SD 卡读卡器。 When the files are copying, the SD Card somehow become disconnected but the reader remains inserted (probably because of poor contact).复制文件时,SD 卡不知何故断开连接,但读卡器仍然插入(可能是因为接触不良)。
Whenever you inserted a Card reader without a card, the Windows Explorer will warn you with "Please insert the disk into 'SD Card (E:\\)'."每当您在没有卡的情况下插入读卡器时,Windows 资源管理器都会警告您“请将磁盘插入‘SD 卡 (E:\\)’”。
But when this situation happened to be on this program, the method didn't throw the exception immerdiately.但是当这种情况发生在这个程序上时,该方法并没有立即抛出异常。 Instead, it showed a messagebox like:相反,它显示了一个消息框,如:

|---USBBackup.exe - No disks| |---USBBackup.exe - 没有磁盘|
| | There're no disks in the drive.驱动器中没有磁盘。 Please insert the disk in the drive E: |请将磁盘插入驱动器 E: |
|Cancel| |取消| |Retry| |重试| |Continue| |继续|

If I clicked the cancel button (or the continue button?) then will throw an exception:如果我单击取消按钮(或继续按钮?),则会抛出异常:

System.IO.IOException: The floppy disk in the drive is not correct. System.IO.IOException: 驱动器中的软盘不正确。
Insert %2 (volume serial number: %3) to drive %1.将 %2(卷序列号:%3)插入驱动器 %1。
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)在 System.IO.__Error.WinIOError(Int32 errorCode, String mightFullPath)
at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)在 System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)
at USBBackup.Form1.CopyMoveDisk(String fromdir, String todir, Int32 times)在 USBBackup.Form1.CopyMoveDisk(String fromdir, String todir, Int32 times)

//Note3: Somehow the messagebox won't show on my Windows 10 VM. //注3:不知何故,消息框不会显示在我的 Windows 10 虚拟机上。
//Instead, it will throw a excetion directly: //相反,它会直接抛出异常:

System.IO.IOException: The device is not ready. System.IO.IOException: 设备未准备好。
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)在 System.IO.__Error.WinIOError(Int32 errorCode, String mightFullPath)
at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)在 System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)
at USBBackup.Form1.CopyMoveDisk(String fromdir, String todir, Int32 times)在 USBBackup.Form1.CopyMoveDisk(String fromdir, String todir, Int32 times)

//But it showed on my Windows 7 VM. //但它显示在我的 Windows 7 VM 上。
//Or probably because I installed the .Net Framework 4.8 on the Win10 VM, but 4.5 on the Win7 VM. //或者可能是因为我在Win10 VM上安装了.Net Framework 4.8,但在Win7 VM上安装了4.5。
Now that I don't want this program to disturb the user, what can I do to avoid showing the messagebox?既然我不想让这个程序打扰用户,我该怎么做才能避免显示消息框?

You will need to call the SetErrorMode API with SEM_FAILCRITICALERRORS to disable the system messageboxes and set it back afterwards.您将需要使用SEM_FAILCRITICALERRORS调用SetErrorMode API 以禁用系统消息框,然后SEM_FAILCRITICALERRORS其设置回来。
Create an internal class NativeMethods :创建一个内部类NativeMethods

internal static class NativeMethods
{
    [DllImport("kernel32.dll")]
    internal static extern ErrorModes SetErrorMode(ErrorModes uMode);

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

An example usage:示例用法:

void BackupFiles()
{
    var prevMode = NativeMethods.SetErrorMode(NativeMethods.SEM_FAILCRITICALERRORS);
    try
    {
        // attempt to copy the files
        // from the removable device
    }
    finally
    {
        NativeMethods.SetErrorMode(prevMode);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM