You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF应用远程连接服务器及SQL Server的问题求助

问题分析与修复指导

核心问题梳理

  • 混淆RDP与SQL登录逻辑:RDP是远程连接服务器桌面,和SQL Server数据库登录是完全独立的操作,不需要先RDP才能连接SQL
  • SQL连接参数完全缺失:代码中所有SQL连接字符串的用户名、密码、数据库名都是空值,直接导致认证失败
  • 重复连接与错误操作:多次重复建立SQL连接,且存在重复打开已连接对象的错误
  • SQL语句不完整:更新语句缺失数据库名和表名,执行必然失败
  • 日志写入存在隐患:Event Viewer的源未提前创建,会引发额外崩溃

分步修复方案

1. 分离RDP与SQL连接逻辑

RDP功能和SQL连接完全无关,要么将RDP做成独立按钮触发,要么暂时移除(如果不需要):

private bool ConnectToServer(string serverIp, string username, string password)
{
    try
    {
        // 移除不必要的RDP调用,如需保留可单独做按钮触发
        return ConnectToSQLServer(serverIp, username, password, "你的目标数据库名");
    }
    catch (Exception ex)
    {
        LogMessage($"{DateTime.Now} - 连接服务器失败: {ex.Message}\nStackTrace: {ex.StackTrace}");
        return false;
    }
}

2. 修复SQL连接字符串

首先在UI新增两个文本框(Username、Password)用于输入SQL认证信息,然后修正连接字符串:

private bool ConnectToSQLServer(string serverIp, string username, string password, string databaseName)
{
    try
    {
        // 填充完整连接参数,添加超时避免无限等待
        string connectionString = $"Data Source={serverIp};Initial Catalog={databaseName};User ID={username};Password={password};Connect Timeout=30";

        using (SqlConnection sqlConnection = new SqlConnection(connectionString))
        {
            sqlConnection.Open();
            return true;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"SQL Server连接错误: {ex.Message}\nStackTrace: {ex.StackTrace}");
        LogMessage($"SQL Server连接错误: {ex.Message}\nStackTrace: {ex.StackTrace}");
        return false;
    }
}

3. 简化更新按钮逻辑

避免重复建立连接,复用已验证的连接参数:

private void UpdateBalances_Click(object sender, RoutedEventArgs e)
{
    try
    {
        // 从UI获取完整参数
        string serverIp = ServerIpTextBox.Text;
        string username = UsernameTextBox.Text;
        string password = PasswordTextBox.Text;
        string databaseName = "你的目标数据库名"; // 可改为UI输入或配置项

        // 先验证SQL连接有效性
        if (!ConnectToSQLServer(serverIp, username, password, databaseName))
        {
            MessageBox.Show("SQL Server连接失败,请检查参数");
            return;
        }

        string ipAddressInput = DeviceListTextBox.Text;
        string balanceInput = BalanceAmountTextBox.Text;

        // 建立单次连接执行更新
        using (SqlConnection sqlConnection = new SqlConnection($"Data Source={serverIp};Initial Catalog={databaseName};User ID={username};Password={password};Connect Timeout=30"))
        {
            sqlConnection.Open();

            if (UpdateBalances(sqlConnection, ipAddressInput, balanceInput))
            {
                MessageBox.Show("余额更新成功");
                LogMessage("余额更新成功");
            }
            else
            {
                MessageBox.Show("余额更新失败,请检查设备IP和余额值");
                LogMessage("余额更新失败,请检查设备IP和余额值");
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"错误: {ex.Message}");
        LogMessage($"错误: {ex.Message}\nStackTrace: {ex.StackTrace}");
    }
}

4. 修复SQL更新语句

补充缺失的表名,移除重复打开连接的错误:

private bool UpdateBalances(SqlConnection connection, string ipAddressInput, string balanceInput)
{
    string[] ipAddressArray = ipAddressInput.Split(',');

    if (decimal.TryParse(balanceInput, out decimal newBalance))
    {
        try
        {
            // 连接已在外部打开,无需重复调用Open()
            foreach (string ipAddress in ipAddressArray)
            {
                // 替换为实际表名,比如dbo.MachineInfo
                SqlCommand command = new SqlCommand($"UPDATE dbo.你的表名 SET current_balance = @NewBalance WHERE machine_name = @IPAddress", connection);
                command.Parameters.AddWithValue("@NewBalance", newBalance);
                command.Parameters.AddWithValue("@IPAddress", ipAddress.Trim());

                int rowsAffected = command.ExecuteNonQuery();
                LogMessage($"{DateTime.Now} - 更新设备 {ipAddress.Trim()},影响行数: {rowsAffected}");
            }

            return true;
        }
        catch (Exception ex)
        {
            LogMessage($"更新错误: {ex.Message}\nStackTrace: {ex.StackTrace}");
            MessageBox.Show($"更新错误: {ex.Message}");
            return false;
        }
    }
    else
    {
        MessageBox.Show("无效的余额输入,请输入数字");
        LogMessage("错误: 无效的余额输入,请输入数字");
        return false;
    }
}

5. 修复日志写入问题

处理Event Viewer源不存在的情况,同时修改日志目录避免权限问题:

private void LogMessage(string message)
{
    string logDirectory = @"C:\BalanceUpdaterLogs";
    string logFileName = "BalanceUpdaterLog.txt";

    if (!Directory.Exists(logDirectory))
    {
        Directory.CreateDirectory(logDirectory);
    }

    string logFilePath = Path.Combine(logDirectory, logFileName);
    File.AppendAllText(logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: {message}\n");

    // 修复Event Log写入逻辑
    try
    {
        if (!EventLog.SourceExists("BalanceUpdater"))
        {
            EventLog.CreateEventSource("BalanceUpdater", "Application");
        }
        using (EventLog eventLog = new EventLog("Application"))
        {
            eventLog.Source = "BalanceUpdater";
            eventLog.WriteEntry($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: {message}", EventLogEntryType.Error);
        }
    }
    catch (Exception ex)
    {
        File.AppendAllText(logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: 事件日志写入失败: {ex.Message}\n");
    }
}

额外建议

  • 先用SQL Server Management Studio手动验证连接参数,确认IP、用户名、密码、数据库名可以正常访问,排除网络/权限问题
  • 添加UI输入验证:检查所有输入框是否为空,避免空值传入逻辑
  • 如果服务器属于域环境,可考虑使用Windows身份认证(Integrated Security=True),无需输入用户名密码

内容的提问来源于stack exchange,提问作者Nore17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 23:07:49