批量安装Windows(1):架设Windows部署服务

对我们个人来说,平常隔一段时间就装一次系统没什么大不了的,可是如果你要帮几十乃至几百台电脑装系统,可就不是那么容易的了。那么有没有批量自动安装系统的方法呢? 当然有,其中之一就是Windows部署服务。

总的思路其实很简单:利用Windows部署服务(WDS)通过网络分发Windows系统和驱动+无人值守自动安装+KMS自动联网激活,客户机通过网络启动即可自动完成系统的安装。

作为这一切的基础,服务器系统是我之前刚刚装好的Windows server 2019.

1、安装并配置DHCP

如果网络上有支持高级选项的DHCP服务器,那这一步可以跳过。

首先是DHCP服务的安装,给本机设定一个静态IP,之后在服务器管理器里单击添加角色与功能,之后一路下一步。

然后就是配置了,首先在管理工具里找到并打开DHCP,在IPV4新建一个作用域,IP地址范围、子网掩码、路由器和DNS自己定,注意要和本机在同一网段。IPv6没有PXE选项,所以可以不用建作用域。

 

需要注意的是DNS之类的选项可以在作用域选项或是服务器选项里调整。

2、安装并配置Windows部署服务

 

和DHCP一样,在服务器管理器里添加角色,选Windows部署服务,之后注意要把部署和传输两个都勾上,之后无脑下一步,安装。

然后打开Windows部署服务(管理工具里有),展开服务器,右键开始配置。

值得注意的是,现在Windows部署服务已经不强制要求域环境了,所以不是域环境的就老老实实选独立服务器,不过因为我是域环境,所以我选择的是与Active Directory集成,之后也都是以这个作为基础的。

然后,注意选择响应所有客户端计算机并不要求管理员审核。各个教程都要求这样选,我自己的理解是因为用WDS安装系统的电脑大部分情况下都是未加入域的,因此就会被认为是未知计算机。

之后会有两个多选项,因为我的WDS是和DHCP装在一起的,所以要把那两个选项勾上。

之后根据建议,选一个足够大的分区来存放系统镜像。

最后不要选立即添加镜像。因为一般情况下都要熟悉一下界面。

这里说明一下:安装镜像是系统安装光盘里的install.wim,一个这样的文件往往包括多个安装镜像,为了节省空间可以只选需要的。比如说Windows7安装光盘里一般包括了家庭普通版、家庭高级版、专业版和旗舰版。由于KMS激活的需要,我们一般选择专业版。

启动镜像是是系统安装光盘里的boot.wim,也就是在我们用光盘启动电脑是首先出现的那个运行Windows安装程序的系统,又被称为Windows预安装环境(Windows PE)。网上的众多PE系统也是根据这个自己修改的。如果你检查一下各大PE的文件,就会在里面发现一个比较大的wim文件,这个就是这些PE改过的启动镜像。另外根据某博客的说法,32位启动镜像可以安装64位操作系统,反之不能。如果添加了多个启动镜像,而且客户机支持,那么在客户机启动时就会出翔类似Windows 7的启动菜单,默认30秒。而且这个启动菜单里的项目就是启动镜像里的名称一栏。而且菜单不支持中文。如果你添加了第三方PE,那么也可以正常进这些PE,但是就不能接着用部署服务安装系统了,不仅因为有部分PE无网络,更重要的是没有对应的接口。

如果你选中要求管理员审核未知计算机,那么这些未知的电脑就会出现在挂起的设备里,要求你手动通过。

多播传输是用来在批量部署Windows时节省网络带宽的。

驱动程序是WDS里的一个大坑。因为Windows部署服务是通过网络传输操作系统,所以如果启动镜像里没有对应主机的网卡驱动,那么安装将无法继续。所以之前可以尽量收集一下客户机的网卡驱动。还有,Windows 10的启动镜像有很多网卡的驱动,但是Windows 7则没有,所以启动镜像尽量选10的。另外,可以把客户机需要的驱动都放这里,到时候会自动分发给客户机。不过你也可以使用基于组的筛选器,虽然我分了组,但还没用过,所以无法发表评价。

之后就是添加镜像了,按照我上面说的,从install.wim添加安装镜像,从boot.wim添加启动镜像。添加驱动程序。

安装镜像和驱动程序都可以分组管理。

还有一些细节需要处理一下,在服务器属性-启动选项卡中,把需要按F12才继续的要求改一下。

如果需要自动化安装,还可以设置一下默认启动镜像。

无人值守可以在客户端选项卡里设置。如果是独立服务器,记得勾上不要将客户端加入域,否则会提示找不到域控制器。

在域中新建一个专门的用户来安装系统。因为我的WDS是与域集成的,所以安装系统时必须要输入域中的用户名与密码。

这时,已经可以通过Windows部署服务来安装系统了,不过还是要手动设置很多东西。

下一次,我来设置无人值守。

VS2017的折腾体验

这次的歌是《悠哉日常大王》的ED

我们这些大一学生刚学到C语言基础的“输入与输出”这一部分。由于坚信“实践是最好的老师”,于是我又一次开始着手编程。自己的平板是Windows 10 ,VC++6.0肯定是运行不起来了。我又懒得去装虚拟机,正好看到巨硬提供免费的VS2017社区版,有Outlook邮箱的我就下载了它。

结果,不出我所料,兼容性问题层出不穷。下面就列出我遇到的一些问题。

问题1:输出字符后直接退出。

我先编了一个Hello World,代码如下:

#include <stdio.h>
int main()
{
printf(“Hello,World!\n”);
return 0;

}

结果运行后只是黑窗口一闪而过,我还以为自己编错了。最后才知道要用system(”pause”)来在输出后停下来。

可是我再次编译时却提示“未定义标识符system”,在网上查资料后才知道要再添加一个头文件stdlib.h。

最后的代码是:

#include <stdlib.h>
#include <stdio.h>
int main()
{
printf(“Hello,World!\n”);
system(“pause”);
return 0;

}

问题2:无法打开源文件math.h。

我第二次想编一个解一元二次方程的小程序。由于求根公式涉及开方,C语言里的开方函数是sqrt,需要头文件math.h的支持。但是VS2017提示无法打开math.h。

这是因为VS2017的默认新建C/C++项目的库目录中没有包含有math.h的目录,要手动在项目属性-配置属性-C/C++-所以选项-附加包含目录里添加。而且比较坑的是,因为版本问题,添加的目录在不同电脑上是不同的。

 

同时还要去VC++目录里添加相应的库目录。

问题3: ‘scanf’: This function or variable may be unsafe. 

解决了sqrt的问题,再编译还是出错,提示scanf不安全,在网上查资料后给了我这样的解释;


旧式的scanf在读取数据的时候会根据format指示从缓冲区中读取直至结束,但有些时候我们的format指示会有Bug,导致scanf读取了给定的缓冲区以外(数组越界)的数据。看下例

int a = 0;
scanf(“%d”, &a);
假设我们输入数字123456,然后按回车。缓冲区中应该是一个数组123456,加上一个换行符,通常是”\r\n”。
这时候我们可以正常地读取到数字a。
但“有些时候”,缓冲区中的数据并不一定正确,这时候我们需要限制scanf的读取范围,通常是给定缓冲区的起始位置和缓冲区的长度。这样可以安全地处理错误数据。
但涉及CRT的人在涉及scanf的时候没有考虑到这么多的不安全因素,所以有了安全版本的scanf,及scanf_s,s的意思就是safe,我们会看到很多_s版本的函数,sprintf_s,vsnprintf_s等等,它们的作用都是一样的。
总之,带_s的函数是不带_s的安全版本,我们在代码中应当尽量使用安全版本。

在VS2005以及以后的VC++中,如果我们使用了不安全的版本,编译器会给我们一条警告,警告的内容就和下面的一样。
‘scanf’: This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\user\documents\visual studio 2013\projects\test\test.cpp 8 1 Test


我真是懒得吐槽巨硬了,安全就安全吧,我把所有的scanf换成了scanf_s。

接下来再编译,终于成功了!

但我很快发现自己又悲剧了。

问题4:输出中文乱码。

就是上图的样子。还好我的耐心还有,并且我知道这是编码的问题。不过我找解决方案时,还是用了“VS2017输出中文乱码”。网上给出的解决方法大体上分为三种。

第一种是安装ForceUTF8这个插件,然而我硬是没找到它。

第二种是利用自定义添加“高级保存”,从而把源码保存为GB2312格式。我也是使用了这一种方法。

还有一种方法是把代码导出到Notepad++之类的专业文本编辑工具中转码,再用VS重新打开项目。最后改掉源码中的乱码部分。我觉的相较别的方法麻烦了一点,于是没用使用这种方法。

问题4:第二个及之后的scanf_s函数不起作用。

这个问题在之后的运行测试中被发现,可以正常输入第一个变量a的值,但之后的输入代码就失效了。我之后也把源码给了我的C语言老师看,他认为代码没问题,而这个问题到现在都没解决,源码如下:

// ConsoleApplication1.cpp: 定义控制台应用程序的入口点。
//

#include “stdafx.h”
#include “stdlib.h” //支持sstem函数
#include “math.h” //支持sqrt函数
#include “stdio.h”

int main()
{
float a, b, c, x1, x2, step; //定义a、b、c、x1、x2与中间变量step
printf(“本程序可用来解形如ax?+bx+c=0(x≠0)的一元二次方程。\n”);
system(“pause”);
printf(“请输入a:”);
scanf_s(“f%”, &a); //录入a
printf(“请输入b:”);
scanf_s(“f%”, &b); //录入b
printf(“请输入c:”);
scanf_s(“f%”, &c); //录入c
step = b*b – 4 * a*c; //计算b?-4ac
step = sqrt(step); //计算(b?-4ac)^(1/2)
x1 = (b + step) / (2 * a); //计算x1
x2 = (-b + step) / (2 * a); // 计算x2
printf(“方程的解为\n”);
printf(“x1=%f\n”, x1); //输出x1
printf(“x2=%f\n”, x2); //输出x2
printf(“按任意键退出\n”);
system(“pause”);
return 0;
}

 

总结:看来学校里一般只用VC++6.0学习C语言还是很有道理的。