衡玉's Blog

Happy coding

Windows下安装GTK+的最佳攻略

 



本文的GTK+版本为2.16.0

前提条件:Windows上已安装Cygwin(安装方法不在本文中叙述)

在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
显示结果:

结果图1

注:如果有其它版本的,先删除之。

4.2)验证安装是否正确(无需编写Helloworld)
在cmd命令行下执行:
gtk-demo
显示结果:
结果图2

至此,安装结束。

如果想使用微软的Windows主题引擎,在安装目录下的etc/gtk-2.0目录下,新建一文件,命名为gtkrc,内容只有一句:
gtk-theme-name = "MS-Windows"
保存并退出。

一切OK。

windows 内核函数前缀的意义

 windows内核函数命名的特征,就是函数名都按其所在的层次或模块加上了特定的前缀。

  • Ex:管理层,Ex是Executive的开头两个字母
  • Ke:和形成,Ke是Kenrel的开头两个字母
  • Hal:硬件抽象层,Hal是Hardware Abstraction Layer的缩写
  • Ob:对象管理,Ob是Object的开头两个字母
  • Mm:内存管理,Mn是Memory Manager的缩写
  • Ps:进程(线程)管理,Ps表示Process
  • Se:安全管理,Se是Security的开头两个字母
  • Io:I/o管理
  • Fs:文件系统,Fs是File System的缩写
  • Cc:文件缓存管理,Cc表示Cache
  • Cm:系统配置管理,Cm是Configuraction manager的缩写
  • Pp:“即插即用”管理,Pp表示PnP
  • Rtl:运行时程序库,Rtl是Runtime Library

 

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

    关键字: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    这个错误是因为停止没有相应,所以控制器上好像停止了,可是程序依然在运行,打开任务管理器,结束这个进程,在删除就没有问题了。

sc windows服务控制工具帮助

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

 

windows内核情景分析 读书手记

用户空间和系统控件

  • 系统空间可以访问用户空间,有必要,应为用户程序实在内核的安排下工作的
  • 用户空间无权访问系统空间,应为系统空间必须受到保护,否则存在崩溃的危险

内核空间的映像是ntoskrnl.exe

用户控件的映像是win32k.sys

 

windows内核

        现在操作系统的一个特征是:用户空间和系统控件的划分

微软把系统空间中靠近底层,与硬件考的较近的部分称为内核,而将内核以上的部分成为Executive,即管理层。

管理层包括:

  1. 对象管理
  2. 内存管理
  3. 进程\线程管理
  4. I\O管理
  5.  安全管理
  6. 进程(线程)通信模块
  7. .......

ISAPI获取url地址的参数

 用ISAPI来完成一些工作,就要能够读取地址栏的参数,地址栏参数就在ECB结构体的lpszQueryString成员变量中

 

LPSTR urlParam = pECB->lpszQueryString;