使用脚本管理Windows网络 第七部分:修复神秘的错误

日期: 2008-10-06 作者:Mitch Tulloch翻译:曾少宁 来源:TechTarget中国 英文

本章关于使用脚本管理Windows网络,阐述了当使用我们之前开发的ChangeIPAddress.vbs脚本去修改远程计算机IP地址时,如何修复其产生的“远程程序调用失败”的错误。原文发表于WindowsNetworking.com。 在前面的文章“远程脚本初探”,我们使用之前开发的ChangeIPAddress.vbs脚本,将它修改了后用以修改远程计算机的IP地址。下面就就是我们修改的脚本: Option Explicit Dim objWMIService Dim objNetAdapter Dim strComputer  &n……

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

本章关于使用脚本管理Windows网络,阐述了当使用我们之前开发的ChangeIPAddress.vbs脚本去修改远程计算机IP地址时,如何修复其产生的“远程程序调用失败”的错误。原文发表于WindowsNetworking.com。

在前面的文章“远程脚本初探”,我们使用之前开发的ChangeIPAddress.vbs脚本,将它修改了后用以修改远程计算机的IP地址。下面就就是我们修改的脚本:

Option Explicit
Dim objWMIService
Dim objNetAdapter
Dim strComputer     
Dim strAddress     
Dim arrIPAddress
Dim arrSubnetMask
Dim colNetAdapters
Dim errEnableStatic
If WScript.Arguments.Count = 0 Then
     Wscript.Echo "Usage: ChangeIPAddress.vbs new_IP_address"
     WScript.Quit
End If
strComputer = "xp2"
strAddress = Wscript.Arguments.Item(0)
arrIPAddress = Array(strAddress)
arrSubnetMask = Array("255.255.255.0")
Set objWMIService = GetObject("winmgmts:\" & strComputer & "rootcimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each objNetAdapter in colNetAdapters
     errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)
Next

这一行:

strComputer = "xp2"

告诉我们,脚本的目标计算机名是XP2。远程计算机XP2原先的IP地址是172.16.11.43。

现在,当我们从管理工作站XP上输入ChangeIPAddress.vbs 172.16.11.65运行脚本时,出现了下列情况:

1. 脚本起作用了,如XP2的地址将从172.16.11.43 改为172.16.11.65;

2. 脚本需要花费很长的时间才执行完;

3. 脚本返回以下错误:

C:toolsChangeIPAddress.vbs(23, 6) SWbemObjectEx: The remote procedure call failed.

我们怎样处理这些结果呢?

简单的解决方法

其实我们可以对自己说,“好了,既然它已经起作用了,那么就让我们忽略这个错误吧。”对于这种说法是可以理解的。毕竟,任何现实的管理员都知道IT不是一个精确的科学工作,当我们无法设计妥善的解决方法时,我们往往最终采用“应急方案”来解决问题。

因此,我们该如何忽略这个错误呢?只需在标头节添加以下这一行:

On Error Resume Next

换句话说,我们脚本的头部将是这样的:

Option Explicit
On Error Resume Next
Dim objWMIService
etc.

现在,我们就不会看到错误,而且我们的脚本也可以正常工作了。但是,它仍然需要一段较长的时间来执行,事实上,足足超过一分钟。这又该怎么办呢?

解决错误讯息

错误消息有时是很隐秘的,这是其中的一个。这里是又一个错误消息:

SWbemObjectEx: The remote procedure call failed.

这是产生错误的那一行代码:

errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)

现在这行代码工作了(如,目标计算机IP地址修改了)但它抛出了一个错误,为什么呢?

让我们先设法理解SWebObjectEx的作用。从MSDN上快速搜索到这个网页,上面有这样的说明:

Extends the functionality of SWbemObject. This object adds the Refresh method for SWbemRefresher objects. 

很好。这样看来SWbemObjectEx只是给SWbemObject增加了更多的功能。那么,SWbemObject又是什么呢?

Contains and manipulates a single WMI object class or instance.

那么,这是又意味着什么呢?网页上告诉了我们很多,但是却又相当怪异。但是,简而言之,SWbemObject(以及SWbemObjectEx )是你用于在WMI中管理或查询的。在我们的脚本上,我们正在查询Win32_NetworkAdapterConfiguration类和返回代表计算机网络适配器的colNetAdapters对象集合。因此,这个错误消息所指的SWbemObjectEx(或SWbemObject)仅仅是该对象代表网络适配器本身,即objNetAdapter 。

那么,是SWbemObject导致了错误。为什么呢?

于是,我必须得跟我一些脚本“高手”朋友交谈一下来尝试和解决这个问题。但是,直到现在我所得到的答复都不能完全令人满意。但是,不管怎么说,什么时候曾有过用 “满意”来描述IT管理员工作的吗?

总之,这里的似乎是存在问题的。根据其中的一位高手所言,似乎Windows XP上的更新补丁的“某个东西”可能已经改变了当导致错误的语句执行时返回调用的创建和提交方式。通常情况下,如果Win32_NetworkAdapterConfiguration类的实例对象的EnableStatic方法调用成功完成,它将返回0,这意味着没有错误,而如果调用返回1,那么这意味着需要重新启动(见本页下的“Return Value”的更多信息)。当然,在Windows XP上,当你更改需网络适配器的IP地址时是不需要重新启动的。如果由于某种原因,更新补丁可能已经改变了一些WMI提供者或其他一些内部元素,因此,Windows认为在目标机器采用新的地址之前系统需要重新启动,而这正是导致错误的原因,因为网络适配器配置的机器一直保持不定型的状态,直到机器被重新启动。但是,当目标计算机的网络适配器配置进入这个不确定状态时,由于脚本仍在管理工作站运行,两台主机的RPC连接在脚本完成运行之前便开始了工作。因此,这就产生了错误。

至少目前来说,这是我能够给出的最佳答案,我将继续进行调研。但是,同时让我们看看我们是否能够设法将这个问题隔离开来,即这个错误只有在Win32_NetworkAdapterConfiguration上的 EnableStatic方法才出现,而不是普遍存在的。如果我们尝试写一个脚本对目标机器的网络适配器进行不一样的操作,而不是改变其IP地址呢?例如,改变目标机器的默认网关而不是IP地址?如果这一方法可行,那么至少我们知道,我们可以成功地从管理员工作站上连接远程计算机,并调用WMI方法来改变网络设置。

改变默认网关

在此,我建议你先停止阅读这篇文章,然后重新回到第四部分。在第四部分中,我指出了“如何使用MSDN去学习运用Win32_NetworkAdapterConfiguration类的属性和方法”。我敢打赌,如果你这样做了,你可以自己写出这样的脚本。大胆尝试一下!

中止

很好,现在你已经开始尝试写自己的脚本了。有可能你的脚本能能正常工作,也有可能不行。如果它不行,尝试下面的步骤:

1. 第一步是回到MSDN中关于Win32_NetworkAdapterConfiguration class 类的页面。

2. 在这一页中,寻找与修改网络适配器的网关有联系的方法。快速地查阅这一页你将看到:

SetGateways: Specifies a list of gateways for routing packets destined for a different subnet than the one this adapter is connected to.

这就是我们想要的,所以,点击SetGateways,打开Win32_NetworkAdapterConfiguration class 类页面的SetGateways方法。

3. 在SetGateways方法的这一页上,你将找到问题的解释:
The SetGateways WMI class method specifies a list of gateways for routing packets to a subnet that is different from the subnet that the network adapter is connected to. This method only works when the Network Interface Card (NIC) is in the static IP mode.

你已经知道了在你调用这个方法之前,目标计算机上必须有一个静态的地址。接着往下读,你会发现调用这个方法的句法是这样的:

SetGateways(A,B)

这里A是一个包含网关IP地址的字符串变量,而B是一个从1到9999间指定数据的整数价值。

现在你应该有了足够的信息来编写你的脚本了。最简单的方法就是从你在这一系列的第二部分所开发的原始ChangeIPAddress.vbs脚本上开始,然后对它进行一点修改,直到我们获得以下这样的一个新的脚本(我们称之为ChangeIPAddress.vbs)

'=========================
' NAME: ChangeGateway.vbs
'
'AUTHOR: Mitch Tulloch
'DATE: February 2007
'
'ARGUMENTS:
'1. gateway_address
'2. metric
'=========================-
Option Explicit
Dim objWMIService
Dim objNetAdapter
Dim strComputer 
Dim strGateway 
Dim arrGateway
Dim intMetric
Dim arrMetric
Dim colNetAdapters
Dim errGateway
'Check for missing arguments
If WScript.Arguments.Count = 0 Then
     Wscript.Echo "Usage: ChangeGateway.vbs gateway_address metric"
     WScript.Quit
End If
strComputer = "xp2"
strGateway = Wscript.Arguments.Item(0)
arrGateway = Array(strGateway)
intMetric = Wscript.Arguments.Item(1)
arrMetric = Array(intMetric)
Set objWMIService = GetObject("winmgmts:\" & strComputer & "rootcimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each objNetAdapter in colNetAdapters
     errGateway = objNetAdapter.SetGateways(arrGateway, arrMetric)
Next
'Display result or error code
If errGateway=0 Then
     Wscript.Echo "Adapter's gateway has been successfully changed to " & strGateway
Else
     Wscript.Echo "Changing the adapter's gateway was not successful. Error code " & errGateway
End If

拷贝这个脚本到记事本(关闭自动换行)并另存为ChangeGateway.vbs。现在我们来测试它。让我们登录到远程主机XP2上,打开命令提示符并输入“ipconfig /all”,得到结果如下:

C:>ipconfig /all
Windows IP Configuration
        Host Name . . . . . . . . . . . . : XP2
        Primary Dns Suffix  . . . . . . . : contoso.com
        Node Type . . . . . . . . . . . . : Unknown
        IP Routing Enabled. . . . . . . . : No
        WINS Proxy Enabled. . . . . . . . : No
Ethernet adapter Local Area Connection:
        Connection-specific DNS Suffix  . :
        Description . . . . . . . . . . . : Intel 21140-Based PCI Fast Ethernet
Adapter (Generic)
        Physical Address. . . . . . . . . : 00-03-FF-21-88-8C
        Dhcp Enabled. . . . . . . . . . . : No
        IP Address. . . . . . . . . . . . : 172.16.11.80
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 172.16.11.1
C:>

现在在管理工作站XP上,打开命令提示符,运行新的脚本:

C:tools>ChangeGateway.vbs 172.16.11.2 5
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Adapter's gateway has been successfully changed to 172.16.11.2
C:tools>

脚本大概需要运行5秒钟便结果,而且没有任何错误抛出。(注意我已经在脚本的开头添加了“On Error Resume Next”,所以我看不到任何错误发生。)

现在让我们回到远程机器XP2,再次运行ipconfig /all:

C:>ipconfig /all
Windows IP Configuration
        Host Name . . . . . . . . . . . . : XP2
        Primary Dns Suffix  . . . . . . . : contoso.com
        Node Type . . . . . . . . . . . . : Unknown
        IP Routing Enabled. . . . . . . . : No
        WINS Proxy Enabled. . . . . . . . : No
Ethernet adapter Local Area Connection:
        Connection-specific DNS Suffix  . :
        Description . . . . . . . . . . . : Intel 21140-Based PCI Fast Ethernet
Adapter (Generic)
        Physical Address. . . . . . . . . : 00-03-FF-21-88-8C
        Dhcp Enabled. . . . . . . . . . . : No
        IP Address. . . . . . . . . . . . : 172.16.11.80
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 172.16.11.2
C:>

它起成功了。没有错误,没有问题——我们已经运行一个脚本远程地操作另一个计算机,它修改了目标主机的默认网关。

还有,我们还没有检查跳数是否已经修改了,对吧?这个ipconfig命令并不显示这些信息,但我们可以用netsh命令去得到这些信息:

C:>netsh interface ip show address
Configuration for interface "Local Area Connection"
    DHCP enabled:                         No
    IP Address:                           172.16.11.80
    SubnetMask:                           255.255.255.0
    Default Gateway:                      172.16.11.2
    GatewayMetric:                        5
    InterfaceMetric:                      0
C:>

没错,它也成功了!

作者

Mitch Tulloch
Mitch Tulloch

Mitch Tulloch是一个作家、培训师和Windows服务器操作系统、IIS管理、网络故障修复和安全方面的专业顾问。他已经写了15本书,其中包括:Microsoft Encyclopedia of Networking (Microsoft Press),Microsoft Encyclopedia of Security (Microsoft Press),Windows Server Hacks (O'Reilly),Windows Server 2003 in a Nutshell (O'Reilly),Windows 2000 Administration in a Nutshell (O'Reilly),and IIS 6 Administration (Osborne/McGraw-Hill)。Mitch居住在加拿大的Winnipeg,你可以他的网站www.mtit.com查到更多关于他的书的信息。

翻译

曾少宁
曾少宁

TechTarget中国特约技术编辑,某高校计算机科学专业教师和网络实验室负责人,曾任职某网络国际厂商,关注数据中心、开发运维、数据库及软件开发技术。有多本关于思科数据中心和虚拟化技术的译著,如《思科绿色数据中心建设与管理》和《基于IP的能源管理》等。

相关推荐