6

我从部署在字段中的 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)
  ...

问题是,到目前为止,我还无法在我的开发环境中复制它,但我收到了来自该领域的几份报告,表明此异常正在发生。

有没有人见过这个?最重要的是,您是否知道原因和/或解决方法,而不仅仅是简单地在它周围放置一个 try/catch 并指示用户再次尝试他们正在尝试做的任何事情?

作为对评论的回应,这是打开对话框的代码(不,这不是检查返回类型的问题)。从 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..
}
4

3 回答 3

7

非特殊目录(例如映射的网络驱动器)也可能出现此问题。在我的例子中,我们的%HOME%环境变量指向一个映射的网络驱动器 (Z:)。因此,以下代码会生成相同的异常:

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));

解决方案:

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));
于 2013-09-23T18:30:01.377 回答
3

这真的应该归功于@Hans Passant,因为他为我指明了正确的方向。

事实证明,一旦我弄清楚问题的真正原因,在我的开发计算机上复制(和修复)这个问题是微不足道的。事实证明,问题确实是 InitialDirectory 属性被设置为某个奇怪的值。就我而言,我可以通过将 InitialDirectory 设置为“\”来复制问题;

这是解决该问题的修改后的代码:

 try
 {
     result = dlg.ShowDialog(Window.GetWindow(this));
 }
 catch{
     dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
     result = dlg.ShowDialog(Window.GetWindow(this));
 }
于 2013-01-07T23:08:54.333 回答
0
      ///<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;
于 2018-01-15T08:25:20.807 回答