一、问题提出
当上实验中心主任后的一个棘手的问题就是机房管理。机房不大,只有60多台电脑,而且已经装上了海光硬盘保护卡豪华版,可以直接网络GHOST硬盘。只要安装好一台电脑,就可以在6个小时左右将40G硬盘信息传遍每一台电脑。
虽然是一个小小的实验中心,也要为大家上机服务,什么等级考试、财务会计、外贸模拟、软件开发样样具全。这样,在40G硬盘中装了6个操作系统(DOS、Win 98、Win 2003 Server、Win 2000 Server、WinXP、Win 2000 Server(英文版MCSE用))。在与补丁和病毒做了一番斗争后,剩下的问题就是自动更新IP地址与计算机名。机房中的每台机器都有一个编号,机器的IP分配也与编号相关。海光蓝卡虽然提供自动修改IP的功能,但对Server版的操作系统不起作用(修改完后,系统就瘫痪了),对非Server版的操作系统虽然起作用,但IP地址分配是随机的,如果想人为定制,必须自己建立MAC地址与IP地址的映射表。总之,使用起来非常不方便,何况还没法对NT Server修改IP呢。打电话咨询海光公司,回话是:你用的保护卡不具备修改NT Server IP地址的功能,我们这里的最新产品是MAX版,可以解决你的问题。这不是又要从兜里掏银子吗!还是自己动手解决吧。
二、解决办法
一开始,我使用DHCP动态分配IP,对每台机器保留一固定IP地址,但由于所有的机器都是克隆出来的,机器名完全一样,每次启机都报有重名计算机存在,还影响了网上邻居的使用。最后一生气,干脆自己编一个自动修改机器名与IP地址的程序。
考查了一下,可以使用Windows Script或是WinBatch实现,不过需要在机器上安装这些软件,似乎有些大材小用。最后决定使用Delphi自己编写一个自动修改IP的程序。这样,借助海光蓝卡上自动修改IP的功能(说是自动修改IP,经我研究,实际上就是解开硬盘保护,自动将每个系统重新启动一下,在启动的过程中,海光自己的驱动程序完成修改工作。),实现自己修改IP。具体方法就是,不再安装海光自动修改IP的程序,改成自己的程序,让系统在第一次启动的时候自动修正IP和计算机名,并重新启动机器。
说干就干,首先将所有机器号与MAC映射表存储成Access数据库,并将IP地址设置为自动获取DHCP,防止启机时冲突。然后在Delphi中编写如下程序:
unit UpdateIP;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, NB30, StdCtrls, DB, ADODB;
type
TfrmUpdateIPAddress = class(TForm)
adoCntAccess: TADOConnection;
adoDSMacAddress: TADODataSet;
procedure adoCntAccessBeforeConnect(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmUpdateIPAddress: TfrmUpdateIPAddress;
implementation
{$R *.dfm}
//============================================================
// 设置数据库路径
//============================================================
procedure TfrmUpdateIPAddress.adoCntAccessBeforeConnect(Sender: TObject);
begin
adoCntAccess.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Password="";' +
'User ID=Admin;Data Source=' + ExtractFilePath(Application.ExeName) +
'\MacData.mdb;Mode=Share Deny None;Extended Properties=""';
end;
//============================================================
// 获取计算机的 MAC 地址
//============================================================
function NBGetAdapterAddress(a :Integer) : string;
var
NC : TNCB;
ADAPTE : TADAPTERSTATUS;
LANAENU : TLANAENUM;
intId : Integer;
cR : Char;
strTem : string;
begin
Result := '';
try
ZeroMemory(@NC, SizeOf(NC));
NC.ncb_command := Chr(NCBENUM);
cR := NetBios(@NC);
//Reissue enum command
NC.ncb_buffer := @LANAENU;
NC.ncb_length := SizeOf(LANAENU);
cR := NetBios(@NC);
if Ord(cR) <> 0 then
exit;
ZeroMemory(@NC, SizeOf(NC));
NC.ncb_command := Chr(NCBRESET);
NC.ncb_lana_num := LANAENU.lana[a];
cR := NetBios(@NC);
if Ord(cR) <> 0 then
exit;
ZeroMemory(@NC, SizeOf(NC));
NC.ncb_command := Chr(NCBASTAT);
NC.ncb_lana_num := LANAENU.lana[a];
StrPCopy(NC.ncb_callname, '*');
NC.ncb_buffer := @ADAPTE;
NC.ncb_length := SizeOf(ADAPTE);
cR := NetBios(@NC);
strTem := '';
for intId := 0 To 5 do
strTem := strTem+ InttoHex(Integer(ADAPTE.adapter_address[intId]), 2);
Result := strTem;
finally
end;
end;
//============================================================
// 设置计算机名
//============================================================
function SetComputerName(AComputerName: string): Boolean;
var
ComputerName: array[0..MAX_COMPUTERNAME_LENGTH + 1] of Char;
begin
StrPCopy(ComputerName, AComputerName);
Result := Windows.SetComputerName(ComputerName);
end;
//============================================================
// 启动时自动修改IP地址以及计算机名
//============================================================
procedure TfrmUpdateIPAddress.FormShow(Sender: TObject);
var
sMac, sNum, sComputerName, BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
sMac := NBGetAdapterAddress(0);
AdoCntAccess.Connected := True;
adoDSMacAddress.Close;
adoDSMacAddress.Parameters.ParamByName('mac').Value := sMac;
adoDSMacAddress.Open;
if adoDSMacAddress.RecordCount = 0 then
Application.Terminate;
sNum := Trim(adoDSMacAddress.FieldByName('ComputerID').Value);
//设置计算机名
sComputerName := 'Stu_' + sNum;
if not SetComputerName(sComputerName) then
begin
ShowMessage('计算机名没有设置成功!');
Application.Terminate;
end;
//设置IP地址、DNS等
BatchFileName := ExtractFilePath(ParamStr(0)) + 'AutoUpdate.bat ' + sNum;
StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_Hide;
if CreateProcess(nil, PChar(BatchFileName), nil, nil,
False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
Application.Terminate;
end;
end.
该程序首先获取当前机器的MAC地址,然后从Access表中检索机器号,并根据机器号生成机器名“Stu_+机器号”。在修改完机器名后,自动启动一个外部批处理(在这里是一个BAT文件),进行挂参数的批处理调用,实现修改IP地址工作。如果有人问为什么要调用批处理的话,实际上我想将系统做成自删除的系统,程序执行完就将自己删除的干干静静,不留任何痕迹,这在后面再讨论。
批处理文件的内容如下:
@ECHO OFF
rem 修改IP地址、子网掩码、网关
cmd /c netsh interface ip set address name="本地连接" source=static addr=10.16.19.%1 mask=255.255.255.0 gateway=10.16.19.254 gwmetric=1
rem 修改DNS
cmd /c netsh interface ip set dns name="本地连接" source=static addr=210.31.198.65
rem 删除放在启动组中的快捷方式
del /q "C:\Documents and Settings\All Users\「开始」菜单\程序\启动\AutoUpdate.*"
rem 调用重启机的批处理文件
Restart.bat
从文件中可以看出,为了让系统在第一次运行时自动修改IP地址,在开始菜单的启动中创建了一个快捷方式,自动调用我的程序,程序执行完后,将启动菜单中快捷方式删除,然后重新启动。至于自删除的功能,这里我没有放上来,感兴趣的话,可以在Google中检索“Delphi 自己 删除”,能找到很多资料。
下面说说重新启动,Windows 98、Windows Me重新启动很简单,只要一条命令就可以了:
rundll32.exe shell32.dll,SHExitWindowsEx n
其中最后面的n表示:
0 - LOGOFF
1 - SHUTDOWN
2 - REBOOT
4 - FORCE
8 - POWEROFF
Window XP的重启不同于98,需要使用 shutdown 命令,具体可以参考手册。
最困难的是NT 2000的重启,使用上面的方法都不起作用。必须通过多条命令实现。下面看看NT 2000重启的批处理文件:
@ECHO OFF & cd/d %temp% & echo [version] > {out}.inf
(set inf=InstallHinfSection DefaultInstall)
echo signature=$chicago$ >> {out}.inf
echo [defaultinstall] >> {out}.inf
rundll32 setupapi,%inf% 1 %temp%\{out}.inf
del {out}.inf
有些乱,但很管用。
好了,所有的准备工作都已经具备,下面是实施办法:
1、首先需要准备一台机器做DHCP服务器,并且配置好IP地址池,但这个IP地址池不要与你想分配的IP地址相重复,否则会有不少麻烦。比如你想给克隆后的机器分配从10.16.19.1到10.16.19.100的IP地址段,那么你可以给你的DHCP服务器分配一个IP地址为192.168.1.1,并且配置可分配地址池为192.168.1.2到192.168.1.101,最好不要将租期设置的很长,否则可能出现IP不够分配的问题,或者在每次操作时清空一下租约。
2、安装客户端机器。
3、将编译好的可执行文件以及两个批处理文件还有一个Access数据库文件拷贝到一个目录中;
4、在目录“C:\Documents and Settings\All Users\「开始」菜单\程序\启动\”中建立一个指向该可执行文件的快捷方式(操作系统不同,目录可能也各不相同);
5、将客户端机器的IP地址设置为自动获取。
6、关闭计算机,使用海光蓝卡克隆硬盘;
7、从海光蓝卡上执行“分配IP地址”功能,所有机器自动重启,当机器启动起来后,首先会自动申请一IP地址,比如说192.168.1.2,并且所有机器IP不会冲突,从而避免因IP地址冲突造成无法正常获取MAC地址的问题出现。然后自己编写的程序将被调用,并完成自动修改IP,设置机器名称,重新启动的过程。这样,IP地址与计算机名就自动修正好了。(没有海光蓝卡的用户也可以通过手动重启机实现自动修正功能)
三、目前还存在的一些问题
目前还没有完全解决NT Server在克隆中的问题,比如说NT内部会有一唯一标识号,在克隆过程中也被复制了,而且上面的方法不能修改NT Server的AD域名。要想解决这个问题,需要从安装着手。Windows NT 2000的安装说明中有这方面的解决办法。如果哪位需要精益求精的话,可以找这方面的参考资料看看。