【发布时间】:2021-12-20 04:45:41
【问题描述】:
//注1:有些本地化消息是直接翻译的,所以在你的电脑上可能会有所不同,但意思是一样的。
//注2:本程序是在.NET Framework 4.5, Release, x64下构建的。
我正在设计一个可以静默自动备份闪存驱动器的程序。
在复制方法中,我使用如下代码:
//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}----------");
}
}
查看代码后,我们想象一个情况:
用户插入 SD 卡读卡器。复制文件时,SD 卡以某种方式断开连接,但读卡器仍然插入(可能是因为接触不良)。
每当您插入没有卡的读卡器时,Windows 资源管理器都会警告您“请将磁盘插入 'SD 卡 (E:\)'。”
但是当这种情况发生在这个程序上时,该方法并没有立即抛出异常。相反,它显示了一个消息框,例如:
|---USBBackup.exe - 无磁盘|
|驱动器中没有磁盘。请将磁盘插入驱动器 E: |
|取消| |重试| |继续|
如果我点击了取消按钮(或继续按钮?)然后会抛出异常:
System.IO.IOException:驱动器中的软盘不正确。
将 %2(卷序列号:%3)插入驱动器 %1。
在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
在 System.IO.File.InternalCopy(字符串源文件名,字符串 destFileName,布尔覆盖,布尔检查主机)
在 USBBackup.Form1.CopyMoveDisk(String fromdir, String todir, Int32 times)
//注意 3:不知何故,消息框不会显示在我的 Windows 10 虚拟机上。
//相反,它会直接抛出异常:
System.IO.IOException:设备未准备好。
在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
在 System.IO.File.InternalCopy(字符串源文件名,字符串 destFileName,布尔覆盖,布尔检查主机)
在 USBBackup.Form1.CopyMoveDisk(String fromdir, String todir, Int32 times)
//但它显示在我的 Windows 7 虚拟机上。
//或者可能是因为我在Win10 VM上安装了.Net Framework 4.8,但在Win7 VM上安装了4.5。
既然我不想让这个程序打扰用户,我该怎么做才能避免显示消息框?
【问题讨论】:
-
是的。由于 try-catch 块,我认为它不应该显示消息框。这不是正常的 JIT 调试消息框。请再次阅读整篇文章。
-
问题解决了。其实我希望你写一个正式的答案。非常感谢。