Sunday, September 2, 2012

How to rename a Machine name and SQL Server name...


On my current project, we will be soon deploying over 1,000 systems.  All of those systems will start off as a fresh Windows 7 ghost image.  That means that every system will, at first, have the same Machine Name and SQL Server name.  I produce a utility project to automate those manual steps and to, hopefully, save time.

First, I created a class to rename the Machine name.  It uses WMI to perform the change.  See the class towards the bottom of this post.

Then, I created a class to rename the SQL Server. Please note a few things about this code: 1) A Connection String must be created to the local computer's "master" database; and 2) This can probably be refactored so that it is no longer raw SQL being executed on the database server, but rather a few individual calls to get the server name, drop the server, and add the local server back.

The typical connection string looks like:

     data source=.\SQLEXPRESS;Initial Catalog=master;Integrated Security=True;

Finally, I chose to create a command-line utility to manage the process.  I won't bother with the details of that because there isn't really anything exciting about it.  You do want to try to reboot the computer after making the change.

Here is the class for changing the Machine name:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Utility.PostImageConfig
{
    public static class SystemConfiguration
    {
        /// <summary>
        /// Get the name of the current machine
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentMachineName()
        {
            return System.Environment.MachineName;
        }

        /// <summary>
        /// Change the Machine Name if it is different than the new machine name.
        /// </summary>
        /// <param name="newMachineName"></param>
        /// <returns>True if the machine name was changed.</returns>
        public static bool ChangeMachineName(string newMachineName)
        {
            Console.WriteLine();
            string oldMachineName = GetCurrentMachineName();

            bool doChangeName = oldMachineName != newMachineName;

            if (doChangeName)
            {
                Console.WriteLine(Resources.Resources.Trace_MachineNameStarted, oldMachineName, newMachineName);

                var remoteControlObject = new ManagementPath
                                              {
                                                  ClassName = "Win32_ComputerSystem",
                                                  Server = oldMachineName,
                                                  Path =
                                                      oldMachineName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + oldMachineName + "'",
                                                  NamespacePath = "\\\\" + oldMachineName + "\\root\\cimv2"
                                              };

                var localScope = new ManagementScope(remoteControlObject);

                var localSystem = new ManagementObject(localScope, remoteControlObject, null);

                ManagementBaseObject newlocalSystemName = localSystem.GetMethodParameters("Rename");
                var methodOptions = new InvokeMethodOptions();

                newlocalSystemName.SetPropertyValue("Name", newMachineName);


                methodOptions.Timeout = new TimeSpan(0, 10, 0);
                ManagementBaseObject outParams = localSystem.InvokeMethod("Rename", newlocalSystemName, null);
            }
            else
            {
                Console.WriteLine(Resources.Resources.Trace_MachineNameMatches);
            }
            Console.WriteLine();

            return doChangeName;
        }
    }
}


Here is the class for changing the SQL Server name:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Data.SqlClient;


namespace Utility.PostImageConfig
{
    public class SQLConfiguration
    {

        private string GetSqlConnectionString()
        {
            return ConfigurationManager.ConnectionStrings["MasterConnectionString"].ConnectionString;
        }


        /// <summary>
        /// Change the SQL Server Name
        /// </summary>
        /// <param name="oldMachineName"></param>
        /// <param name="newMachineName"></param>
        public void ChangeSQLServerName(string oldMachineName, string newMachineName)
        {
            Console.WriteLine(Resources.Resources.Trace_SQLStarted, oldMachineName, newMachineName);

            using (SqlConnection conn = new SqlConnection(GetSqlConnectionString()))
            {
                StringBuilder sqlSB = new StringBuilder();
                sqlSB.AppendLine("@DECLARE @oldServername varchar(75)");
                sqlSB.AppendLine("@DECLARE @newServername varchar(75)");
                sqlSB.AppendLine("SET @oldServername = @@SERVERNAME");
                sqlSB.AppendFormat("SET @newServername = REPLACE(@oldServername,'{0}','{1}')\n", oldMachineName, newMachineName);
                sqlSB.AppendLine("IF (@oldServername <> @newServername)");
                sqlSB.AppendLine("BEGIN");
                sqlSB.AppendLine("     exec('exec sp_dropserver [' + @oldServername + ']')");
                sqlSB.AppendLine("     exec('exec sp_addserver [' + @newServername + '], local')");
                sqlSB.AppendLine("     SELECT 1");
                sqlSB.AppendLine("END");
                sqlSB.AppendLine("ELSE");
                sqlSB.AppendLine("BEGIN");
                sqlSB.AppendLine("     SELECT 0");
                sqlSB.AppendLine("END");

                Console.WriteLine(sqlSB.ToString());

                conn.Open();
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.CommandText = sqlSB.ToString();
                int result = (int)cmd.ExecuteScalar();
                // interpret the result
                if (result == 0)
                {
                    Console.WriteLine(Resources.Resources.Trace_SQLNotChanged);
                }
                else
                {
                    Console.WriteLine(Resources.Resources.Trace_SQLChanged);
                }
            }
            Console.WriteLine(Resources.Resources.Trace_SQLFinished, oldMachineName, newMachineName);

        }
    }
}


No comments:

Post a Comment