warning C4743: “const std::ios_base::failure::`vftable'”有不同的大小: 16 和 12 字节

最近在使用VS2013进行静态库链接的时候,发现在最后链接的时候,编译器报告如下警告

4>LINK : warning C4743: “const std::system_error::`vftable'”在“aaa.cc”和“bbb.cpp”中具有不同的大小:  16 和 12 字节
4>LINK : warning C4743: “const std::_System_error::`vftable'”在“ccc.cc”和“ddd.cpp”中具有不同的大小:  16 和 12 字节
4>LINK : warning C4743: “const std::ios_base::failure::`vftable'”在“eee.cc”和“fff.cpp”中具有不同的大小:  16 和 12 字节
4>LINK : warning C4743: “const std::runtime_error::`vftable'”在“xxx.cc”和“yyy.cpp”中具有不同的大小:  16 和 12 字节

尽管这个是个警告,但是由于涉及到vftable 的问题,这个问题会导致对象指针之间相互赋值的时候导致内存布局混乱,非常可能导致严重的问题。因此这个警告的危险级别甚至比错误的还要严重,绝不能简单的忽略这个问题。

研究了很久,发现,在Debug版本上面是没有问题的,但是Release版本上面必然出现该问题。并且当设置VC++ 的 “工程属性->配置属性->C/C++->优化->全程序优化”为 “否”的时候,也是可以无警告链接通过的。但是却会导致我们的工程损失更多的优化,降低运行效率。

这个问题产生的原因是一个宏引起的,这个宏就是 “_HAS_EXCEPTIONS=0” 。这个宏控制了STL对于异常的处理流程,影响着typeinfo,system_error 等几个文件中对于VC 运行时库的链接选择,要么链接libcmt.lib,要么链接msvcrt.lib。比较不凑巧的是,微软在实现这两个库的时候,其中一个比另外一个多了一个虚函数。(这种情况不应该发生,但是确实发生了!)

因此,如果我们的LIB工程定义了“_HAS_EXCEPTIONS=0” ,那么所有使用我们这个LIB的项目,都要定义这个宏。

对于简单的项目,只要都定义“_HAS_EXCEPTIONS=0” 就可以解决问题。但是对于复杂的工程,尤其是依赖了大量的第三方的已经编译过的,没有源代码的LIB项目来说,只能是采用妥协的办法,所有的工程都取消这个宏的定义,使得两者的内存布局相同。毕竟,稳定性是第一需求。

Windows机器上程序崩溃dump(UMDF Crash Dump)

最近接到用户的投诉,在Windows 7 32位的机器上,UMDF驱动频繁崩溃,关键是SetUnhandledExceptionFilter 设置的异常过滤竟然一丁点用都没有,查询了半天,才注意到UMDF框架把UnhandledException接管了,你完全是无力反抗。

然后去MSDN上查询,根据Determining Why the Reflector Terminated the Host Process微软文档,WER会在“%windir%\system32\LogFiles\WUDF”目录下面生成DUMP文件,测试之后发现,是否生成完全依赖WER的心情,捣鼓到后来,干脆完全不生成DUMP文件了,另外他偶尔生成的也都是MiniDump ,作用有限。“Users\All Users\Microsoft\Windows\WER\ReportQueue”目录下面的报告数据,也是时有时无,阴晴不定。

继续Google,微软文档 Collecting User-Mode Dumps 设置如下的注册表

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"DumpType"=dword:00000001
"DumpCount"=dword:0000000A
"DumpFolder"="D:\\Temp"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"DumpType"=dword:00000001
"DumpCount"=dword:0000000A
"DumpFolder"="D:\\Temp"

[HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"DumpType"=dword:00000001
"DumpCount"=dword:0000000A
"DumpFolder"="D:\\Temp"

这样设置之后,正常的应用都可以在D:\Temp 下面生成崩溃记录,但是WUDFHost.exe 就是不能生成崩溃DUMP,貌似是WUDFHost.exe 用其他低权限用户账户运行,导致没办法生成转储文件。

继续Google,ProcDump进入视野,着实是个好的工具软件,非常好用。于是写了个批处理文件来跟踪WUDFHost.exe的异常。

procdump -ma -e WUDFHost.exe

应用崩溃的时候,会在当前目录下面生产对应的.dmp文件。

本地下载

下面为简单的用法例子

Using ProcDump

usage: procdump [-a] [[-c|-cl CPU usage] [-u] [-s seconds]] [-n exceeds] [-e [1 [-b]] [-f <filter,...>] [-g] [-h] [-l] [-m|-ml commit usage] [-ma | -mp] [-o] [-p|-pl counter threshold] [-r] [-t] [-d <callback DLL>] [-64] <[-w] <process name or service name or PID> [dump file] | -i <dump file> | -u | -x <dump file> <image file> [arguments] >] [-? [ -e]
-a Avoid outage. Requires -r. If the trigger will cause the target to suspend for a prolonged time due to an exceeded concurrent dump limit, the trigger will be skipped.
-b Treat debug breakpoints as exceptions (otherwise ignore them).
-c CPU threshold at which to create a dump of the process.
-cl CPU threshold below which to create a dump of the process.
-d Invoke the minidump callback routine named MiniDumpCallbackRoutine of the specified DLL.
-e Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions.
-f Filter the first chance exceptions. Wildcards (*) are supported. To just display the names without dumping, use a blank ("") filter.
-g Run as a native debugger in a managed process (no interop).
-h Write dump if process has a hung window (does not respond to window messages for at least 5 seconds).
-i Install ProcDump as the AeDebug postmortem debugger. Only -ma, -mp, -d and -r are supported as additional options.
-l Display the debug logging of the process.
-m Memory commit threshold in MB at which to create a dump.
-ma Write a dump file with all process memory. The default dump format only includes thread and handle information.
-ml Trigger when memory commit drops below specified MB value.
-mp Write a dump file with thread and handle information, and all read/write process memory. To minimize dump size, memory areas larger than 512MB are searched for, and if found, the largest area is excluded. A memory area is the collection of same sized memory allocation areas. The removal of this (cache) memory reduces Exchange and SQL Server dumps by over 90%.
-n Number of dumps to write before exiting.
-o Overwrite an existing dump file.
-p Trigger on the specified performance counter when the threshold is exceeded. Note: to specify a process counter when there are multiple instances of the process running, use the process ID with the following syntax: "\Process(<name>_<pid>)\counter"
-pl Trigger when performance counter falls below the specified value.
-r
Dump using a clone. Concurrent limit is optional (default 1, max 5).
CAUTION: a high concurrency value may impact system performance.
Windows 7 : Uses Reflection. OS doesn't support -e.
Windows 8.0 : Uses Reflection. OS doesn't support -e.
Windows 8.1+: Uses PSS. All trigger types are supported.
-s Consecutive seconds before dump is written (default is 10).
-t Write a dump when the process terminates.
-u Treat CPU usage relative to a single core (used with -c).
As the only option, Uninstalls ProcDump as the postmortem debugger.
-w Wait for the specified process to launch if it's not running.
-x Launch the specified image with optional arguments. If it is a Store Application or Package, ProcDump will start on the next activation (only).
-64 By default ProcDump will capture a 32-bit dump of a 32-bit process when running on 64-bit Windows. This option overrides to create a 64-bit dump. Only use for WOW64 subsystem debugging.
-? Use -? -e to see example command lines.
If you omit the dump file name, it defaults to <processname>_<datetime>.dmp.
Use the -accepteula command line option to automatically accept the Sysinternals license agreement.
Examples

Write a mini dump of a process named 'notepad' (only one match can exist):
C:\>procdump notepad

Write a full dump of a process with PID '4572':
C:\>procdump -ma 4572

Write 3 mini dumps 5 seconds apart of a process named 'notepad':
C:\>procdump -s 5 -n 3 notepad

Write up to 3 mini dumps of a process named 'consume' when it exceeds 20% CPU usage for five seconds:
C:\>procdump -c 20 -s 5 -n 3 consume

Write a mini dump for a process named 'hang.exe' when one of it's Windows is unresponsive for more than 5 seconds:
C:\>procdump -h hang.exe hungwindow.dmp

Write a mini dump of a process named 'outlook' when total system CPU usage exceeds 20% for 10 seconds:
C:\>procdump outlook -p "\Processor(_Total)\% Processor Time" 20

Write a full dump of a process named 'outlook' when Outlook's handle count exceeds 10,000:
C:\>procdump -ma outlook -p "\Process(Outlook)\Handle Count" 10000

Write a MiniPlus dump of the Microsoft Exchange Information Store when it has an unhandled exception:
C:\>procdump -mp -e store.exe

Display without writing a dump, the exception codes/names of w3wp.exe:
C:\>procdump -e 1 -f "" w3wp.exe

Write a mini dump of w3wp.exe if an exception's code/name contains 'NotFound':
C:\>procdump -e 1 -f NotFound w3wp.exe

Launch a process and then monitor it for exceptions:
C:\>procdump -e 1 -f "" -x c:\dumps consume.exe

Register for launch, and attempt to activate, a modern 'application'. A new ProcDump instance will start when it activated to monitor for exceptions:
C:\>procdump -e 1 -f ""
-x c:\dumps Microsoft.BingMaps_8wekyb3d8bbwe!AppexMaps

Register for launch of a modern 'package'. A new ProcDump instance will start when it is (manually) activated to monitor for exceptions:
C:\>procdump -e 1 -f ""
-x c:\dumps Microsoft.BingMaps_1.2.0.136_x64__8wekyb3d8bbwe
 
Register as the Just-in-Time (AeDebug) debugger. Makes full dumps in c:\dumps.
C:\>procdump -ma -i c:\dumps
See a list of example command lines (the examples are listed above):
C:\>procdump -? -e

VisualSVNServer Service failed to start

这是VisualSVN Server Manager启动时报出的一个启动错误,可能的问题有以下3种。

1:端口被占用:使用CMD命令

netstat -an

查看端口是否已使用,如果已使用则更换一个端口。

2:Repositories 的物理目录不存在,重新设置Repositories  物理路径。

3:服务VisualSVN Server Manager 服务启动用户设置不正确,在系统服务中,找到 VisualSVN Server 点击右键——属性——登录选项卡,如果是网络用户,就尝试切换到本地用户试试,如果是本地用户,就尝试指定一下其他用户试试。

VistualSVN

解决Win7“无法访问Windows Installer服务。Windows Installer没有正确安装时可能发生这种情况...”

今天在卸载一个软件时,发生错误,提示信息如下:

无法访问Windows Installer服务。Windows Installer没有正确安装时可能发生这种情况...

截图如下:
1356154505_5881

在网上找了下原因,都知道是Windows Installer服务出现了问题,如没有启动它呀,

启动不了Windows Installer呀之类的...却没有给出一个有用的解决方法。

好不容易知道微软提供了一个 Windows Fix it 服务,网址如下

http://support2.microsoft.com/default.aspx?scid=kb;%5BLN%5D;290301
或者
http://support2.microsoft.com/fixit/zh-cn
或者
Fix problems that block programs from being installed or removed
经过一番折腾,搞定!

目前(2018.03.14)貌似微软关闭了这个网站,可以在本站下载Microsoft Fix it 51015

这个工具微软的下载地址为http://download.microsoft.com/download/D/9/7/D97359C4-B5EA-40C7-9991-3EEF14D4848F/MicrosoftFixit51015.msi

如何在VS2010 IE11 下调试BHO控件

VS2010 IE11 下调试BHO控件,在新版本的调试器中已经简化调试流程,简单的设置一下,就可以直接调试BHO的DLL文件了,方便很多。

如下图设置,点击工程属性,然后选择 “调试”在“要启动的调试器”中选择 “Web 浏览器调试器”,在“HTTP URL”中输入具体的网站地址,然后直接启动调试即可。

BHODebug

用Visual Studio 2008开发IE BHO (浏览器帮助对象)之一

BHO 通常并不提供其自身的任何用户界面 (UI)。它们而是通过在后台响应浏览器事件和用户输入数据来发挥作用。例如,BHO 可以拦截弹出窗口、自动填充窗体或为鼠标手势添加支持。

有一种常见误解认为工具栏扩展项需要 BHO.但如果将 BHO 与工具栏配合使用,则可以实现更丰富的用户体验。(关于IE工具栏的编程,在另一篇文章中说明).

BHO 的生命周期与它所交互的浏览器实例的生命周期相等。在 IE 6 和早期版本中,这意味着要为每个新的顶层窗口创建(和销毁)一个新 BHO。在IE 7中则是为每个选项卡都创建和销毁一个新 BHO。

BHO 必须实现 IObjectWithSite 接口, 该接口提供了两个方法GetSite和SetSite。根据MSDN的说明:

GetSite:  Gets the last site set with IObjectWithSite::SetSite. If there is no known site, the object returns a failure code.

SetSite:  Provides the site's IUnknown pointer to the object.

我们主要是对后者进行调用,此方法方便了与 Internet Explorer 的初始通信,并会在其将要释放时通知 BHO。我们实现此接口,然后将 BHO 的 CLSID 添加到注册表中,就可以创建一个简单的浏览器扩展。过程如下:

1. 在Visual Studio中,选择VC++中的ATL项目, 创建一个新的项目MySolutionPlugin, 在随后的向导中,确认Server Type是Dll, Visual Studio会为我们创建程序的模板.

2. 为该项目添加我们的程序主体, (不熟悉visual studio的同学在资源浏览器里的右键菜单里选 add-->class, 可别选到New Item), 类型选ATL Simple Object ,  short name命名为RayBHO,各项属性如下:
a) “线程模型” ---“Apartment”
b) “聚合”---“否”
c) “接口”---“双重”
d) “支持”---勾上“IobjectWithSite”。

具体的含义请参考MSDN.

一般来说,Internet Explorer 至少调用SetSite方法两次: 一次用于建立连接,另一次则是在浏览器退出时。我们 BHO 中的 SetSite 实现将执行以下操作:

•存储对站点的引用。在初始化期间,浏览器将 IUnknown 指针传递给顶层 WebBrowser 控件,然后 BHO 将对它的引用存储在一个专用成员变量中。

•释放目前被占用的站点指针。Internet Explorer 传递 NULL 时,BHO 必须释放所有接口引用并且断开与浏览器的连接。

要实现SetSite,我们需手工在添加一个public的方法:

STDMETHOD(SetSite)(IUnknown * pUnkSite);

STDMETHOD 宏是将方法标记为虚方法并且确保其具有适用于公共 COM 接口的调用约定的一个ATL 约定, 它有助于区分 COM 接口和该类中可能存在的其他公共方法。其实现成员方法时应相应使用 STDMETHODIMP 宏。同时我们需要声明一个私有变量来保存Browser的指针"

CComPtr<IWebBrowser2> m_spWebBrowser;//保存Browser指针的

私有变量
然后是SetSite的实现

STDMETHODIMP CRayBHO::SetSite(IUnknown*pUnkSite)
{
    if(pUnkSite!=NULL)
    {
        //缓存指向IWebBrowser2的指针。
        pUnkSite->QueryInterface(IID_IWebBrowser2,(void**)&m_spWebBrowser);
    }
    else
    {
        //在此释放缓存的指针和其他资源。
        m_spWebBrowser.Release();
    }
    //返回基类实现
    return IObjectWithSiteImpl::SetSite(pUnkSite);
}

从上面的介绍我们知道, 初始化期间,浏览器将传递一个对其顶层 IWebBrowser2 接口(我们对其进行缓存处理)的引用。浏览器关闭时将传递 NULL,为避免内存泄漏和循环引用计数,此时释放所有指针和资源非常重要。最后,我们调用基类实现以便继续执行接口合约的其余部分。

加载DLL 后,系统将通过 DLL_PROCESS_ATTACH 通知调用 DllMain 函数。由于 Internet Explorer 大量使用多线程,因此,对 DllMain 的频繁的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知会降低扩展和浏览器进程的整体性能。

如果BHO 不需要线程级的跟踪,我们可以在 DLL_PROCESS_ATTACH 通知期间调用 DisableThreadLibraryCalls 以避免新线程通知的额外开销。修改DllMain.cpp 中的DllMain函数:

extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if(dwReason==DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hInstance);
    }
    return _AtlModule.DllMain(dwReason,lpReserved);
}

要使BHO工作,我们还需要把BHO 的 CLSID 添加到注册表中。此条目会将 此DLL 标记为浏览器帮助程序对象,并使 Internet Explorer 在启动时加载 BHO。我们可以在MySolutionPlugin.idl中找到该BHO的CLSID.幸运的,Visual Studio会帮助我们实现这些, 你看到:

importlib("stdole2.tlb");
[
uuid(057F3E68-6C2E-40A5-A641-E8CF9D6766F3),
helpstring("RayBHO Class")
]

您的机器的CLSID可能有所不同, 接着打开RayBHO.rgs文件,添加入:

HKLM
{
    NoRemove SOFTWARE
    {
        NoRemove Microsoft
        {
            NoRemove Windows
            {
                NoRemove CurrentVersion
                {
                    NoRemove Explorer
                    {
                        NoRemove 'Browser Helper Objects'
                        {
                            ForceRemove {057F3E68-6C2E-40A5-A641-E8CF9D6766F3} = s 'RayBHO Class'
                            {
                                val NoExplorer = d '1'
                            }
                        }
                    }
                }
            }
        }
    }
}

这一段是为了在注册表里添加一个双字节的NoExplorer=1的键,不让Windows Explorer加载该BHO,因此该BHO只能在ie中运行.

注意,这里的UUID字段跟MySolutionPlugin.idl 中的是一致的。

你可以编译这个BHO. 如果一切正常, 你可以在IE的管理加载项里看到这个BHO.

如果不幸报错: 该BHO无法被注册,根据我的经验,原因大概有2类,可以依次检查

1. 你是否有管理员权限以修改注册表,如不是管理员身份,可以在菜单上右击Microsoft Visual studio 2008,从右键菜单中选择"运行方式"...
2. 你的注册表条目语法是否正确,或者含有非法字符.

引用 http://blog.csdn.net/dupei/article/details/6092692

Windows下Mingw的复制粘贴

使用GIT,免不了会接触到GIT的命令行界面,但是在这个界面上面貌似不能复制粘贴,比较麻烦,网上查询了一下,可以按照下图的方式来操作,就是有些费劲啊。
右击标题栏,在弹出的菜单里面选择复制粘贴。mingw_copy

调试UMDF驱动

相对于调试运行在最高特权级的WDM、KMDF驱动,调试运行在ring3的UMDF驱动难度大为降低,不需要双机调试,我们可以像调试普通应用程序和服务一样在一台电脑上完成。

调试方法:

  1. 编译好需要调试的驱动(包括安装用的inf等),连接硬件,把需要调试的驱动安装上。然后断开硬件连接(对于USB设备来说直接拔出就可以了)。
  2. 启动WinDBG,设置好符号路径,特别是被调试驱动的符号。详细设置可以参考Debugging Tools的文档。
  3. 运 行regedit,打开
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WUDF\Services\{193a1820-d9ac-4997-8c55-be817523f6aa}

    如果之前从 未调试过UMDF驱动,会发现HostProcessDbgBreakOnDriverLoad键值为0,这个键值的含义是延迟多少秒加载驱动对象。我们 把它修改为15秒(十六进制0xF,如果手慢可以改得更大)。注意这个键值不影响DllMain,如果要调试DllMain,请修改 HostProcessDbgBreakOnStart。

  4. 插入硬件,并且在15秒内使用WinDBG的Attach to Process(快捷键是F6),找到UMDFHost.exe,attach即可。注意如果系统有多个使用UMDF驱动的硬件,就会有多个 UMDFHost.exe进程,为了不致混淆,请提前移除不用的硬件。
  5. 完成调试后,请恢复注册表(将延迟修改为0),以免正常硬件的驱动加载被延迟。

链接 http://hyperiris.blog.163.com/blog/static/180840059201026477127/

Windows打开应用,提示“此程序被组策略阻止”

Windows打开应用,提示“此程序被组策略阻止”,该问题为组策略限制了用户使用某个应用程序,一般可以在

控制面板--->管理工具--->本地安全策略-->软件限制策略

中找到并且解除限制。但是有时候采用域控制的网络,这个控制信息可能存储在域控制服务器上面,这个时候就不好处理了,其实域控制的信息,也是要提前写入到本机的,总不能用户拔掉网线就可以使用某个应用,插上网线就不能使用某个应用了吧。因此只要找到注册表位置,删除即可。

组策略的注册表位置如下所示

[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft]

先备份一下注册表,然后全部删除,重启机器即可。

其他的可能存储软件限制逻辑的注册表位置如下所示,可以自行尝试。

[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft]
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies]
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Group Policy]
[HKEY_CURRENT_USER\Software\Policies\Microsoft]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies]

RicheditCtrl 控件在不同语言环境的操作系统上可能出现的乱码问题

由于工作上需要,把软件移植到英文版的os上(软件已是unicode版本的),发现RicheditCtrl
控件上显示的字体(本来内容应该显示为中文)乱码了。

发生乱码的具体代码:

mRichEditCtrl.SetSel(-1, -1);
mRichEditCtrl.ReplaceSel( (LPCTSTR)Message.GetBuffer());
Message.ReleaseBuffer();

查找原因:可能是控件不了解字符串已经是unicode代码,所以控件根据locale 的code page来硬性将代码转换为unicode显示,所以出现乱码。

解决方法:

mRichEditCtrl.SetSel(-1, -1);
#if UNICODE
	SETTEXTEX SetTxtEx = {0,};
	SetTxtEx.flags = ST_SELECTION;
	SetTxtEx.codepage = 1200;
	BOOL bRet = ::SendMessage(mRichEditCtrl.GetSafeHwnd(), EM_SETTEXTEX, (WPARAM)&SetTxtEx, (LPARAM)Message.GetBuffer());
	ASSERT(bRet);
#else
	mRichEditCtrl.ReplaceSel( (LPCTSTR)Message.GetBuffer());
#endif
Message.ReleaseBuffer();
The code page used to translate the text to Unicode. If codepage is 1200 (Unicode code page), no translation is done. If codepage is CP_ACP, the system code page is used.
参考 http://www.cppblog.com/jeffrey78/articles/2214.html