64位Windows文件打开

发布于 2024-11-27 13:54:01 字数 648 浏览 0 评论 0原文

我正在尝试使用对话框来打开程序中的文件。这在 32 位系统上完美运行,但是当我尝试在 64 位系统上使用它时,它无法打开该文件。我发现如果尝试打开的文件与我的程序位于同一目录中,则它可以正常工作。但是,尝试从另一个文件夹打开文件根本不起作用。

因此,我尝试将文件复制到程序文件夹中。这在 32 位系统上也可以正常工作,但在 64 位系统上根本不起作用。有什么想法吗?

char cwdl[500];
getcwd(cwdl,500);
string mystring = string(cwdl);

CFileDialog fileDlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, "All Files (*.*)|*.*||", this);
fileDlg.m_ofn.lpstrTitle = "Select New File";
if( fileDlg.DoModal() == IDOK)
{

    CString newFile= fileDlg.GetFileName();
    mystring+="\\"+newFile;
    const char * newLoc = mystring.c_str(); 
    CopyFile(newFile,newLoc,true);

这只是代码片段。

I'm trying to use a dialog box to open a file in my program. This works perfectly on a 32 bit system, but when I try to use it on 64 bit it is unable to open the file. I've figured out that if the file trying to be opened is in the same directory as my program, it works fine. Trying to open a file from another folder, however, doesn't work at all.

So, I tried to copy the file to the program folder. This also works fine on 32 bit but doesn't work at all on a 64 system. Any thoughts why?

char cwdl[500];
getcwd(cwdl,500);
string mystring = string(cwdl);

CFileDialog fileDlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, "All Files (*.*)|*.*||", this);
fileDlg.m_ofn.lpstrTitle = "Select New File";
if( fileDlg.DoModal() == IDOK)
{

    CString newFile= fileDlg.GetFileName();
    mystring+="\\"+newFile;
    const char * newLoc = mystring.c_str(); 
    CopyFile(newFile,newLoc,true);

this is just a snippet of the code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

诗酒趁年少 2024-12-04 13:54:01

UAC 和文件系统重定向既相关又不同。

用户帐户控制是基于权限的安全性,可防止未经授权的用户更改您的文件系统或执行可能影响其他用户的应用程序。该提示允许您通过临时提供管理员权限来覆盖安全性(如果这是您的意图)。

文件系统重定向是为了通过镜像 32 位系统文件夹和注册表来向后兼容 32 位应用程序。事实上,如果导致 UAC 启动重定向的操作没有发生,那么在这种情况下它将始终尝试使用该文件的 64 位版本。除非您明确指定重定向目录或以管理员权限运行32位应用程序来绕过UAC。

好吧,这就是说您正在使用相对路径,因此它将在当前目录中查找该进程的文件。如果它被编译为 32 位进程,则由于上述重定向,在具有不同体系结构的系统上运行它可能不会按预期运行。

您可以使用 GetCurrentDirectory Windows API 来查看当前进程正在使用哪个目录并验证它是否是您所期望的。如果没有,你有几个选择。

  • 最简单的方法是使用完全限定的文件路径。
  • 您还可以有两个构建,一个针对您打算部署的每个架构。毕竟,如果您使用的是 64 位系统,您不妨部署 64 位应用程序。
  • 更复杂的选项是子类化 CFileDialog 并通过在构造函数中调用 Wow64DisableWow64FsRedirection 和在析构函数中调用 Wow64RevertWow64FsRedirection 来禁用重定向。然而,这是一个系统设置,因此您可能会因在 64 位 Windows 上强制使用 32 位应用程序而遇到新问题。

可能还有很多其他选择,因为通常有很多方法可以给猫剥皮。然而,第一步是放置一些调试代码,并使用 GetCurrentDirectory 验证或消除重定向作为罪魁祸首

UAC and file system redirection are related yet different.

User account control is a permissions based security to prevent unauthorized users from changing your file system or executing applications which may affect other users. The prompt allows you to override the security by providing administrator privileges temporarily if that was your intent.

File system redirection is to allow backwards compatibility with 32bit applications by having a mirrored 32bit system folders and registry. In fact if the action causes UAC to kick in redirection does not occur it will always try to use the 64bit version of the file in that case. Unless you specify the redirection directory explicitly or run the 32bit application with administrator privileges to bypass UAC.

Ok that said you are using a relative path so it will look for the file in the current directory for the process. If it's compiled as 32 bit process running it on systems with different architectures may not behave as expected due to aforementioned redirection.

You can use GetCurrentDirectory windows API to see what directory the current process is using and verify it is what you expected. If not you have a few options.

  • The easiest would be to use fully qualified file paths.
  • You could also have two builds one targeted for each architecture you intend to deploy on. After all if you're on a 64bit system you might as well deploy 64bit applications.
  • A more involved option would be to subclass CFileDialog and disable redirection by calling Wow64DisableWow64FsRedirection in the constructor and Wow64RevertWow64FsRedirection in the desctructor. However this is meant to be a system setting so you may get new problems by forcing your 32bit application on 64bit windows.

There are probably plenty of other options as well since there is usually many ways to skin a cat. However the first step is to put some debug code in place and verify or eliminate redirection as a culprit with GetCurrentDirectory

似最初 2024-12-04 13:54:01

也许只有我这么认为,但我看到了一个奇怪的结果:在 64 位模式下,用于存储路径位置的缓冲区的前四个字节用零填充。

char wk[_MAX_PATH];
char *ret = _getcwd(wk, _MAX_PATH);  // wk = "\0\0\0\0C:\\MyFolder\\..."
                                     // ret = "C:\\MyFolder\\..."

返回值 OTOH 是正确的。 “ret”指向wk + ​​4;

在 32 位模式下,没有前导零,路径从第一个字节开始。注意:这是一个多字节应用程序,而不是 Unicode。

我使用的是 Visual Studio 2010 (10.0.40219.1 SP1Rel)。

无论如何,如果您得到相同的结果,那就可以解释为什么您的示例不起作用。您可能会说(仅限 64 位模式):

string mystring = string(cwdl + 4);   // 64-bit only

奇怪还是什么?

编辑:似乎是对齐问题。如果 _getcwd 位于单独的函数中,则工作正常。

Maybe it's just me, but I'm seeing a strange result: in 64-bit mode, the first four bytes of the buffer used to store the location of the path, are filled with zeros.

char wk[_MAX_PATH];
char *ret = _getcwd(wk, _MAX_PATH);  // wk = "\0\0\0\0C:\\MyFolder\\..."
                                     // ret = "C:\\MyFolder\\..."

The return value OTOH is correct. "ret" points to wk + 4;

In 32-bit mode, there are no leading zeros, the path starts at the first byte. Note: this is a Multi-byte app, not Unicode.

I'm using Visual Studio 2010 (10.0.40219.1 SP1Rel).

Anyway, if you're getting the same result, that would explain why your example doesn't work. You would have to say (in 64-bit mode only):

string mystring = string(cwdl + 4);   // 64-bit only

Weird or What?

Edit: Seems to be an alignment problem. Works OK if the _getcwd is in a separate function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文