Windows Vista for Developers——第五部分:Windows核心服务器(Windows Core Server)入门
作者:Kenny Kerr
翻译:Dflying Chen
请同时参考《Windows Vista for Developers》系列。
我想现在是时候暂停一下Windows Vista,而是讨论一下他的老大哥——Windows Server,特别是Windows Server Core。Server Core是即将发布的下个版本Windows Server中的一个特殊的版本(当然,很多代码都是与Windows Vista共享的),为了减少维护所需要的工作量,Server Core只专注于一种服务,例如DNS解析服务器或文件服务器等,而其他的诸如Web浏览器、计算器等鸡肋程序统统都不包含在内——这些程序除了增加维护成本之外,看不出还有什么别的用处。
在《Windows Vista for Developers》系列的第五部分中,我们将接触一下Windows Server Core。与本系列中的其他文章不同的是,本文中的示例代码较少,而主要是介绍这个新操作系统的功能。在本系列的后续文章中,我将详细讨论一些Windows Vista以及Windows Server所提供的特性。最近我也注意到了一些关于这个新平台的健壮性的争论(请参考http://www.knowing.net/CommentView,guid,46b9f3f8-e6e2-4d61-a39c-bdc5e1a6fc54.aspx和http://swigartconsulting.blogs.com/tech_blender/2006/10/vista_server_co.html),所以在本文中我也会对此给出一些自己的观点,争取尽量站得高一些并给出点总体的介绍。但开始之前,我们要做的第一件事情就是安装好Windows Server Core。
安装Windows Server Core非常简单,你只需要决定将其安装到那个分区上就行了。与Windows Vista相比,安装的过程也显得快了不少。这自然是因为省去了很多额外的安装、配置时间。安装好后,系统的欢迎界面如下所示(点击放大):
因为这是我们第一次登录,所以系统并没有提供任何默认的帐号。你可能会产生疑惑,如何在不登录的情况下创建用户呢?是否有某些默认的无需密码的帐号呢?幸运的是,Windows沿袭下来的“Administrator”帐号仍旧可用,且没有初始密码。这样我们即可使用“Administrator”登录至系统中。这些应该写在文档中,因为那些不是很熟悉Windows的用户可能想不到用“Administrator”尝试。
因为这是你第一次使用该帐号登录,所以Windows需要一点时间来创建用户个性化信息。完成之后,我们将看到一个shell:
这个地方显得有些诡异了。如果你是个Windows高手的话,那么这个命令提示窗口没什么问题。而你若习惯了用Windows资源管理器以及一些MMC控制程序来管理系统的话,那么这个界面可能对你来说可不是那么的友好,没什么能够帮上你的东西——至少在刚开始的时候。
当前我们要做的第一件事就是配置系统,以便我们能够通过远程连接对其进行管理。若想看看计算机的那个似乎随机产生的名字,输入hostname 命令即可。现在你的第一个命令方面的挑战就是如何更改计算机名。
虽然Server Core基本上没有任何GUI工具,但它却几乎拥有普通Windows的所有管理功能。也就是说,基本上每个命令行工具都可以使用,但最值得称道的是远程访问/管理功能被保留了下来。包括Windows Management Instrumentation (WMI)以及对RPC的支持等,很多Windows SDK函数和接口以及很多Windows Gui管理工具都需要这些功能的支持。Server Core同样包含了Windows Remote Management(WinRM),它是WS-Management的一个实现。
知道可以使用WMI之后,我们就可以使用其相关命令行工具来重名名计算机了。幸运的是,Win32_ComputerSystem类提供了一个名为Rename的方法,所以重名名计算机只不过是一条命令的事情:
wmic ComputerSystem where Name="%COMPUTERNAME%" call Rename Name="NewName"
wmic 命令以类的名称开始,系统将自动把它展开为类的全名。虽然这里只用到了一个ComputerSystem 类的实例,WMI仍然需要我们对其作以甄别,这正是where 子句的作用。WMI查询语言非常类似于SQL。COMPUTERNAME 环境变量将自动返回当前的计算机名,我们无需手工打出那一长串自动生成的名字。最后调用了Rename 方法,并将新的计算机名称通过Name 参数传递进取。如果一切顺利的话,输出将类似如下所示:
Executing (\\LH-Z6KDIWK41SMN\ROOT\CIMV2:Win32_ComputerSystem.Name="LH-Z6KDIWK41SMN")->Rename()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
ReturnValue = 0;
};
若该方法执行失败,那么ReturnValue 将是一个非零值,若ReturnValue 为0,那么就代表着该操作执行成功。在此输入hostname ,可以看到新的计算机名。若你没有更改计算机名所需要的权限,那么ReturnValue 将为5。更改计算机名之后,我们需要重新启动计算机以使改动生效。重新启动计算机可以使用如下命令:
shutdown /r
我们也可以重命名当前正在使用的帐号:
wmic UserAccount where Name="%USERNAME%" call Rename Name="NewName"
这条命令使用了Win32_UserAccount类,在这里可以看到有关WMI类的详细列表。
因为该计算机已经自动连接到了网络中,假设在网络中还有其他的计算机而你想要在某一台上对该计算机进行远程管理,那么只要做一件事情就够了——更改当前用户的密码,因为Windows不允许空密码的帐号建立远程连接。幸运的是更改密码并不需要任何的命令行工具。按下Ctrl+Alt+Del 即可在出现的对话框中选择“Change a password...”。
设置好密码之后,我们即可使用Windows资源管理器从远程连接到该计算机上,执行管理工作,甚至使用MMC等其他管理工具。自然,默认情况下该计算机的很多服务都被禁用掉了,我们需要根据需要进行启用。
其中的一个默认情况下被禁用的功能就是终端服务(Terminal Services)。若想使用远程桌面连接(Remote Desktop Connection)的话,我们需要在注册表中更改某一位的设置。若你现在仍在该命令提示窗口中,那么可以输入如下的脚本命令:
cscript %SystemRoot%\System32\scregedit.wsf /ar 0
当然,这条命令只不过是设定了注册表中某个键的值而已。若你已经离开了该命令提示操作界面,那么可以在远程通过使用注册表编辑器完成同样的工作。在File菜单中选择“Connect Network Registry...”命令,输入该计算机名即可开始浏览并根据需要更改其注册表:
Key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server
Value: fDenyTSConnections
0表示允许连接,1表示禁止。若将其设置为0,那么我们即可使用远程桌面连接登录到该计算机上了。
这是一个使用脚本命令的平台么?
一个常见的问题就是,Server Core是不是个使用脚本命令的平台?就像传统的UNIX界面那样,shell就是个强大的脚本平台。实际上,这个功能并不是Server Core所关注的重点,但在某种程度上,Server Core的开发者确实希望能够实现这样一种效果。Windows上的脚本的发展方向显然是PowerShell ,不过不幸的是目前为止Server Core还不能支持,因为Server Core并不支持PowerShell 所需要的.NET Framework 。
虽然Server Core包含了WMI、CSCRIPT等其他强大的脚本相关功能,但除非有类似PowerShell 的工具出现,并提供更加丰富且一致的脚本编程环境,否则仍旧无法称之为脚本命令平台。
你是不是在搞笑?Server Core不支持.NET Framework?
确实是这样,Server Core不支持.NET Framework。虽然Server Core的开发者非常想将其包含进来,但实施起来却并不那么容易。最主要的问题就是.NET Framework的设计并不十分模块化。即使只想要一个最简单的控制台“Hello World”程序,我们也不得不完整地安装.NET Framework以及其大量的依赖选项。正是因为这些依赖选项才导致了这个结果。.NET Framework中很大的一个依赖选项就是IE(是不是有些不可思议?——译者注)。我们广大的开发者都希望微软公司的.NET Framework开发团队能够在未来注意到这个问题,并解决。至少应该可以将.NET Framework分割开来以避免这些无谓的依赖。到了那时,Server Core即可支持.NET Framework,并运行托管代码——例如我们期待的PowerShell。
当然,如果你乐意的话,还是可以使用Windows SDK和Visual C++开发原生代码。基于Server Core开发自然也不会出现什么问题。补充一句,你可能可以尝试手工安装.NET Framework ,以便移除一些不必要的依赖选项,但这也将造成系统的不稳定,对于那些需要长时间运行的服务起来说,或许会让你今后的维护头痛不已。我的朋友Ari 就非常擅长这中手工安装。
没有GUI?哦等等……
Server Core所提供的唯一shell就是命令提示窗口(cmd.exe)。同样还提供了Windows任务管理器,以便管理应用程序以及服务。这样也暗示了Server Core只能在某种程度上支持GUI应用程序。很多我用C++编写的GUI应用程序仍可在Server Core上运行,不过都受到了一定程度的限制。所有普通控件以及其他UI元素仅可用,但依赖Explorer的东西,例如打开/保存文件对话框都不能正常显示,其他的一些对话框的功能也均受到了不同程度的影响。
Server Core的开发者曾经考虑过完整移除GUI功能(例如对GDI的支持),但记事本和任务管理器简直太有用了,所以我们都很高兴能够看到现在Server Core的样子——至少支持最基本的GUI。
我的应用程序能运行于Server Core上么?
一个简单却不那么漂亮的判断方法就是检查程序是否需要Windows Explorer(%SystemRoot%\Explorer.exe)。更好一些的方法需要调用Windows Vista提供的GetProductInfo 方法。请参考如下示例:
OSVERSIONINFOEX info = { sizeof (OSVERSIONINFOEX) };
VERIFY(::GetVersionEx(reinterpret_cast<POSVERSIONINFO>(&info)));
wcout << L"Version: "
<< info.dwMajorVersion
<<L"."
<< info.dwMinorVersion
<<L"."
<< info.dwBuildNumber
<< L" Service Pack "
<< info.wServicePackMajor
<< "."
<< info.wServicePackMinor
<< std::endl;
DWORD type = 0;
VERIFY(::GetProductInfo(info.dwMajorVersion,
info.dwMinorVersion,
info.wServicePackMajor,
info.wServicePackMinor,
&type));
switch (type)
{
case PRODUCT_UNLICENSED:
{
wcout << L"The software license is invalid or expired." << std::endl;
break;
}
case PRODUCT_DATACENTER_SERVER_CORE:
case PRODUCT_STANDARD_SERVER_CORE:
case PRODUCT_ENTERPRISE_SERVER_CORE:
{
wcout << L"This is Windows Server Core." << std::endl;
break;
}
default:
{
wcout << L"This is probably not Windows Server Core..." << std::endl;
}
};
你应该可以发现,上面的代码中存在着一个问题。产品类型列表可能会随着新版本Windows的推出而不停增长。当前只有三个版本的Server Core,但今后很可能会越变越多。幸运的是,微软公司替我们考虑到了这一点。技巧在于调用GetProductInfo 时,你必须只指定程序运行于的最新版本的Windows版本。这样即可保证实际的产品类型被正确映射到你所指定的版本上。设想十年以后,在Windows 2016(原文发表于2006年——译者注),微软公司引入了一个新的产品类型,名为PRODUCT_EXTRA_CRISPY_ENTERPRISE_SERVER_CORE(含义为“超级无敌清爽版Server Core”——译者注)。如果你将GetProductInfo 基于6.0版本和0.0service pack 硬编码到了程序中,那么程序就会自动映射到最接近的版本上。在这个例子中,十有八九会是PRODUCT_ENTERPRISE_SERVER_CORE。基于这些信息,我们可以将上面的这段示例代码重构为如下样子:
DWORD type = 0;
VERIFY(::GetProductInfo(6,
0,
0,
0,
&type));
switch (type)
{
case PRODUCT_UNLICENSED:
{
wcout << L"The software license is invalid or expired." << endl;
break;
}
case PRODUCT_DATACENTER_SERVER_CORE:
case PRODUCT_STANDARD_SERVER_CORE:
case PRODUCT_ENTERPRISE_SERVER_CORE:
{
wcout << L"This is Windows Server Core." << endl;
break;
}
default:
{
wcout << L"This is not Windows Server Core." << endl;
}
};
恩,这就是我今天要说的。希望这些对Server Core的介绍能够帮助你了解一些有关Windows Server新系列的知识。