Change IP related values due to WAN design change

Discussion in 'Scripting' started by Dick Wade, Mar 30, 2005.

  1. Dick Wade

    Dick Wade Guest

    Hi all,

    I am a solo IT person for 108 users on a Windows 2000 Server/Windows 2000
    Professional. Our county changed it's network design which requires that I
    make quite a few IP address/subnet changes on all of our devices. The
    county IP staff just informed me of this change yesterday and it will be
    switched over at 5:00pm CDT today.

    I need help with a vbs script that will touch all client machines and
    network printers on my network (which will be on but not logged into Windows
    2000 Professional) to do the following:

    1. Make modifications to a configuration file (completed)

    2. On failure of the modification

    a. Log host name and "failed cfg modification."

    b. Send e-mail to myself

    3. On success log host name and "cfg modification complete."

    4. Change DNS Server address

    5. Change Default Gateway address

    6. Change IP address on static addresses keeping value the last octet to the
    right but changing the first three to the new subnet address (subnet mask
    remains the same on all).

    7. Log success with machine name and "TCP/IP changes complete."

    8. Do a lease refresh for all leased IP addresses.

    9. Report completion of script and open log file in Notepad for viewing and
    printing.

    James
     
    Dick Wade, Mar 30, 2005
    #1
    1. Advertisements

  2. Dick Wade

    Jim Vierra Guest

    Now is the time to move all machines to DHCP. Use infinite leases for the
    permanent addresses. Next time you only have to change DHCP settings.
     
    Jim Vierra, Mar 31, 2005
    #2
    1. Advertisements

  3. Dick Wade

    Dick Wade Guest

    Good suggestion Jim. Won't help me right now.
     
    Dick Wade, Mar 31, 2005
    #3
  4. Hi Dick,
    It's no good requesting such a detailed script when you say it has to be
    done by 5pm yesterday (but see below anyway).

    The answer is that "yes" you can change IP addresses on dozens of
    Windows 2000 computers using a script. I didn't read the rest of your
    post in much detail. Do you really expect someone to write a script for
    you that does things like "e-mail you if there's a problem"? I don't
    think so.

    Assuming you're the domain admin, and don't have any silly firewalls or
    XP-SP2 installed, you can use the WMI Win32_NetworkAdapterConfiguration
    class. It has methods for getting and setting items such as the gateway
    and subnet mask. I've used this in real life on a big network. Bear in
    mind your script will lose the connection as soon as the subnet changes,
    so program carefully to allow for this. I don't know about "refreshing
    leases" - I've never done this.

    I've posted some code blocks below, but you'll have to co-ordinate these
    into a meaningful fully working script yourself. I assume you know how
    to recurse your text file into an array. You could adjust the _trace()
    routine to provide logging to file if you want, but when I ran it in
    real life, I just ran under CScript and noted any errors.

    * BEWARE OF LINE WRAP *

    ----- start ----- start ----- start -----

    // NetAdapters2.js

    // List of Computers to work with
    // - populate from text file in real life
    var arrCmpNames = new Array();
    arrCmpNames.push("Comp1");
    arrCmpNames.push("Comp2");

    // New Settings - populate the NetworkSettings object
    var newSettings = new NetworkSettings();
    newSettings.DefaultIPGateway.push("122.82.39.242");
    newSettings.IPSubnet.push("255.255.248.0");
    newSettings.DNSServerSearchOrder.push("122.82.37.145");
    newSettings.DNSServerSearchOrder.push("122.82.37.146");
    newSettings.WINSPrimaryServer = "122.82.37.145";
    newSettings.WINSSecondaryServer = "122.82.37.146";
    newSettings.DNSDomain = "";
    newSettings.WINSEnableLMHostsLookup = false;
    newSettings.FullDNSRegistrationEnabled = true;

    // Keep this global for efficiency - used for SAFEARRAY conversions
    var oDict = new ActiveXObject("Scripting.Dictionary");

    // Do the work - Enum list of computers
    var oLoc = new ActiveXObject("WbemScripting.SWbemLocator");
    for(var i in arrCmpNames) {
    var strThisCmp = arrCmpNames;
    _trace("\nTrying to get Adapter for " + strThisCmp);
    var oSvc = getService(strThisCmp);
    if (!oSvc) {
    _trace("Failed to get service for " + strThisCmp);
    continue;
    }

    // We should have a reliable connection at this point so get the adapter
    var oAdapter = getAdapter(oSvc);
    if (!oAdapter) {
    _trace("Failed to get adapter for " + strThisCmp);
    continue;
    }

    _trace("Got Adapter " + oAdapter.Caption);

    // Set to new values
    if(!setSettings(oAdapter, newSettings)) {
    _trace("** Could not change settings **");
    }
    }
    oDict = null;
    oSvc = null;
    oLoc = null;
    _trace("Done");

    // ---------- Functions ----------

    // Network settings object (struct)
    function NetworkSettings() {
    this.IPAddress = new Array();
    this.IPSubnet = new Array();
    this.DefaultIPGateway = new Array();
    this.DNSServerSearchOrder = new Array();
    this.WINSPrimaryServer = new String();
    this.WINSSecondaryServer = new String();
    this.DNSDomain = new String();
    this.WINSEnableLMHostsLookup = new Number();
    this.FullDNSRegistrationEnabled = new Number();
    }

    function getService(strCmp) {
    // Try to connect to server
    // Accepts a string computer name
    // Returns a Wbem service object or false on fail;
    var err;

    try
    {
    var oSvc = oLoc.ConnectServer(strCmp, "root\\cimv2");
    }
    catch(err)
    {
    _trace(_formatError(err) + " While connecting to " + strCmp);
    return false;
    }
    return oSvc;
    }

    function getAdapter(oService) {
    // Accepts a computer
    // Returns first IP enabled Adapter or false on fail

    var strWQL = "Select * from Win32_NetworkAdapterConfiguration where
    IPEnabled=TRUE"
    var wbemObjectSet = oService.ExecQuery(strWQL);
    if (wbemObjectSet.Count != 1) {
    _trace("Number of IP Enabled Adapters = " + wbemObjectSet.Count + "
    instead of 1");
    return false;
    }

    // Enum the Adapters - can only be one!
    var e = new Enumerator(wbemObjectSet);
    for(;!e.atEnd();e.moveNext()) {
    var oThisAdapter = e.item();
    // We only want the first adapter
    return(oThisAdapter);
    }
    }

    function setSettings(oAdapter2, oSettings) {
    // Set the Adapter Settings
    // Accepts an Adapter object and a NetworkSettings object
    // Returns true or false
    var result;
    var err;
    var vbAryIP = oAdapter2.IPAddress;

    try {
    // Set up Gateways
    result = oAdapter2.SetGateways(vbConv(oSettings.DefaultIPGateway));
    _trace("Result of setting gateways " + result);

    // Set up WINS
    result = oAdapter2.SetWINSServer(oSettings.WINSPrimaryServer,
    oSettings.WINSSecondaryServer);
    _trace("Result of setting WINS " + result);

    // Set up DNS
    result =
    oAdapter2.SetDNSServerSearchOrder(vbConv(oSettings.DNSServerSearchOrder));
    _trace("Result of setting DNS " + result);

    // * Domain specific *
    // - if it's not blank, make it blank
    if(oAdapter2.DNSDomain) {
    result = oAdapter2.SetDNSDomain(oSettings.DNSDomain);
    _trace("Result of setting non-null DNSDomain " + result);
    }

    } catch(err) {
    _trace(_formatError(err));
    return false;
    }

    try {
    result = oAdapter2.EnableStatic(vbAryIP, vbConv(oSettings.IPSubnet));
    _trace("Result of setting EnableStatic " + result);
    } catch(err) {
    var facility = err.number >> 16 & 0x1FFF;
    var errno = err.number & 0x1FFF;
    _trace("facility is " + facility);
    _trace("errno is " + errno);
    if(facility == 7 && errno == 1726) {
    _trace("RPC Failed setting Subnet - Assuming Success!");
    } else {
    _trace(_formatError(err) + " Setting Subnet");
    return false;
    }
    }

    return true;
    }

    function vbConv(arrJS) {
    // Use Dictionary object to convert JScript Array to SAFEARRAY
    // oDict is a global var

    oDict.RemoveAll();
    for (var i in arrJS) {
    oDict.Add(i, arrJS);
    }
    return oDict.Items();
    }

    function _formatError(objError) {
    // Format a string containing error info
    if (objError.number > 0) {
    var errno = objError.number.toString(16).toUpperCase();
    } else {
    var errno = (objError.number + 0x100000000).toString(16).toUpperCase();
    }
    var strDesc = objError.description;
    var strResult = "Error " + errno + ": " + strDesc;
    return strResult;
    }

    function _trace(strMsg) {
    WScript.Echo(strMsg);
    }
     
    Gerry Hickman, Apr 1, 2005
    #4
  5. Dick Wade

    Jim Vierra Guest

    New code. Unknown network, Thousands of users at stake.

    Too much impact. If the question is coming from someone with little
    scripting knowledge it's a formula for disaster.

    The only good answer is the right answer which is to use DHCP.

    I have fought with many companies and site admins. Eventually I win and
    they convert to DHCP. Now life on the Intranets is much more predictable
    and manageable.

    The of rough and ready "I know IP" ideology dies hard but, come on, this is
    the modern world. For the cost of testing a dangerous script in a big
    network it's worth turning on DHCP and doing the conversions now. The
    subnets are already defined. Now you only need a script that changes the
    DHCP setting and reboots the machine.

    DO it in segments with the script and watch the outcome.

    --
    Jim Vierra
    http://msdn.microsoft.com/theshow/Episode048/default.asp
     
    Jim Vierra, Apr 1, 2005
    #5
  6. Hi Jim,

    I agree with your comments, but many environments insist on fixed IPs
    with good reason, and anyway, he'll still need a similar script to
    switch them all to DHCP and don't forget the DNS and WINS cleaup.

    The code I posted is 95% ready to roll, the only reason it's not
    complete is because it had a few things specific to my network - for
    example last time I ran it, I was also changing the machine domain
    suffix and rebooting! I don't think he wants that bit.

    What you can do, is create an additional NetworkSettings object called
    oldSettings like this

    var oldSettings = new NetworkSettings();

    and fill it with the old settings. This allows you to quickly
    "roll-back" to the old settings if there's a problem. All you have to do
    is test it on 10 machines and then decide if you want to go "network wide".

    It's a useful script to have lying around anyway, but DHCP does have a
    lot of benefits too.
     
    Gerry Hickman, Apr 1, 2005
    #6
  7. Dick Wade

    Jim Vierra Guest

    Properly set up WINS and DNS will take care of their own cleanup nicely.

    The switch to DNS is a much simpler and safer script and it accomplishes
    much more than the original tasking. As far as "Best Practices" goes it
    places the system under much greater management and control for the future
    at no extra cost.

    Staging the changeover by doing, say, one segment per hour , should allow
    WINS and DNS to keep up nicely. It depends on the segmenting of the
    network. Unfortunately, large networks with physically handed out IPs tend
    to not be segmented for security.. After DHCP is implemented then
    segmenting becomes an easy exercise.

    I bet it can be done with zero user impact. If it can't then using a script
    to do the proposed will definitely be a disaster.

    I have hosted these kinds of issues before. I have never heard an argument
    for workstations that proves that static IPs are of any advantage. Even
    resources like printers and file servers gain when they can be moved to
    DHCP. Just think of the added flexibility of the network when you have
    complete central control.

    You can further control IPs by requiring that clients are quarantined prior
    to obtaining an address. This gives the control that most network security
    people require. Quarantining was always available but not automatic. Now it
    is simplified in Windows Server 2003 SP1. Now you don't need scripts to
    notify you when a new client has gotten a quarantined address. You just get
    a request to allow or disallow a client on the network. From that point
    until you change the DHCP rules the client has the same address.

    Control, convenience and accountability.
     
    Jim Vierra, Apr 3, 2005
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.