代码之家  ›  专栏  ›  技术社区  ›  jchristo

释放时服务炸弹爆炸[重复]

  •  -2
  • jchristo  · 技术社区  · 6 年前

    希望我能在这里得到一些帮助。

    在开发服务器上,我在Visual Studio 2013社区中创建了一个C#windows服务。我已经在调试模式下对其进行了测试: In Main()

    #if DEBUG
       ...run debug code...
    #else
       ...run service code...
    #endif
    

    在调试模式下,它运行得非常好。然后,我添加了一个安装程序类,并在 相同的 并在“服务”窗口中启动它。然而,它没有任何作用。我检查了事件日志并看到以下错误消息:

    Application: SharenetIFF.exe
    Framework Version: v4.0.30319
    Description: The process was terminated due to an unhandled exception.
    Exception Info: System.NullReferenceException
    at SharenetIFF.RunValues.GetRunValues()
    at SharenetIFF.SearchFiles.LookforIFFFiles(Int32)
    at SharenetIFF.Program.DoThis()
    at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
    at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
    at System.Threading.ThreadHelper.ThreadStart()
    

    以下是RunValues中的代码:

    class RunValues
    {
        public int id { get; set; }
        public int runTimeSpan { get; set; }
        public int numberOfRunTime { get; set; }
        private SqlConnection myCon = new SqlConnection();
    
        public List<int> GetRunValues()
        {
            List<int> values = null;
            string destPath = "";
    
            try
            {
                string mySQL = "select RunFreq, RunTimes from IFFRunValues";
    
                myCon.ConnectionString = ConfigurationManager.ConnectionStrings["DatabaseConn"].ConnectionString;                
                myCon.Open();
    
                SqlCommand myCmd = new SqlCommand(mySQL, myCon);
                SqlDataReader runValuesReader = myCmd.ExecuteReader();
                if (runValuesReader.HasRows)
                {
                    while (runValuesReader.Read())
                    {
                        runTimeSpan = Convert.ToInt16(runValuesReader["RunFreq"]);
                        numberOfRunTime = Convert.ToInt16(runValuesReader["RunTimes"]);
                    }
                    values = new List<int>();
                    values.Add(runTimeSpan);
                    values.Add(numberOfRunTime);
                }
                runValuesReader.Close();
                myCon.Close();
                runValuesReader.Dispose();
                myCmd.Dispose();
                myCon.Dispose();
            }
            catch (Exception ex)
            {
                destPath = Path.Combine("C:\\",  "error_log.txt");
                File.AppendAllText(destPath, ex.Message);
                values.Clear();
            }
    
            return values;
        }
    }
    

    我认为它在连接字符串上失败了,主要是因为这里没有其他内容。但不知道为什么。所有的代码都在try/catch块中,那么如何可能出现未处理的异常呢?如果将服务发布到开发它的同一台开发计算机上,那么如果在visual studio之外运行,服务是否需要不同的权限?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Zohar Peled    6 年前

    这开始只是一个评论,但时间太长了,所以。。。

    这个方法应该做什么还不完全清楚。一方面,填充实例的属性。另一方面,您返回 int ,但将值转换为 Int16 (那是 short )而不是to Int32 。您填充该列表 之后 循环,这意味着您只获得select语句返回的最后一个值,它没有order by子句,这意味着行以任意顺序返回,并且您不使用 Id 不动产。

    另外,请注意Steve关于将文件直接保存到 C:\

    那是在我们还没接触到你用一个字段 SQLConnection ,而不是 using 语句,该语句将确保在处理完后将其关闭并进行处置,或者确保仅处理 try 块,这意味着如果在代码到达之前出现异常,则不会处理任何内容,或者数据库中的表列可能为空,因此 Convert.ToInt 如果读取器包含 DBNull.Value 而不是实际值。

    也就是说,这里是当前代码的改进版本。我只是对它进行了修改,使其能够正确地处理所有内容,安全地从dataReader获取值,而不是抛出 NullReferenceException ,但正如我所说的,我不太清楚你用这种方法试图实现什么。

    class RunValues
    {
        public int id { get; set; }
        public int runTimeSpan { get; set; }
        public int numberOfRunTime { get; set; }
    
        public List<int> GetRunValues()
        {
            var values = new List<int>();
    
            // I'm guessing it needs " where id = @id" here...
            var mySQL = "select RunFreq, RunTimes from IFFRunValues"; 
            using(var myCon = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConn"].ConnectionString))
            {
                using(var myCmd = new SqlCommand(mySQL, myCon))
                {
                    try
                    {
                        myCon.Open();
                        SqlDataReader runValuesReader = myCmd.ExecuteReader();
                        if (runValuesReader.HasRows)
                        {
                            while (runValuesReader.Read())
                            {
                                runTimeSpan = runValuesReader.GetValueOrDefault<int>("RunFreq");
                                numberOfRunTime = runValuesReader.GetValueOrDefault<int>("RunTimes");
                                values.Add(runTimeSpan);
                                values.Add(numberOfRunTime);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        var destPath = Path.Combine("C:\\",  "error_log.txt");
                        File.AppendAllText(destPath, ex.Message);
                        values.Clear();
                    }
                }
            }            
            return values;
        }
    }
    

    这个 GetValueOrDefault<T> 是一个扩展方法,我已经使用了很长时间,甚至记不起第一次在哪里遇到它-下面是包含它的类:

    /// <summary>
    /// Provides extension methods for IDataReader.
    /// </summary>
    public static class IDataReaderExtensions
    {
        /// <summary>
        /// Gets the value of type T from the column specified by the index parameter, or default(T) if it's null.
        /// </summary>
        /// <typeparam name="T">The type of the value to get.</typeparam>
        /// <param name="reader">An instance of a class implementing IDataReader.</param>
        /// <param name="index">The index of the column from where to get the value.</param>
        /// <returns>The value of type T from the specified column, default(T) if null.</returns>
        public static T GetValueOrDefault<T>(this IDataReader reader, int index)
        {
            return (Convert.IsDBNull(reader[index])) ? default(T) : (T)reader.GetValue(index);
        }
    
        /// <summary>
        /// Gets the value of type T from the column specified by the name parameter, or default(T) if it's null.
        /// </summary>
        /// <typeparam name="T">The type of the value to get.</typeparam>
        /// <param name="reader">An instance of a class implementing IDataReader.</param>
        /// <param name="name">The name of the column from where to get the value.</param>
        /// <returns>The value of type T from the specified column, default(T) if null.</returns>
        public static T GetValueOrDefault<T>(this IDataReader reader, string name)
        {
            return reader.GetValueOrDefault<T>(reader.GetOrdinal(name));
        }
    }