I am trying to capture the queries via SQL Server trace using C# that are getting executed during my automation test run. When I run the below code ,I am getting the exception
'Failed to initialize object as reader.'
So In this case what can be done?
Source Code
class Program
{
static void Main(string[] args)
{
using (Impersonation user = new Impersonation("xxx", "xxx","xxx"))
{
ConnectionInfoBase conninfo = new SqlConnectionInfo();
((SqlConnectionInfo)conninfo).ServerName = "xxxxx";
((SqlConnectionInfo)conninfo).UseIntegratedSecurity = true;
TraceServer trace = new TraceServer();
trace.InitializeAsReader(conninfo, #"Standard.tdf");
for (int count = 0; count < 30; count++)
{
while (trace.Read())
{
Console.WriteLine(trace["TextData"]);
}
Thread.Sleep(1000);
}
}
}
}
Inner Exception
SqlTraceException: Failed to get SQL Tools directory path from InstAPI....
This exception was originally thrown at this call stack:
Microsoft.SqlServer.Management.Trace.TraceUtils.GetSqlToolsBinaryPath(string)
Microsoft.SqlServer.Management.Trace.TraceUtils.CreateInstance(string, string)
Microsoft.SqlServer.Management.Trace.TraceServer.InitializeAsReader(Microsoft.SqlServer.Management.Common.ConnectionInfoBase, string)
Related
The below code isn't logging to my database. Is it because the console application closes too soon and if so how can I prevent this?
private static ILogger _logger;
static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
{
_logger.Error((Exception)e.ExceptionObject);
}
private static void Main(string[] args)
{
var container = new Container();
_logger = container.GetInstance<ILogger>();
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
throw new Exception("test");
You can call LogManager.Shutdown() before leaving your UnhandledExceptionTrapper method. This calls internally LogManager.Flush() which
Flush any pending log messages (in case of asynchronous targets) with the default timeout of 15 seconds.
see NSLog Flush documentation.
Additional Troubleshooting
In the debug console, error messages are displayed if, for example, SQL errors occur on the connection, but by default you do not see if you have an invalid configuration.
Since NLog offers extensive configuration options, it is easy to make a small configuration errors that results in no logging. A typical example would be an incorrect ConnectionString or DBProvider.
As an example, suppose you have configured an incorrect DBProvider.
You can e.g call
LogManager.GetCurrentClassLogger().Debug("test logging");
LogManager.Flush();
and it would just silently fail.
However, if you insert
LogManager.ThrowExceptions = true;
before the test log call, you will see appropriate messages in the debug console. For example, if you have an invalid DBProvider like Npgsql.NpgsqlConnection1, Npgsql (note the invalid 1 in it), you would see
Unhandled exception. NLog.NLogRuntimeException: Exception occurred in NLog
---> NLog.NLogRuntimeException: Target Database Target[nlog-db] failed to initialize.
---> System.TypeLoadException: Could not load type 'Npgsql.NpgsqlConnection1' from assembly 'Npgsql'.
which would give a clear indication of what went wrong.
More Diagnostics
To see even more diagnostics, you can add the following lines:
InternalLogger.LogToConsole = true;
InternalLogger.LogLevel = LogLevel.Trace;
Among other things, you can see when the connection is opened, what data is written and information about flushing, a small sample excerpt:
2022-03-11 08:47:56.8428 Trace DatabaseTarget(Name=nlog-db): Open connection.
2022-03-11 08:47:57.0275 Trace DatabaseTarget(Name=nlog-db): Executing Text: insert into "public"."log_table"(time_stamp,level,logger,message,stacktrace) values(CAST(#time_stamp AS timestamp),#level,#logger,#message,#stacktrace);
2022-03-11 08:47:57.0380 Trace DatabaseTarget: Parameter: '#time_stamp' = '2022-03-11T08:47:56.837' (String)
2022-03-11 08:47:57.0380 Trace DatabaseTarget: Parameter: '#level' = 'Debug' (String)
2022-03-11 08:47:57.0380 Trace DatabaseTarget: Parameter: '#logger' = 'ConsoleDBLog.Program' (String)
2022-03-11 08:47:57.0395 Trace DatabaseTarget: Parameter: '#message' = 'test logging' (String)
2022-03-11 08:47:57.0415 Trace DatabaseTarget: Parameter: '#stacktrace' = '' (String)
2022-03-11 08:47:57.1099 Trace DatabaseTarget(Name=nlog-db): Finished execution, result = 1
2022-03-11 08:47:57.1111 Trace DatabaseTarget(Name=nlog-db): Close connection (KeepConnection = false).
2022-03-11 08:47:57.1167 Debug LogFactory Flush with timeout=15 secs
Self-Contained Example
using System;
using NLog;
using NLog.Targets;
namespace ConsoleDBLog;
internal static class Program
{
private static ILogger? _logger;
static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
{
_logger?.Error((Exception?) e.ExceptionObject, "unhandled exception");
LogManager.Shutdown();
}
private static void Main()
{
SetupDB_NLOG();
_logger = LogManager.GetCurrentClassLogger();
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
throw new Exception("test");
}
static void SetupDB_NLOG()
{
DatabaseTarget target = new DatabaseTarget();
target.Name = "nlog-db";
target.DBProvider = "Npgsql.NpgsqlConnection, Npgsql";
target.ConnectionString = "Server=127.0.0.1;Port=5432;User Id=stephan;Password=;Database=stephan;";
target.CommandText =
"insert into \"public\".\"log_table\"(time_stamp,level,logger,message,stacktrace) values(CAST(#time_stamp AS timestamp),#level,#logger,#message,#stacktrace);";
var param = new DatabaseParameterInfo
{
Name = "#time_stamp",
Layout = "${date:format=yyyy-MM-ddTHH\\:mm\\:ss.fff}"
};
target.Parameters.Add(param);
param = new DatabaseParameterInfo
{
Name = "#level",
Layout = "${level}"
};
target.Parameters.Add(param);
param = new DatabaseParameterInfo
{
Name = "#logger",
Layout = "${logger}"
};
target.Parameters.Add(param);
param = new DatabaseParameterInfo
{
Name = "#message",
Layout = "${message}"
};
target.Parameters.Add(param);
param = new DatabaseParameterInfo
{
Name = "#stacktrace",
Layout = "${exception:format=stacktrace}"
};
target.Parameters.Add(param);
NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Debug);
//Uncomment the following lines to see things that would silently fail and
//to get more diagnostic debug output about what is actually running.
// InternalLogger.LogToConsole = true;
// InternalLogger.LogLevel = LogLevel.Trace;
// LogManager.ThrowExceptions = true;
// LogManager.GetCurrentClassLogger().Debug("test logging");
// LogManager.Flush();
}
}
Which gives the followoing entries in the DB:
I have a C# Console application that will be run from SQL Server agent. If the console application fail, i would like to have the error message shown in the SQL Server agent history log. But it doesnt seem to grab anything from the console app. It only says:
Message Executed as user: domain\account. The step did not generate any output. Process Exit Code 1. The step failed.
So how should i built my console application so that the SQL Server agent would print the error message instead of the "The step did not generate any output." message?
Here's a simple code that i have tested:
class Program
{
static void Main(string[] args)
{
var x = 0;
// division by zero error
var y = 1 / x;
//Console.Error.WriteLine("error message");
}
}
As stated by #ChrisK, to correctly build a Console Application that will return an error message to SQL Server Agent, the code must use a try/catch and write the error message to the Console.Error
Writing the code that way solved my problem:
static int Main(string[] args)
{
try
{
var x = 0;
var y = 1 / x;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return 1;
}
return 0;
}
I have an optimistic concurrency method from which I need to return a value. I am getting an error indicating the return variable is not in scope.
private static string GenerateCustomerId(string contextPath)
{
var retryMaxCount = 3; // maximum number of attempts
var cycles = 0; // current attempt
Exception exception = null; // inner exception storage
while (cycles++ < retryMaxCount) // cycle control
{
try
{
Content sequenceContent = Content.Load(contextPath);
int currentSequence;
int.TryParse(sequenceContent["LastSequenceNo"].ToString(), out currentSequence);
currentSequence++;
string currentDate = DateTime.Now.ToString("ddMMyyyy");
string customerID = string.Format("{0}{1}", currentDate, currentSequence);
//Save back to content with new update
sequenceContent["LastSequenceNo"] = currentSequence.ToString();
sequenceContent["LastCustomerID"] = customerID;
sequenceContent.Save();
}
catch (NodeIsOutOfDateException e)
{
exception = e; // storing the exception temporarily
}
return customerID; //"**Customer ID does not exist in current context**"
}
// rethrow if needed
if (exception != null)
throw new ApplicationException("Node is out of date after 3 attempts.", exception);
}
How can I return the value of CustomerID?
Just move the return statement into the try block - and then add an extra throw statement at the very end of the method; if you ever reach the end of the method without an exception, that indicates something very strange going on. Or you could just make the final throw unconditional, of course:
private static string GenerateCustomerId(string contextPath)
{
var retryMaxCount = 3; // maximum number of attempts
Exception exception = null; // inner exception storage
for (int cycles = 0; cycles < retryMaxCount; cycles++)
{
try
{
...
// If we get to the end of the try block, we're fine
return customerID;
}
catch (NodeIsOutOfDateException e)
{
exception = e; // storing the exception temporarily
}
}
throw new ApplicationException(
"Node is out of date after " + retryMaxCount + " attempts.", exception);
}
As an aside, I'd personally avoid ApplicationException - I'd either just rethrow the original exception, or create a dedicated RetryCountExceeded exception or something similar. ApplicationException was basically a mistake on Microsoft's part, IMO.
(Also note that I've converted your while loop into a for loop for simplicity. I would certainly find the for loop easier to read and understand, and I suspect most other developers would feel the same way. I'd consider making retryMaxCount a constant in your class rather than a local variable, too.)
I read in this post (http://bytes.com/topic/c-sharp/answers/238006-cannot-catch-exception-thread#post970280) that: 'Thrown exceptions are stack-bound objects. Since every thread has its
own stack, an exception thrown in thread A cannot suddenly appear in
thread B'
But I have a project in which exactly this seems to happen. i am kind of desperate to find the source of my problem. what i am doing is calling 10 threads, of which each one runs several tools simultaneously. each tool is run in yet another thread by starting an executable in a process. this means if i have e.g. 2 tools i will have 10x2 threads in total. the problem is the following: if an exception is thrown, e.g. when one of the tool threads fails and i want to catch it inside the same thread, it happens that any of the threads catches the exception. I verify that by letting the run method output by letting the runTool function include the threadId and toolId in the exception that it throws and comparing the output from the throw and the catch
here the simplified code:
class Worker
{
private ManualResetEvent[] threadResetEvents;
private ManualResetEvent[][] toolResetEvents;
private Tool[] tools;
public int stopped = false;
public void run(int threadNo)
{
threadResetEvents = new ManualResetEvent[threadNo];
toolResetEvents = new ManualResetEvent[threadNo][];
for (int i = 0; i < threadNo; i++)
{
threadResetEvents[i] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(fillDb), (object)i);
}
sendToObservers("Filling database...");
WaitHandle.WaitAll(threadResetEvents);
}
private void fillDb(object obj)
{
int threadId = (int)obj;
while (!stopped)
{
toolResetEvents[threadId] = new ManualResetEvent[tools.Length];
for (int i = 0; i < tools.Length; i++)
{
toolResetEvents[threadId][i] = new ManualResetEvent(false);
ToolInfoObject info = new ToolInfoObject(threadId, i);
ThreadPool.QueueUserWorkItem(new WaitCallback(runTool), info);
}
WaitHandle.WaitAll(toolResetEvents[threadId]);
}
}
private void runTool(object obj)
{
ToolInfoObject info = (ToolInfoObject) i;
int threadId = info.threadId;
int toolId = info.toolId;
try
{
tools[toolId].runTool(threadId, toolId);
}
catch (Exception e)
{
Console.WriteLine("Exception caught in Thread " + threadId + ", Tool " + toolId + ": " + e.GetBaseException());
}
}
}
class ToolInfoObject
{
public int threadId;
public int toolId;
public ToolInfoObject(int thread, int tool)
{
this.threadId = thread;
this.toolId = tool;
}
}
I'd be grateful for any help
EDIT:
in more detail, the problem shows up when an IOException is thrown. i let every tool create a directory and files in it based on the thread number. if a file is not accessible it will lead to a message like this:
Exception caught in Thread 1, Tool 0: System.IO.FileNotFoundException: Die Datei "C:\tmpdir\3\log.txt" konnte nicht gefunden werden.
which means the exception actuall happened in thread 3, but was caught in thread 1
Check if your Tool is threadsafe. If it is not this can lead to your problem.
I am developing Windows Phone 7 Silverlight Application. I want to do Application Level error handling instead of writing try...catch... in all methods. I need to extract Method Name, Class Name and Line Number where the actual error occurred. Below is the demo code. In Application_UnhandledException event, I am expecting Method = "GenerateError" and Class = "ExceptionTesting". Also, I want to get LineNumber where the actual error occurred (this is not shown in code).
Code to generate Error:
public partial class ExceptionTesting : PhoneApplicationPage
{
// Generate Error to Test Exception Handling
private void GenerateError()
{
Int16 i = Convert.ToInt16("test");
}
}
Code that Handles Application Level Exception:
// Code to execute on Unhandled Exceptions
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
StackTrace st = new StackTrace();
var query = st.GetFrames() // get the frames
.Select(frame => new
{
Method = frame.GetMethod(),
Class = frame.GetMethod().DeclaringType
});
foreach (var q in query)
{
if (q.Method.Name.Contains("GenerateError"))
{
MessageBox.Show("Class: " + q.Class + ", Method: " + q.Method);
}
}
if (System.Diagnostics.Debugger.IsAttached)
{
// An unhandled exception has occurred; break into the debugger
System.Diagnostics.Debugger.Break();
}
}
The Application_UnhandledException method is not called from your method where the exception happens, so new StrackTrace() will not be meaningful, as you have discovered.
To get the stack trace for the place where the exception occurred, use e.Exception.StackTrace.
Note that the real exception may be wrapped inside another exception, possibly several layers deep (e.Exception.InnerException).
You could also use BugSense to get this information.
Disclaimer: I am one of the cofounders