前提条件:Windows上已安装Cygwin(安装方法不在本文中叙述) 注:如果有其它版本的,先删除之。 至此,安装结束。
本文的GTK+版本为2.16.0
在Windows平台上安装GTK+,方法很多,最简单的方法是采用一体包进行安装,步骤如下:
1)下载gtk+-bundle_2.16.0-20090317_win32.zip
地址:http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.16/gtk+-bundle_2.16.0-20090317_win32.zip
2)解压缩到指定目录
我解压到C:\GTK
3)设置环境变量PATH
“我的电脑”--右键“属性”--“高级”--“环境变量”,编辑Path,添加:
c:\gtk\bin
4)测试
4.1)确保Windows系统内未安装其它版本的gtk+,在cmd命令行下执行:
pkg-config --cflags gtk+-2.0
显示结果:
4.2)验证安装是否正确(无需编写Helloworld)
在cmd命令行下执行:
gtk-demo
显示结果:
如果想使用微软的Windows主题引擎,在安装目录下的etc/gtk-2.0目录下,新建一文件,命名为gtkrc,内容只有一句:
gtk-theme-name = "MS-Windows"
保存并退出。
一切OK。
windows内核函数命名的特征,就是函数名都按其所在的层次或模块加上了特定的前缀。
depends.exe工具的作用是查看Dll提供的接口函数
ATL创建的windows服务,只是负责控制,而将业务逻辑放在mfc的dll中,建立线程后,在发送消息,代码如下
extern "C" __declspec(dllexport) void _DllMain() { unsigned nThreadId; HANDLE hThread = (HANDLE)_beginthreadex(NULL,0, &ThreadMain,NULL, 0, &nThreadId); Sleep(1000); PostThreadMessage(nThreadId, WM_TIMEISUP, NULL, NULL); } unsigned __stdcall ThreadMain(LPVOID pParam) { MSG msg; while(true){ if(::GetMessage(&msg, NULL, NULL, NULL)) { switch(msg.message){ case WM_TIMEISUP: { Download d; break; } default: break; } } }; /* MSG msg; while(::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) { switch(msg.message) { case WM_TIMEISUP: { Download d; break; } default: break; } }*/ return 0; }
关键字:C++,初始化,initialization,对象,object
来自实际项目的一段代码,简化形式如下:
switch (t)
{
case 0:
int a = 0;
break;
default:
break;
}
有什么问题吗?似乎没有。请用编译器编译一下……
嗯?!一个错误“error C2361: initialization of 'a' is skipped by 'default' label”。这怎么可能?
几番思琢,悟出解释:C++约定,在块语句中,对象的作用域从对象的声明语句开始直到块语句的结束,也就是说default标号后的语句是可以使用对象a的。如果程序执行时从switch处跳到default处,就会导致对象a没有被正确地初始化。确保对象的初始化可是C++的重要设计哲学,所以编译器会很严格地检查这种违例情况,像上述的示例代码中default语句后面并没有使用a,但考虑到以后代码的改动可能无意中使用,所以一样被封杀。
明白了原因,解决起来就很容易了。只要明确地限制对象a的作用域就行了。
switch (t)
{
case 0:
{ //added for fix problem
int a = 0;
break;
} //added for fix problem
default:
break;
}
如果确实需要在整个switch语句中使用对象a,那就把int a = 0;移到switch语句之前即可。不过从原先的语句看,其意图似乎并不是这样的,所以推荐前面的解决方案。
结束了吗?没有。让我们继续考究错误提示信息中“initialization”(也就是初始化)的确切含义。C++很看重初始化,所以往往会给我们造成一种错觉,似乎对象在定义处一定会经过初始化过程。真实情况如何呢?还是用实例来证明吧。
switch (t)
{
case 0:
int a;
a = 0;
break;
default:
break;
}
编译,这次没有报错。很明显int a;定义了对象,但没有进行初始化,否则就应该报告原先的错误。
再看看用户自定义类型。
class B
{
};
switch (t)
{
case 0:
B b;
break;
default:
break;
}
编译结果也没有错误,所以没有提供构造器的类仍然没有初始化过程。
如果给类加入构造器,情况就不同了。
class B
{
public: //added for initialization
B(){} //added for initialization
};
这样就能重现原先的错误。证明有了构造器,编译器就将进行初始化处理并对之进行安全检查。
从上面的实验,可以直观地体验到一些基本的C++观念和原理,并提高认识深度。
1.int a = 0;既是声明也是定义,还包括初始化;int a;是声明还是定义依上下文而定,但如果是定义就不会包括初始化;a = 0;仅仅是赋值语句,在此句前对象已经存在了。
2.为了避免不必要的开销,默认情况下,即程序员没有在代码中明确指示时,编译器不提供初始化过程。某些需要确保初始化的类,请提供构造器。这里透露出一个C++的设计哲学:通常你会面对多种选择,所以请精确地控制代码,其收益则是可以自由取舍调配的安全性、速度、内存开销等程序特性。
3.严密注意程序中标号的使用情况,特别是case、default等常规标号,否则他们可能会破坏对象的正确状态。如果提供了对象初始化,则能够获得编译器的额外帮助。
服务启动后再停止时出错,是因为我在成员函数PreMessageLoop()函数中缺少控制代码所致,控制代码如下:
HRESULT CRestoreSerModule::PreMessageLoop(int nShowCmd) { m_status.dwControlsAccepted = m_status.dwControlsAccepted | SERVICE_ACCEPT_PAUSE_CONTINUE; HRESULT hr = __super::PreMessageLoop(nShowCmd); if (hr == S_FALSE) hr = S_OK; return hr; }
加上这些代码即可正常启动、停止了。
至于无法删除,
[SC] deleteservice FAILD 1072 这个错误是因为停止没有相应,所以控制器上好像停止了,可是程序依然在运行,打开任务管理器,结束这个进程,在删除就没有问题了。
E:\projects\ATL\RestoreSer\Debug>sc /?
错误: 未知命令
描述:
SC 是用于与服务控制管理器通信的命令行程序。
用法:
sc <server> [command] [service name] <option1> <option2>...
选项 <server> 的格式为 "\\ServerName"
可以键入 "sc [command]"以获得命令的进一步帮助
命令:
query-----------查询服务的状态,
或枚举服务类型的状态。
queryex---------查询服务的扩展状态,
或枚举服务类型的状态。
start-----------启动服务。
pause-----------发送 PAUSE 控制请求到服务。
interrogate-----发送 INTERROGATE 控制请求到服务。
continue--------发送 CONTINUE 控制请求到服务。
stop------------发送 STOP 请求到服务。
config----------(永久地)更改服务的配置。
description-----更改服务的描述。
failure---------更改服务失败时所进行的操作。
qc--------------查询服务的配置信息。
qdescription----查询服务的描述。
qfailure--------查询失败服务所进行的操作。
delete----------(从注册表)删除服务。
create----------创建服务(将其添加到注册表)。
control---------发送控制到服务。
sdshow----------显示服务的安全描述符。
sdset-----------设置服务的安全描述符。
GetDisplayName--获取服务的 DisplayName。
GetKeyName------获取服务的 ServiceKeyName。
EnumDepend------枚举服务的依存关系。
下列命令不查询服务名称:
sc <server> <command> <option>
boot------------(ok | bad) 表明是否将上一次启动保存为
最后所知的好的启动配置
Lock------------锁定服务数据库
QueryLock-------查询 SCManager 数据库的 LockStatus
示例:
sc start MyService
用户空间和系统控件
内核空间的映像是ntoskrnl.exe
用户控件的映像是win32k.sys
windows内核
现在操作系统的一个特征是:用户空间和系统控件的划分
微软把系统空间中靠近底层,与硬件考的较近的部分称为内核,而将内核以上的部分成为Executive,即管理层。
管理层包括:
用ISAPI来完成一些工作,就要能够读取地址栏的参数,地址栏参数就在ECB结构体的lpszQueryString成员变量中
LPSTR urlParam = pECB->lpszQueryString;