6/30/2005

把WinDbg集成到Visual Studio中

在我的前一篇BLOG(http://blog.joycode.com/jiangsheng/archive/2005/06/08/53126.aspx)中我提到了如何使用WinDbg来调试Visual C++程序。但是,从IDE到命令行之间的切换比较麻烦,为了偷懒起见,可以把WinDbg加到Visual Studio的工具菜单中,这样就可以直接从IDE启动WinDbg来进行调试了。下面是外部工具配置界面的设置
标题 : WinDbg

命令行: C:\masm32\debug\windbg.exe (这不是一个典型路径,但是既然MASM里面有了,我也懒得再去下一个来装,如果是单独下载安装的话,命令行可能像这样:"C:\Program Files\Debugging Tools for Windows\windbg.exe")

参数:-ee c++ -G -i "$(TargetDir)" -y "$(TargetDir)" -QY -logo -QSY -sdce -WF "$(ProjectFileName).WEW" "$(TargetPath)"

(命令行太长的时候windbg会工作不正常。至于这些参数的含义——呃,还是去下一个Debug Tools For Windows回来装上看文档比较好。)

初始目录: $(ProjectDir)

当然,调试的代码不限于C++,实际上,我主要是用windbg来调试汇编代码。

6/08/2005

使用WinDbg调试VC程序

虽然在VC6.0中可以通过安装Visual C++ Toolkit(网站:http://msdn.microsoft.com/visualc/vctoolkit2003/)来编写基于最新版本的平台SDK、DirectX SDK的程序以及托管代码,但是VC6附带的调试器并不支持新版本的调试信息,所以实际上是不能用VC6来调试新版本编译器生成的程序的。一个替代的解决方案是使用新版本的Windows调试工具Windbg(网站:http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx)。Windbg的调试功能基本和Visual C++中的相同,但是需要手动设定源文件和调试符号文件的搜索路径(可以参考VC6.0中的对应设置)。一些代码,例如MFC的代码比较难于定位,这时可以双击调用堆栈中的函数名称来打开文件并定位到函数所在位置。Windbg可以进行有限的托管代码调试,但是调试过程比较麻烦。在没有安装Visual Studio的计算机上调试,例如进行远程调试的时候可能还需要部署调试符号(Generating and Deploying Debug Symbols With Visual C++ 6.0)。
调试Visual Studio .Net 的程序需要用户是管理员或者"Debug User"用户组成员。如果登录用户不是该组成员,那么也可以用WinDbg来调试程序。

5/13/2005

在线地址本服务

我收到的来自在线地址本服务的邀请现在越来越频繁了。今天我又收到了一封这样的邮件:Add yourself to xxx's address book! Open your invitation
This invitation was sent to my email address on behalf of xxxxxx (xxxxxx@hotmail.com)
If you do not wish to receive invitations from this Ringo member, click here. To stop receiving invitations from all Ringo members, click here.
在我的上一篇BLOG(Please don't show your password to 3rd party.)中,我提到了一些站点的服务存在风险,因为它们要求用户提供邮箱的密码,而这样可能导致身份冒用——实际上,他们已经用我朋友——其中一些名字我比较陌生,因为我不熟悉一些网友的真实姓名——的名义给我发送了数十封这样的电子邮件,而且看起来我将会持续收到这样的邮件,即使是在我注册之后。尽管一些网站声称我可以通过提供我的电子邮件地址来停止接收他们给我发送的邀请,但是这样的方法显然没有生效——和垃圾邮件中的停止接收链接一样,这仅仅证明这个电子邮箱正在被使用,并且准备好接收更多的垃圾邮件。记得蠕虫病毒么?这种收集邮件地址的方法更加简单,而且可以绕过任何防火墙。我建议收到这样的邮件的人在注册之前看看这篇文章:http://www.anu.edu.au/people/Roger.Clarke/DV/ContactPITs.html ,以了解可能付出的代价。OK,在继续讨论之前,让我们来看看这些网站到底是什么。有多少人在注册之前看过他们的服务条款?要使用他们的服务,你必须同意他们的服务和隐私条款并且提供你的个人信息,例如生日、性别诸如此类。第一眼看上去这些服务条块似乎是完全无害的,除了:
http://www.bebo.com/Privacy.jsp

You agree that we may use personal information about you to improve our marketing and promotional efforts, to analyze site usage, improve our content and product offerings, and customize the Site's content, layout, and services. These uses improve the Site and better tailor it to meet your needs, so as to provide you with a smooth, efficient, safe and customized experience while using the Site.

We use your personal information to: troubleshoot problems; measure consumer interest in our services, inform you about offers, products, services, and updates; customize your experience; detect and protect us against error, fraud and other criminal activity; enforce our Terms of Use; and as otherwise described to you at the time of collection.

You agree that we may use your personal information to contact you and deliver information to you that, in some cases, are targeted to your interests, such as targeted banner advertisements, administrative notices, product offerings, and communications relevant to your use of the Site. By accepting the Terms of Use and Privacy Policy, you expressly agree to receive this information. You may make changes to your email notification preferences at any time.It is possible that as we continue to develop our website and our business, Bebo's service and/or related assets might be acquired. Notwithstanding any provision in this policy to the contrary, in event of a merger or acquisition, your personal information may be transferred to the acquiring entity, and become subject to the acquirer's data practices.

http://www.bebo.com/TermsOfUse.jsp

Bebo reserves the right at all times to monitor, review, retain, and/or disclose in good faith any information it believes in good faith that such action or disclosure is necessary to conform to legal and government requirements, or to protect and defend the rights or property of Bebo or enforce the TOU.Bebo reserves the right to collect and distribute non-personal demographic information to third parties. As such this information would not contain any information that would allow your identity to be deduced.

不够危险?来看看这个:(http://ringo.com/about/terms.html)
Modifications to Service
These Terms & Conditions were last modified on January 25, 2005. At any time and without prior notice, Ringo shall have the right, in its sole discretion, to modify, add or remove terms of these Terms & Conditions, without notifying our customers of such modifications, additions or removals, and all such changes shall be effective immediately. Your continued participation and use of this website and/or the Ringo services following our posting of any such change on our site will constitute binding acceptance of such change. You agree that Ringo shall not be liable to you or to any third party for any modification, suspension or discontinuance of the service.
OK,看过上面的文字,我也同意Ringo不liable,所以我不会去注册。因为这个网站的拥有者是Monster.com,我所知道的世界上最大的求职网站,所以从现在开始我不会理会任何类似的邀请,不管这样的邀请来自哪里。

我更加忧虑的是那些要求电子邮箱密码的服务,例如http://www.sms.ac, http://www.bebo.comhttp://www.hi5.com 之类。一些电子邮件服务和其他服务共享密码,例如MSN Money和Yahoo Messenger,而这样的电子邮件的密码被泄漏可能造成的损失不仅仅是发送垃圾邮件而已。很多人——包括我在内——在很多站点(甚至可能是银行的网站)使用同样的用户名和密码。但是,有多少人阅读过并且对法律条文有足够认识来理解它们的服务条款?有多少人知道很多这样的密码要求页面(在我发表这篇文章的时候,我没找到一个反例)完全没有加密措施?通过任何一个路由器——如果有人愿意的话,可以是在网站服务器所在网络上的那个——都可以获得这样的用户名和密码而不违反任何任何服务条款。更不用说这样的安全防护措施是否可以阻止黑客获取服务器上的数据了。

大多数人知道垃圾邮件和连锁信息(把这个信息发送给XX个人你就可以XXXX之类)是不受欢迎的。但是我还是不断收到一些这样的无用电子邮件、MSN和QQ消息——如果我还在使用手机的话,可能还有需要付费的文字消息——这大约占我的日常通讯量的2/3。再次提醒并不会阻止那些不听劝告的人发送这样的信息,但是我希望能够让一些没有被提醒过的人认识到,免费的蛋糕并不是看起来那么美味可口。我也建议你在阅读之后,做一些你自己的搜索和研究来做出你自己的判断。

5/08/2005

程序员之懒

程序员在我看来是比较会偷懒的一个群体。为了在开发软件的时候减少人工操作,他们会使用各种各样的软件和语言特性,例如IDE和预处理宏。李建忠在他的BLOG(http://blog.joycode.com/lijianzhong/archive/2005/05/08/50440.aspx)中提到,为了简化声明属性的工作,他的同事自己写了一些小工具来生成需要的代码。在C++托管扩展中,这个工作稍微简单一些,用预处理宏就可以了。

#define DECLARE_PROPERTY_DOUBLE_PUBLIC(propertyName)protected: double _##propertyName;
public: __property double get_##propertyName(){ return _##propertyName; } __property void set_##propertyName( double new_##propertyName ){ _##propertyName= new_##propertyName; }

public __gc __sealed class Vector {
public:
// ...
DECLARE_PROPERTY_DOUBLE(x)
DECLARE_PROPERTY_DOUBLE(y)
DECLARE_PROPERTY_DOUBLE(z)

};

当然,如果使用C++/CLI的话,这个工作更加简单:

public ref class Vector sealed
{
public:
property double x;
property double y;
property double z;
};

我在编程的时候也是个彻底的实用主义者,需要大量重复编写的代码都是尽量用宏实现。例如,我用如下的宏来简化CCmdTarget派生类对IOleCommandTarget类的处理:

#define DECLARE_IOLECOMMANDTARGET STDMETHOD(QueryStatus)(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [],OLECMDTEXT* pcmdtext); STDMETHOD(Exec)(const GUID*,DWORD nCmdID, DWORD nCmdExecOpt,VARIANTARG* pvarargIn, VARIANTARG* pvarargOut);

#define IMPLEMENT_IOLECOMMANDTARGET(theClass,localclass)STDMETHODIMP theClass::X##localclass::Exec(const GUID* pguidCmdGroup,DWORD nCmdID, DWORD nCmdExecOpt,VARIANTARG* pvarargIn, VARIANTARG* pvarargOut){ METHOD_PROLOGUE_EX(theClass, localclass) ASSERT_VALID(pThis); return pThis->Exec(pguidCmdGroup,nCmdID,nCmdExecOpt,pvarargIn,pvarargOut);}STDMETHODIMP theClass::X##localclass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[],OLECMDTEXT* pcmdtext){ METHOD_PROLOGUE_EX(theClass, localclass) ASSERT_VALID(pThis); return pThis->QueryStatus(pguidCmdGroup,cCmds,prgCmds,pcmdtext);}

#define IMPLEMENT_LOCALCLASS_UNKNOWN(theClass,localclass) STDMETHODIMP_(ULONG) theClass::X##localclass::AddRef() { METHOD_PROLOGUE_EX(theClass, localclass) ASSERT_VALID(pThis); return pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) theClass::X##localclass::Release() { METHOD_PROLOGUE_EX(theClass, localclass) ASSERT_VALID(pThis); return pThis->ExternalRelease(); } STDMETHODIMP theClass::X##localclass::QueryInterface( REFIID iid, LPVOID* ppvObj) { METHOD_PROLOGUE_EX(theClass, localclass) ASSERT_VALID(pThis); return pThis->ExternalQueryInterface(&iid, ppvObj); }

这样要在CCmdTarget派生类中实现IOleCommandTarget接口的话,只需要编写实现函数就行了:

//声明
class CScreenCaptureGDI : public CScreenCaptureBase
{
DECLARE_OLECOMMANDTARGET
……
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget)
DECLARE_OLECOMMANDTARGET
END_INTERFACE_PART(OleCommandTarget)
……
}

//实现

IMPLEMENT_DYNCREATE(CScreenCaptureDirectX, CCmdTarget)

BEGIN_INTERFACE_MAP(CScreenCaptureDirectX, CScreenCaptureBase)
……
INTERFACE_PART(CScreenCaptureDirectX, IID_IOleCommandTarget , OleCommandTarget)
END_INTERFACE_MAP()

IMPLEMENT_LOCALCLASS_UNKNOWN(CScreenCaptureDirectX,OleCommandTarget)

IMPLEMENT_IOLECOMMANDTARGET(CScreenCaptureDirectX,OleCommandTarget)

和微软知识库文章Q177551(http://support.microsoft.com/kb/177551)比较一下就知道可以少写多少代码了。

MFC对COM接口的宏支持在MFC技术文章TN038(http://msdn.microsoft.com/library/en-us/vclib/html/_MFCNOTES_TN038.asp)中有详细说明。

使用宏在编写程序的时候有时可以减少很多工作量,但是缺点是调试比较麻烦。MFC中包含大量的宏,在编写自己的宏的时候可以作为参考。

4/25/2005

请勿向第三方公开你的个人密码

Please don't show your password to 3rd party.

一直以来我都持续收到一些加入在线手机社区http://www.sms.ac的邀请,因为我没有手机(要找我的人注意:我醒着的话一般都挂在MSN上),所以总是看过就算。但是今天收到了来自一个不是很熟的朋友的加入这个社区和另外一个社区http://www.bebo.com的邀请,所以上网搜索了一下一些个人BLOG对这两个网站的引用。搜索的结果触目惊心。
这些网站显然都要求用户输入邮箱和邮箱的密码,同时使用邮箱中保存的联系人信息来邀请用户的联系人加入。但是,向第三方公开你的密码意味着公开你的全部邮件、联系人的家庭地址、电话等信息。这可能不是你的朋友愿意看到的情形。

密码是私有的,并且从不应该向第三方公开。任何在注册时要求现存密码的服务都是可疑的,特别在询问你的邮箱密码而没有警告用户这样可能造成的危险的情况下。如果某个网站询问你的hotmail账户和密码,那么几乎可以肯定这是个没有和微软合作的网站,因为真正和微软合作的商业网站应该会使用.Net Passport来和微软共享用户注册信息,例如http://www.match.com。

如果你收到了注册某个网站的邀请,首先搜索因特网上对这个网站的引用以确定是否值得向这个网站公开你的个人信息。如果有必要,你可以新建一个电子邮件和密码组合来参与在线社区。


参考
http://hownow.brownpau.com/archives/2005/02/spam_from_smsac
http://www.jaffacake.net/BensBlog.nsf/dx/bebo.com---update

顺便说一下,微软发布了Windows XP和Windows 2003的64位版本(Microsoft Windows XP Professional x64 Edition )Windows Server 2003 x64 Editions。