调试利用 Vista API 中的 FileDialog 的 Visual Studio 2010 解决方案的问题

Posted

技术标签:

【中文标题】调试利用 Vista API 中的 FileDialog 的 Visual Studio 2010 解决方案的问题【英文标题】:Issue with debugging Visual Studio 2010 solution that utilises FileDialog from the Vista API 【发布时间】:2011-07-20 03:04:25 【问题描述】:

我有一个 WinForms C# Visual Studio 2008 (.NET 3.5) 解决方案,该解决方案将升级到 Visual Studio 2010(.NET 保持在 3.5 版)。该解决方案利用 Vista API 中的 FileDialog 有两个原因:

    在 Windows XP 中运行应用程序时,期望为用户提供一个 Windows XP 外观文件对话框。在 Windows Vista 和 7 中运行相同的应用程序时,文件对话框将具有 Vista 的外观。 更重要的是,我们的应用程序允许用户打开项目文件,该文件可以是本地文件(存储在用户的机器或 USB 设备上),也可以是服务器项目(托管在 MS SQL Server 中)。为此,我们使用 Vista API,因为我们可以访问文件类型下拉列表控件的事件处理程序。因此,实现方式是向用户显示打开文件对话框,当他们从文件类型下拉列表中选择“服务器”选项时,打开文件对话框关闭,并打开一个不同的对话框,允许用户选择他们希望连接的服务器和服务器项目。

在 Visual Studio 2008 中调试应用程序时,Vista API 没有问题。当解决方案升级到 Visual Studio 2010(在 Windows 7 中运行)时,用户尝试调试应用程序,并且用户希望访问 Vista API 打开文件对话框,应用程序崩溃并抛出 ArgumentException 并显示以下消息: “值不在预期范围内”。奇怪的是,当用户从 Visual Studio 2010 运行解决方案而不进行调试 (Ctrl + F5) 时,不会发生异常。 “违规”代码是:

internal void DoFolderChange(IFileDialog dialog)

    IShellItem ppsi = null;
    string ppszName = string.Empty;
    dialog.GetFolder(out ppsi);

    // Exception occurs here
    ppsi.GetDisplayName(NativeMethods.SIGDN.SIGDN_FILESYSPATH, out ppszName);
    OnFolderChange(ppszName);

我尝试了一些谷歌搜索,但无济于事。我有一个带有 Vista API 的示例 Visual Studio 2010 解决方案,这个问题也出现在这个解决方案中。可以从here 下载示例项目(ZIP 格式)。重现问题:

    在 Visual Studio 2010 中调试解决方案。 “Vista Api Demo”启动后,单击“对话框”选项卡。 从位于“对话框”选项卡右侧的“Vista Look”列中,单击“打开文件”按钮。 将出现一个对话框,其中包含“文件类型已更改为 1”消息。点击确定按钮。 观察到此时应用程序崩溃了,但 clsFileDialog.cs 中的 DoFolderChange(IFileDialog) 方法抛出了异常。

对于这篇冗长的帖子,我深表歉意,但我需要解释为什么需要 Vista API 文件对话框实现的整个背景。感谢您为解决此问题提供的任何帮助,因为我的开发团队正在考虑使用 Visual Studio 2010,我们开发人员不想为了绕过此问题而摆弄附加和分离调试器。

【问题讨论】:

【参考方案1】:

我遇到了这个问题,我想出了一个解决办法。

原代码:

OpenFileDialog fdlg = new OpenFileDialog();
string tempDirectoryName = @"..\SomeFolder\"; /* Note, the use of a relative directory*/
fdlg.InitialDirectory = tempDirectoryName ;
Nullable<bool> result = fdlg.ShowDialog();

然后我将其更改为:

OpenFileDialog fdlg = new OpenFileDialog();
string tempDirectoryName = @"..\SomeFolder\"; /* Note, the use of a relative directory*/
string massagedDirectoryName = System.IO.Path.**GetFullPath**(tempDirectoryName);
fdlg.InitialDirectory = massagedDirectoryName; /*Note, this is now the full folder name */
Nullable<bool> result = fdlg.ShowDialog();

它不再轰炸我了。

我的情况几乎相同。

我的场景:

代码是 VS2008 下的 WPF 应用程序并且可以工作。 (3.5 框架是目标框架) 我将代码向上转换为 VS2010(4.0 框架是目标框架)。然后出现了这个新问题。

两个代码库都在 Windows 7 x64 上运行。

.......

我的完整错误是:

 Value does not fall within the expected range.
    at MS.Internal.Interop.HRESULT.ThrowIfFailed(String message)
    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.CommonDialog.ShowDialog()

【讨论】:

感谢您的回复 granadaCoder。老实说,我已经有一段时间没有研究这个问题了,但是我的一位同事也找到了解决我问题的方法。虽然我还没有看到他修复的确切性质,但他发现代码中有我们没有使用的事件,所以他取消了这些事件的注册并且没有发生崩溃。当我下次有机会时,我会看看我同事的解决方案以及你的解决方案。再次感谢!

以上是关于调试利用 Vista API 中的 FileDialog 的 Visual Studio 2010 解决方案的问题的主要内容,如果未能解决你的问题,请参考以下文章

Vista 不直接支持WinDBG内核调试

XP/Vista 的音量(平衡)控制

Windows Vista 下的指针稳定性

使用 Debugger.Break() 将调试器附加到 Vista 或 Windows 7 上正在运行的进程

NUnit 不能在 Visual Studio 2003 中的 Vista x64 上运行

CLR 调试概述