1)问题的来源:

ISAutomationRunner程序中,主体功能(调用vbs)完成以后。由于这个软件需要在批处理中被调用,处于方便性考虑需要加入控制台输出功能。因为程序主体来自codeguru上别人的程序,而且是GUI的,无法直接进行控制台输出。首先试了试改成支持MFC的console程序的,结果报错,粗略分析了下是由于源码中有几个地方用到了窗口句柄。不得以采用了为GUI程序添加控制台输出的方法:

-------------------------------------

AttachConsole(-1); // 将当前程序附着到父进程上

freopen("CONIN$", "r+t", stdin); // 重定向 STDIN
freopen("CONOUT$", "w+t", stdout); // 重定向STDOUT

-------------------------------------

其中AttachConsole需要用新的SDK,因而需要设置_WIN32_WINNT=0x0500,这么一设置后AttachConsole使用正常了。

编译,运行,出现文件选择框,确定。晕,出现异常了。

IDE中调试一番,发现是程序中使用的CTextFile类(Johan Rosengren所写的一个很实用的类)中调用的CFileDialog析构时出现异常了,源码如下

-------------------------------------

BOOL CTextFile::GetFilename( BOOL save, CString& filename )
/* ============================================================
    Function :        CTextFile::GetFilename
    Description :    The function will display a standard file
                    dialog. If the instance is created with an
                    extension, the extension will be used to
                    filter files.
    Return :        BOOL                -    TRUE if a file was
                                            selected
    Parameters :    BOOL save            -    TRUE if the file
                                            should be saved.
                    CString& filename    -    Placeholder for the
                                            selected filename

   ============================================================*/
{
    CString filter;
    CString extension = GetExtension();
    if( extension.GetLength() )
        filter = extension + _T( "-files (*." + extension + ")|*." ) + extension + _T( "|All Files (*.*)|*.*||" );

    BOOL result = FALSE;
    CFileDialog dlg( !save, extension, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter );

    if( dlg.DoModal() == IDOK )
    {
        filename = dlg.GetPathName();
        result = TRUE;
    }

    return result;

}

--------------------------------------

2)问题的原因:

首先注释了新入的AttachConsole函数,问题依旧。自己郁闷的折腾了好一番,没法只好暂时搁置了。刚才又想起来,于是开始google,一搜“ CFileDialog 析构 异常 ”,乖乖-总算让我碰上一个MFC的bug了。

问题的产生原因在

http://codeguru.earthweb.net/forum/printthread.php?t=320297&pp=50

有所解释,我认为大体可以理解为:

VC6 自带的SDK和 MFC42中的定义,再后来的SDK中更新了,从而导致在析构的时候多卸载了内容

3)问题的解决:

a)换回老SDK,手动加载AttachConsole

b)修改CTextFile源码,由在栈上分配CFileDialog改为在堆上分配

根据我的情况,我选择了a方法,手动加载AttachConsole的源码如下

--------------------------------------

//为了在不用PLATFORM SDK的情况下加载AttachConsole
BOOL myAttachConsole(DWORD dwProcessId)
{
    typedef BOOL (WINAPI* _AttachConsole)(DWORD dwProcessId);
    HINSTANCE hinstance = LoadLibrary(_T("kernel32.dll"));
    if (hinstance == NULL)
    {
        return FALSE;
    }
    _AttachConsole AttachConsole = NULL;
    AttachConsole = (_AttachConsole)GetProcAddress(hinstance , "AttachConsole");
    if (AttachConsole == NULL)
    {
        return FALSE;
    }
    AttachConsole(dwProcessId); 

       return TRUE;
}

--------------------------------------

4)感慨:

写程序就是这样的充满意外。。。

posted on 2010-04-23 10:57  silentmj  阅读(1124)  评论(0编辑  收藏  举报