[英]Exception when calling ShowDialog on a Microsoft.Win32.OpenFileDialog
I'm getting reports from a WPF application that is deployed in the field that the following ArgumentException is being thrown when attempting to display an Open File Dialog. 我从WPF应用程序获取报告,该应用程序部署在字段中,在尝试显示打开文件对话框时引发以下ArgumentException。
Exception Message: Value does not fall within the expected range.
Method Information: MS.Internal.AppModel.IShellItem2 GetShellItemForPath(System.String)
Exception Source: PresentationFramework
Stack Trace
at MS.Internal.AppModel.ShellUtil.GetShellItemForPath(String path)
at Microsoft.Win32.FileDialog.PrepareVistaDialog(IFileDialog dialog)
at Microsoft.Win32.FileDialog.RunVistaDialog(IntPtr hwndOwner)
at Microsoft.Win32.FileDialog.RunDialog(IntPtr hwndOwner)
at Microsoft.Win32.CommonDialog.ShowDialog(Window owner)
...
The problem is that so far I haven't been able to replicate this in my development environment but I have received several reports from the field that this exception is occurring. 问题是到目前为止我还没有能够在我的开发环境中复制它,但是我收到了来自该领域的几个报告,说明这个例外正在发生。
Has anyone seen this before? 谁看过这个吗? And most importantly do you know the cause and/or a fix for it other than just simply putting a try/catch around it and instructing the user to try again whatever it is they were trying to do? 最重要的是你知道原因和/或修复它,除了简单地在它周围放一个try / catch并指示用户再试一次他们试图做的事情吗?
In response to a comment, this is the code that opens the dialog (and no, it was not a problem of checking the return type). 在回复注释时,这是打开对话框的代码(不,这不是检查返回类型的问题)。 The exception is thrown from within ShowDialog (see stack trace): 从ShowDialog中抛出异常(请参阅堆栈跟踪):
Nullable<bool> result = null;
var dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".txt";
dlg.Filter = "Text Files (.txt)|*.txt|All Files|*.*";
dlg.Title = "Open File";
dlg.Multiselect = false;
dlg.InitialDirectory = GetFolderFromConfig("folders.templates");
result = dlg.ShowDialog(Window.GetWindow(this));
if (result == true)
{
// Invokes another method here..
}
This issue can also occur with non-special directories, such as mapped network drives. 非特殊目录(例如映射的网络驱动器)也会发生此问题。 In my case, our %HOME%
environment variable points to a mapped network drive (Z:). 在我的例子中,我们的%HOME%
环境变量指向映射的网络驱动器(Z :)。 Thus the following code generates the same exception: 因此,以下代码生成相同的异常:
Nullable<bool> result = null;
var dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".txt";
dlg.Filter = "Text Files (.txt)|*.txt|All Files|*.*";
dlg.Title = "Open File";
dlg.Multiselect = false;
dlg.InitialDirectory = Environment.GetEnvironmentVariable("Home")+@"\.ssh"; // boom
result = dlg.ShowDialog(Window.GetWindow(this));
Solution: 解:
var dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".txt";
dlg.Filter = "Text Files (.txt)|*.txt|All Files|*.*";
dlg.Title = "Open File";
dlg.Multiselect = false;
dlg.InitialDirectory = System.IO.Path.GetFullPath(Environment.GetEnvironmentVariable("Home")+@"\.ssh"); // no boom
result = dlg.ShowDialog(Window.GetWindow(this));
This should really go to @Hans Passant as he pointed me in the right direction. 这应该真的去了@Hans Passant,因为他指出了我正确的方向。
It turns out the problem was trivial to replicate (and fix) on my development computer once I figured out what the problem really was. 事实证明,一旦我弄清楚问题究竟是什么,在我的开发计算机上复制(和修复)这个问题是微不足道的。 It turns out that the issue was indeed the InitialDirectory property being set to some odd value. 事实证明,问题确实是将InitialDirectory属性设置为某个奇数值。 in my case I was able to replicate the issue by setting InitialDirectory to "\\"; 在我的情况下,我能够通过将InitialDirectory设置为“\\”来复制该问题;
Here's the modified code to address the issue: 以下是解决此问题的修改后的代码:
try
{
result = dlg.ShowDialog(Window.GetWindow(this));
}
catch{
dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
result = dlg.ShowDialog(Window.GetWindow(this));
}
///<summary>
/// Tries to handle inability of user to access file dialog folder
/// by using other folder. Shows meaningful message to
/// user for action on failure.
///</summary>
private bool? ShowDialogSafe()
{
try
{
return dlg.ShowDialog(Window.GetWindow(this));
}
// reacts on rare case of bad default folder, filter only folder related excepions
catch (Exception handledEx) when (IsInitialDirectoryAccessError(handledEx))
{
var original = dlg.InitialDirectory;
var possible = Environment.GetFolderPath(Environment.SpecialFolder.Personal);// hope user has access to his own, may try Desktop
try
{
dlg.InitialDirectory = possible;
return FileDialog.ShowDialog(Window.GetWindow(this));
}
catch (Exception ex) when (IsInitialDirectoryAccessError(ex))
{
var message = string.Format("Failed to access directories '{0}' and '{1}'. Please contact system administrator.", original, possible);
throw new IOException(message, ex);
}
}
}
/// <summary>
/// see GetShellItemForPath(string path) http://referencesource.microsoft.com/#PresentationFramework/src/Framework/MS/Internal/AppModel/ShellProvider.cs,f0a8bc5f6e7b1503,references
/// System.IO.FileNotFoundException: 'The network name cannot be found. (Exception from HRESULT: 0x80070043)' - no such share exsits
/// "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"} System.UnauthorizedAccessException - folder is forbidden
/// System.ArgumentException: 'Value does not fall within the expected range.' - badly formatted path
/// </summary>
/// <param name="handledEx"></param>
/// <returns></returns>
private static bool IsInitialDirectoryAccessError(Exception handledEx)
=> handledEx is IOException || handledEx is UnauthorizedAccessException || handledEx is ArgumentException;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.