windows GetOpenFileName 在 64 位中失败,但在 32 位中有效?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4982680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GetOpenFileName fails in 64 bit, but works in 32Bit?
提问by rwb
I have the following code, I use to Open a File Open Dialog using Win32 API. It works fine in 32bit, but fails when I use in a 64bit (In a DLL). What am I doing wrong?
我有以下代码,用于使用 Win32 API 打开文件打开对话框。它在 32 位上运行良好,但在 64 位(在 DLL 中)中使用时失败。我究竟做错了什么?
char Filestring[256];
Filter = "OBJ filesOPENFILENAME opf={0};
opf.lStructSize = sizeof(OPENFILENAME);
opf.hwndOwner = mainHWND;
opf.lpstrFilter = Filter;
opf.nFilterIndex = 1L;
opf.lpstrFile = Filestring;
opf.lpstrFile[0] = 'char Filestring[MAX_PATH] = "ZeroMemory(&opf, sizeof(opf));
";
OPENFILENAME opf={0};
opf.lStructSize = sizeof(OPENFILENAME);
opf.lpstrFile = Filestring;
opf.nMaxFile = MAX_PATH;
GetOpenFileName(&opf);
';
opf.nMaxFile = 256;
opf.lpstrInitialDir = Path;
opf.lpstrTitle = "Open Obj File";
opf.lpstrDefExt = "*.*";
opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
*.objif( RPC_E_CHANGED_MODE == CoInitialize(NULL) )
ASSERT(FALSE); // MTA Apartment found
CoUnitialize()
#ifdef _WIN64
#pragma pack( push )
#pragma pack( 16 )
#include "Commdlg.h"
#pragma pack( pop )
#else
#include "Commdlg.h"
#endif // _WIN64
";
char* returnstring = NULL;
OPENFILENAME opf;
opf.hwndOwner = mainHWND;
opf.lpstrFilter = Filter;
opf.lpstrCustomFilter = 0;
opf.nMaxCustFilter = 0L;
opf.nFilterIndex = 1L;
opf.lpstrFile = Filestring;
opf.lpstrFile[0] = '##代码##';
opf.nMaxFile = 256;
opf.lpstrFileTitle = 0;
opf.nMaxFileTitle=50;
opf.lpstrInitialDir = Path;
opf.lpstrTitle = "Open Obj File";
opf.nFileOffset = 0;
opf.nFileExtension = 0;
opf.lpstrDefExt = "*.*";
opf.lpfnHook = NULL;
opf.lCustData = 0;
opf.Flags = (OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT) & ~OFN_ALLOWMULTISELECT;
opf.lStructSize = sizeof(OPENFILENAME);
if(GetOpenFileName(&opf))
{
returnstring = opf.lpstrFile;
if (returnstring) {
result = returnstring;
}
}
EDIT: By failing, I meant that the Open File Dialog doesn't show up. The code still returns zero without any errors.
编辑:失败,我的意思是打开文件对话框没有出现。代码仍然返回零,没有任何错误。
EDIT 2: I have called CommDlgExtendedError() and it returned 1. From the MSDN reference, does it mean the dialog has invalid lStructSize? I have checked the sizeof(OPENFILENAME)
and it returned 140 bytes.
编辑 2:我调用了 CommDlgExtendedError() 并返回了 1。从 MSDN 参考中,这是否意味着对话框的 lStructSize 无效?我检查了sizeof(OPENFILENAME)
它,它返回了 140 个字节。
UPDATE: In my Project Settings, Under Code Generation the "Struct Member Alignment" is set to 4 Bytes(/Zp4). I changed this to default and it magically worked. Look for the answers and their comments below for more information.
更新:在我的项目设置中,在代码生成下,“结构成员对齐”设置为 4 字节(/Zp4)。我将其更改为默认值,它神奇地起作用了。在下面寻找答案和他们的评论以获取更多信息。
回答by David Heffernan
You aren't initialising lpTemplateName
and so it contains random stack noise. This in turn will lead to 'hInstance` being references which also contains stack noise.
您没有初始化lpTemplateName
,因此它包含随机堆栈噪声。这反过来将导致 'hInstance' 成为也包含堆栈噪声的引用。
When calling a function like this you should first of all zero out the struct and only fill in the fields that are non-zero. Something like this:
在调用这样的函数时,您应该首先将结构清零,并且只填充非零的字段。像这样的东西:
##代码##There was no need to exclude OFN_ALLOWMULTISELECT
explicitly since you were not including it in the first place!
没有必要OFN_ALLOWMULTISELECT
明确排除,因为您一开始就没有包括它!
EDIT
编辑
You state in a comment that this doesn't work. Calling CommDlgExtendedError
is a good idea and should tell you why it fails.
您在评论中声明这不起作用。打电话CommDlgExtendedError
是个好主意,应该告诉你为什么会失败。
You could also try to run the minimal possible GetOpenFileName
which is this:
你也可以尝试运行最小的可能GetOpenFileName
是这样的:
回答by Dominique Massiot
I have the very same problem and a partial solution : + the simple following simple example (proposed abobe) was not working in x64 mode. + I changed the complie option "struct Member Alignment" from 1byte /Zp1 to default which solved this problem (by introducing others !!!)
我有同样的问题和部分解决方案:+ 下面的简单示例(建议 abobe)在 x64 模式下不起作用。+ 我将 complie 选项“struct Member Alignment”从 1byte /Zp1 更改为默认值,解决了这个问题(通过引入其他人!!!)
char Filestring[MAX_PATH] = "\0"; OPENFILENAME opf={0}; opf.lStructSize = sizeof(OPENFILENAME); opf.lpstrFile = Filestring; opf.nMaxFile = MAX_PATH; GetOpenFileName(&opf);
字符文件串[MAX_PATH] = "\0"; OPENFILENAME opf={0}; opf.lStructSize = sizeof(OPENFILENAME); opf.lpstrFile = 文件字符串;opf.nMaxFile = MAX_PATH; GetOpenFileName(&opf);
回答by Alois Kraus
To find out more you should call CommDlgExtendedErrorto get the error code what went wrong. Besides this I would initialize all member of the struct to 0 with
要了解更多信息,您应该调用CommDlgExtendedError获取错误代码。除此之外,我会将结构的所有成员初始化为 0
##代码##Since the file open dialog is in reality a COM component it could be worth to check out if your thread apartment state is different under 64 bit.
由于文件打开对话框实际上是一个 COM 组件,因此有必要检查一下您的线程单元状态在 64 位下是否不同。
##代码##Yours, Alois Kraus
你的,阿洛伊斯·克劳斯
回答by Nick van Esch
As a note in Microsoft Office 2010 64-bit we gave up and used the internal wrappers as the structure turned into 140 bytes and we were not sure how to change alignment.
作为 Microsoft Office 2010 64 位的说明,我们放弃并使用内部包装器,因为结构变成了 140 字节,我们不确定如何更改对齐方式。
Application.GetOpenFilename(FileFilter, FilterIndex, Title, ButtonText, MultiSelect) and Application.GetSaveAsFilename(InitialFilename, FileFilter, FilterIndex, Title, ButtonText)
Application.GetOpenFilename(FileFilter, FilterIndex, Title, ButtonText, MultiSelect) 和 Application.GetSaveAsFilename(InitialFilename, FileFilter, FilterIndex, Title, ButtonText)
http://msdn.microsoft.com/en-us/library/ff834966.aspx
http://msdn.microsoft.com/en-us/library/ff834966.aspx
Needless to say we think all individuals with fairly heavy applications in Excel should start considering other options as maintaining future versions across multiple clients and platforms may just be... insane!
不用说,我们认为所有在 Excel 中使用相当繁重的应用程序的人都应该开始考虑其他选项,因为在多个客户端和平台上维护未来的版本可能只是......疯了!
回答by GeneralHQ
I managed to get around this problem by setting the packing appropriately before including the header file. That way, for the purpose of this one function, we were using the 'default' 16 byte alignment, but did not have to change the packing alignment for the rest of our program:
我设法通过在包含头文件之前适当地设置打包来解决这个问题。这样,为了这个函数的目的,我们使用了“默认”的 16 字节对齐方式,但不必更改程序其余部分的包装对齐方式:
##代码##