使用C#更改SQL Server Express的TCP/IP端口

3

我正在部署SQL Server Express,并需要编写C#代码来更改TCP/IP属性,但不希望在SQL Server配置管理器中更改它们。

以下代码停止SQL Server,然后将tcp端口更改为1433,最后再次启动SQL Server。该代码在Windows XP机器上运行良好;但是,在Windows 7机器上出现错误。错误发生在prot.Alter();行。

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");
}

当我在Windows 7机器上运行时,收到以下错误消息:
SqlServer.Management.Smo.FailedOperationException: 修改失败。 ---> Microsoft.SqlServer.Management.Smo.FailedOperationException: 对于ServerIPAddress 'IPAll'设置StringValue失败。 ---> System.NullReferenceException: 未将对象引用设置到对象的实例。
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)

--- 内部异常堆栈的结尾 ---
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()
--- 内部异常堆栈的结尾 ---
at Microsoft.SqlServer.Management.Smo.Wmi.ServerIPAddress.AlterImplWorker()
at Microsoft.SqlServer.Management.Smo.Wmi.ServerProtocol.AlterImplWorker()
at Microsoft.SqlServer.Management.Smo.Wmi.ProtocolBase.Alter()
--- 内部异常堆栈的结尾 ---
at Microsoft.SqlServer.Management.Smo.Wmi.ProtocolBase.Alter()


当你调用类似这样的代码:Service Mysvc = mc.Services["MSSQL$SQL" + machineName];时,你应该始终检查返回的值(Mysvc)是否真的是!= null,而不仅仅是在它上面调用其他方法!很可能,你的SQL Server服务在Windows 7上有不同的名称,因此这个调用不会返回任何东西,但你接着又在它上面调用了Mysvc.ServiceState... - marc_s
你解决这个问题了吗?是UAC/权限提升的问题吗? - Warren P
UAC是这里的问题,以管理员身份运行可以解决问题。 - Brock Hensley
2个回答

1

这里的问题在于UAC。以管理员身份运行将解决该问题。


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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接