3

I am deploying SQL Server Express with my application and I need to have C# code that changes the TCP/IP properties without changing them in SQL Server Configuration Manager.

The following code stops SQL Server then it changes the tcp port to 1433 and then starts SQL Server again. The code works fine on a Windows XP machine; however, it errors out on a Windows 7 machine. The error occurs on the prot.Alter(); line.

try
{
    Service Mysvc = mc.Services["MSSQL$SQL" + machineName];

    if (Mysvc.ServiceState == ServiceState.Running)
    {
       MessageBox.Show("Stopping Service","PMP");
       Mysvc.Stop();
    }

    ServerInstance s = mc.ServerInstances["SQL" + machineName];
    ServerProtocol prot = s.ServerProtocols["Tcp"];
    prot.IPAddresses[0].IPAddressProperties["TcpPort"].Value = "1433";
    prot.Alter();

    MessageBox.Show("Starting Service","PMP");
    Mysvc.Start();
}
catch (Exception e)
{
    MessageBox.Show("Error in setting TCP Port " + e.ToString(),"PMP");
}

The following error message is what I receive when I run it on a Windows 7 machine:

SqlServer.Management.Smo.FailedOperationException: Alter failed. ---> Microsoft.SqlServer.Management.Smo.FailedOperationException: SetStringValue failed for ServerIPAddress 'IPAll'. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Management.ManagementObject.MapOutParameters(Object[] args, ManagementBaseObject >outParams, IWbemClassObjectFreeThreaded outParamsClass)
at System.Management.ManagementObject.InvokeMethod(String methodName, Object[] args)
at Microsoft.SqlServer.Management.Smo.Wmi.WmiSmoObject.InvokeMgmtMethod(ManagementObject mo, >ManagementOperationObserver observer, String methodName, Object[] parameters)

--- End of inner exception stack trace ---
at Microsoft.SqlServer.Management.Smo.Wmi.WmiSmoObject.InvokeMgmtMethod(ManagementObject mo, >ManagementOperationObserver observer, String methodName, Object[] parameters)
at Microsoft.SqlServer.Management.Smo.Wmi.WmiSmoObject.AlterProtocolProperties (ProtocolPropertyCollection protocolProperties)
at Microsoft.SqlServer.Management.Smo.Wmi.ServerIPAddress.AlterImplWorker()
--- End of inner exception stack trace ---
at Microsoft.SqlServer.Management.Smo.Wmi.ServerIPAddress.AlterImplWorker()
at Microsoft.SqlServer.Management.Smo.Wmi.ServerProtocol.AlterImplWorker()
at Microsoft.SqlServer.Management.Smo.Wmi.ProtocolBase.Alter()
--- End of inner exception stack trace ---
at Microsoft.SqlServer.Management.Smo.Wmi.ProtocolBase.Alter()

4

2 回答 2

1

UAC 是这里的问题。以管理员身份运行将解决此问题。

于 2014-05-06T19:48:30.363 回答
0

该类Service不允许您在继续下一步操作之前等待服务启动或停止。正如您的代码所代表的那样,该服务被发送一个停止命令,但在服务停止之前继续执行。

您可以通过重构类来解决此问题ServiceController

using Microsoft.SqlServer.Management.Smo.Wmi;

const string instanceName = "SQLEXPRESS";

var managedComputer = new ManagedComputer();

var serviceController = new ServiceController(string.Concat("MSSQL$", instanceName));

var serverInstance = managedComputer.ServerInstances[instanceName];

var serverProtocol = serverInstance?.ServerProtocols["Tcp"];

var ipAddresses = serverProtocol?.IPAddresses;

if (ipAddresses != null)
{
    for (var i = 0; i < ipAddresses?.Count; i++)
    {
        var ipAddress = ipAddresses[i];

        if (!string.Equals(ipAddress.Name, "IPAll"))
        {
            continue;
        }

        if (serviceController.Status == ServiceControllerStatus.Running)
        {
            serviceController.Stop();

            serviceController.WaitForStatus(ServiceControllerStatus.Stopped);
        }

        ipAddress.IPAddressProperties["TcpDynamicPorts"].Value = "0";
        ipAddress.IPAddressProperties["TcpPort"].Value = "1433";

        serverProtocol.Alter();

        break;
    }
}

if (serviceController.Status == ServiceControllerStatus.Running)
{
    return;
}

serviceController.Start();

serviceController.WaitForStatus(ServiceControllerStatus.Running);
于 2015-04-28T17:45:54.233 回答