Winapi Windows7中的GetOpenFilename api调用赢得';我不允许直接访问我的文档

Winapi Windows7中的GetOpenFilename api调用赢得';我不允许直接访问我的文档,winapi,ms-access,windows-7,Winapi,Ms Access,Windows 7,在我的许多Access(2002)程序中,我使用comdlg32.dll中的GetOpenFileNameA和GetSaveFileNameA函数。我经常将初始目录设置为用户的“我的文档”文件夹(使用shell32中对SHGetSpecialFolderLocation和SHGetPathFromIDListA的调用)。这一切在Windows XP下都可以正常工作 但是,我最近切换到Windows 7作为我的开发环境,并收到以下错误消息: 无法使用打开此位置 这个节目。请换一种 地点 我用来获取

在我的许多Access(2002)程序中,我使用comdlg32.dll中的GetOpenFileNameA和GetSaveFileNameA函数。我经常将初始目录设置为用户的“我的文档”文件夹(使用shell32中对SHGetSpecialFolderLocation和SHGetPathFromIDListA的调用)。这一切在Windows XP下都可以正常工作

但是,我最近切换到Windows 7作为我的开发环境,并收到以下错误消息:

无法使用打开此位置 这个节目。请换一种 地点

我用来获取“我的文档”位置的函数是返回正确的文件夹。然而,即使我将该目录位置硬编码到GetOpenFileNameA调用中,我仍然会得到错误

我看到了这篇文章:但是,即使将它改为使用Access而不是Excel,我也没有运气

编辑:突然间,这对我来说不再是问题。我怀疑windows更新解决了这个问题。有人知道这是真是假吗


编辑:事实证明这仍然是个问题。此外,如果它有助于排除故障,我发现我收到了任何特殊文件夹位置(我的音乐、我的文档等)的此错误消息。此外,如果我将My Music文件夹的位置更改为,例如C:\Test,则当我尝试打开文件夹C:\Test时,会收到此消息,而文件夹C:\Users\Mike\Music(My Music的原始位置)会顺利打开。

Windows 7添加了“库”的概念,它基本上是一个虚拟文件夹,包含至少两个实际子目录的内容。它使用库的一个地方是“我的文档”文件夹,该文件夹(至少在默认情况下)是一个库,其中包括用户的文档目录(“c:\users\Where\Documents”)和公共文档目录(“c:\users\public\Documents”)

因此,您使用的基本方法根本无法工作——没有表示Documents文件夹的路径。Documents文件夹需要由PIDL指定,而不是由路径指定

编辑:如果不能打开C:\Up\\Us\Debug,还不清楚发生了什么。C++中的快速测试使用了类似于:

的代码。
OPENFILENAME data = {0};
wchar_t filename[256] = {0};

data.lpstrInitialDir = L"C:\\users\\jerry\\documents";
data.lStructSize = sizeof(data);
data.lpstrFile = filename;
data.nMaxFile = sizeof(filename);

GetOpenFileName(&data);

哦,没有必要指定初始路径——文档文件夹是默认路径。

我在原始问题中发布的链接()我将在这里进行总结。要修复此行为,您需要删除所有受影响程序的shell兼容性注册表项中的STRIPFOLDERBIT标志

请记住(这让我很长时间都感到困惑)如果您有64位窗口,32位程序会在一个特殊的注册表部分中有条目。下面是一些快速而肮脏的方法:

将以下键的STRIPFOLDERBIT重命名为xSTRIPFOLDERBIT(如适用):

HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\excel.exe HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msaccess.exe HKEY\U LOCAL\U MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\excel.exe HKEY\U LOCAL\U MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msaccess.exe


除了我用来获取“My Documents”文件夹的函数调用返回一个实际路径(“C:\Users\Mike\Documents”)。如果我以“C:\Users\Mike”作为初始目录调用GetOpenFileName,它将很好地打开到该目录中;如果用“C:\Users\Mike\Documents\SomeSubFolder”调用它“作为初始目录,它也可以工作。当我用“C:\Users\Mike\Documents”调用它时,它就会弹出错误消息。我可以担心将来会合并新的Win7库概念,因为现在我只希望对话框打开文件夹“C:\Users\Mike\Documents”而不会出错。如果我将初始路径留空,我避免了错误消息,但它仍然拒绝在Documents文件夹中打开。似乎Microsoft强烈建议在Windows Vista和更高版本()中使用不同的api调用(IFileOpenDialog vs GetOpenFileName)。我不完全确定如何从vba接到那个电话。我可能会单独问这个问题。我仍然不确定为什么我不能在对话框中使用显式路径,但似乎解决方案应该是:1)检查当前的windows版本;2) 如果Vista或更高版本使用新对话框。@mwolfe02:Hmm…听起来VBA好像在幕后做什么,所以您试图提供给GetOpenFileName的内容与它接收到的内容不太一样。在这种情况下,你可能是正确的,你唯一能做的就是回避它(或者在一个DLL中创建一个像C++一样的THONK),并调用VBA而不是“调整”你的参数)。我原来的问题似乎已经解决了,但是这里有一些很好的信息。所以我将这个答案标记为已接受。相关问题发布在这里:为什么你要强制初始目录为MyDocs?如果您保存了用户以前所做的选择,或者您的应用程序能够根据某些状态猜测有用的目录,则只应强制使用初始目录。ComDlg32也会尝试为您记住一些信息。MyDocs无论如何都是默认的回退,因此没有必要强制它。@Anders:主要是为了在从Access导出信息时为用户提供一个一致的起点。我的用户经常使用多址应用程序。通常,他们有一个文件夹结构,用于根据导出的Access应用程序将导出的信息保存在不同的位置。据我所知,ComDlg32根据进程可执行文件记住信息。不幸的是,七个完全不同的访问应用程序都将msaccess.exe作为进程可执行文件。新的IFileDialog实际上有一个SetClientGUID属性