shell32.dll: GetOpenFileName新线程期间的访问冲突



GetOpenFileName失败,访问违反。文件必须在桌面,并有很长的名称。只有在第一次成功打开文件后才会出现问题。当鼠标光标悬停在即将显示工具提示的文件上时,出现问题。

见下面的答案。我把原来的问题描述留在下面。

Mike d .

=======================

我使用GetOpenFileName。有时在shell32内部会出现访问冲突。第一次使用该代码时不会发生违规,通常需要尝试五到六次。另外,如果在打开文件窗口弹出后,在1秒或2秒内选择文件,则不会发生违规。此外,调试时显示的调用堆栈不包括我的任何代码。这就好像某个独立的线程正在醒来做某事。

任何见解,我可能会调试这个非常感谢!

我制作了一个显示相同行为的"hello"world应用程序。然而,在失败之前,它需要更多的尝试。似乎还必须在它失败之前切换目录。

GOFN是从为此目的创建的线程中完成的。下面是"hello world"应用程序的代码。

typedef struct 
{
public:
    HWND        hWnd;
    HINSTANCE   hInst;
} def_params, *p_params;
DWORD WINAPI ReadLogFile_DataRecorderThread (PVOID pvoid);
void ReadLogFile_DataRecorder (HWND hWnd, HINSTANCE hInst)  // ***************************
{
    static def_params Params;
    Params.hWnd = hWnd;
    Params.hInst = hInst;
    HANDLE T = CreateThread (NULL,0,ReadLogFile_DataRecorderThread,&Params,0,NULL);
    CloseHandle (T);
    return;
}
DWORD WINAPI ReadLogFile_DataRecorderThread (PVOID pvoid)   
{
    p_params P = (p_params) pvoid;
    HWND hWnd = P->hWnd;
    HINSTANCE hInst = P->hInst;
    char    ReadLogFileLastDir[256];
//  static def_OpenFileHook Hook;
    OPENFILENAME    ofn;
    char            fn[MAX_PATH]="";
    char            filter[32]="Text Files*.TXT;";
    char            title[]="Open IMC Data Recorder Log File";
    char            defext[]="TXT";
    int             status;
// Get File Name
    fn[0] = '';
    ReadLogFileLastDir[0] = '';
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize         = sizeof(ofn);
    ofn.hwndOwner           = hWnd;
    ofn.hInstance           = hInst;
    ofn.hInstance           = (HINSTANCE) GetWindowLong (hWnd, GWL_HINSTANCE);
    ofn.lpstrFilter         = filter;
    ofn.nFilterIndex        = 0;
    ofn.lpstrCustomFilter   = NULL ;
    ofn.nMaxCustFilter      = 0 ;
    ofn.lpstrFile           = fn;
    ofn.nMaxFile            = sizeof(fn);
    ofn.lpstrFileTitle      = NULL;
    if (ReadLogFileLastDir[0] == '')
    {
        SHGetSpecialFolderPath (NULL,ReadLogFileLastDir,0x0005,false);
    };
    ofn.lpstrInitialDir = ReadLogFileLastDir;
    ofn.lpstrTitle          = title;
    ofn.Flags               = OFN_FILEMUSTEXIST  | 
                              OFN_PATHMUSTEXIST  | 
                              OFN_EXPLORER       | 
                              // OFN_ENABLETEMPLATE | 
                              OFN_ENABLESIZING   | 
                              // OFN_ENABLEHOOK     |
                              OFN_READONLY;
    ofn.lpstrDefExt         = NULL;
    ofn.lpfnHook            = NULL;         // Hook.DialogHook; // hook routine
    ofn.lCustData           = NULL;          // (long) &Hook;       // data for hook routine
    ofn.lpTemplateName      = NULL;          // MAKEINTRESOURCE(IDD_HOOKFILEOPEN);
    ofn.nFileOffset         = 0 ;
    ofn.nFileExtension      = 0 ;
    ofn.lpstrDefExt         = defext;
    status = GetOpenFileName (&ofn);
    int S;
    S = CommDlgExtendedError();
    return 0;
}

当它失败时,调用堆栈看起来像这样…

SHELL32! 7ca4e035()
SHELL32! 7cb2dc16()
SHELL32! 7cb2dd5a()
SHELL32! 7cb27361()
SHELL32! 7c9f40a3()
BROWSEUI! 75f81b9a()
SHLWAPI! 77f69548()
NTDLL! 7c927545()
NTDLL! 7c927583()
NTDLL! 7c927645()
NTDLL! 7c92761c()
KERNEL32! 7c80b50b()

对不起,但我无法获得这些符号,因为我有一个旧的Visual c++:-(

)

在我看来,问题发生在GOFN的东西即将打开描述文件的弹出窗口时,鼠标光标悬停在文件名上。

导致这个问题的一组情况有些奇怪。实验表明,必须在GOFN窗口中执行以下操作:

  • 在DESKTOP上打开文件
  • 将鼠标悬停在长文件名上

如果我这样做两次,它总是失败。我使用的文件名是

IMCLOG_20120323_1658_ -_20120324_0653_CST_ + DST_E2_2_second.TXT

我用NOTEPAD尝试了同样的事情,出现了同样的问题!

我发现了许多关于同样问题的报告。例如:

社会。MSDN问题报告

CodeProject上问题CodeGuru线程

还有一个谷歌缓存链接,指向已删除的MS Connect错误报告。正如您所发现的,这个问题似乎只针对桌面中的文件。

我发现的唯一建议的解决方案是在线程开始时调用CoInitializeEx(NULL),并在结束时调用CoUninitialize(),所以这值得一试。

另外,GetOpenFileName()的MSDN文档说:

从Windows Vista开始,"打开"one_answers"另存为"公共对话框已被"公共项目"对话框所取代。

因此,完全抛弃GetOpenFileName()可能是值得的。

最新更新