I am implementing a ShowToolWindow() function in a visual studio extension project that displays a toolwindow on click of a button.
The following code works:
private void ShowToolWindow()
{
IVsUIShell vsUIShell = (IVsUIShell)Package.GetGlobalService(typeof(SVsUIShell));
IVsWindowFrame frame;
Guid WindowGuid = new Guid("48d81433-5d5c-4d4c-a174-d8e620c0e0a8");
vsUIShell.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fForceCreate, ref WindowGuid, out frame);
frame.Show();
}
However, the following code does not work
private void ShowToolWindow1()
{
this.package = new ToolWindowPackage()/*Package that provides the window*/;
var window = (MyToolWindow)this.package.FindToolWindow(typeof(MyToolWindow), 0, true); /*This line throws an exception*/
IVsWindowFrame frame = window.Frame;
frame.show();
}
In this case the FindToolWindow throws the following exception
Activated Event Time Duration Thread
Exception: Exception thrown: 'System.Exception' in Microsoft.VisualStudio.Shell.15.0.dll ("The service 'Microsoft.VisualStudio.Shell.Interop.SVsUIShell' must be installed for this feature to work. Ensure that this service is available."). Exception thrown: 'System.Exception' in Microsoft.VisualStudio.Shell.15.0.dll ("The service 'Microsoft.VisualStudio.Shell.Interop.SVsUIShell' must be installed for this feature to work. Ensure that this service is available.")
It seems it is not calling the Package.FindToolWindow, but rather the IVsUIShell.FindToolWindow. How should I resolve this.
I am asking this question because I need to get a handle of the ToolWindowPane. Therefore even though the first way shows the toolwindow correctly it is not suffice. An alternative solution to this question, could someone tell me how to get a handle of the ToolWindowPane Through the first method?
You should not create a new instance of ToolWindowPackage by yourself. You should use an existing package instance instantiated by Visual Studio.
Related
According to the documentation here: https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicecontroller.servicename?view=dotnet-plat-ext-7.0#exceptions
The ServiceController.ServiceName will throw an InvalidOperationException if "The service was not found."
But running this code, it runs without throwing an exception:
var serviceController = new ServiceController();
serviceController.ServiceName = "Not.Existing.Service";
I, personally, don't believe this check on the service status happens upon setting the ServiceName (on the creation of the ServiceControler object). But the documentation is not clear when the exception is thrown exactly on this property.
There's also a possibility that the exception is thrown on getting the value from the ServiceName, I tried the following scenario:
Installed a service
Ran the code (below)
Paused the debugger on line 3
Uninstalled the service
Continued running the code
No exception occurred!
/*1*/ serviceController.ServiceName = "Existing.Service";
/*2*/ serviceController.Start();
/*3*/ var serviceName = serviceController.ServiceName;
I also found other questions (this one) that none of the answers mention this property when checking whether a Windows service is installed or not.
Note: my problem is not trying to figure out how to check whether a Windows service is installed or not, but to understand when the exception is thrown on the ServiceName property.
You'll need to use the constructor with string argument to make (an attempt to make) a link with an existing service.
Initializes a new instance of the ServiceController class that is associated with an existing service on the local computer.
The constructor will not throw an exception in case the service does not exist, but accessing that ServiceName property get will throw one as documented.
Below example throws that exception.
var serviceController = new ServiceController("Not.Existing.Service");
var serviceName = serviceController.ServiceName; // << Exception thrown.
If you look at the source code here you will see when this exception is thrown. There are several opportunities for ServiceController to throw this exception on the service name. Specifically, look in the private void GenerateNames() definition. This function is only called in the getters for ServiceName and DisplayName and that's when you'll probably encounter this exception.
If you read this code, it is clearly mentioned that it does not throw exceptions for invalid service names (It does only validation check) on the setter of ServiceController's ServiceName
Intro
When an user creates a mistake in the configuration of NLog (like invalid XML), We (NLog) throw a NLogConfigurationException. The exception contains the description what is wrong.
But sometimes this NLogConfigurationException is "eaten" by a System.TypeInitializationException if the first call to NLog is from a static field/property.
Example
E.g. if the user has this program:
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
namespace TypeInitializationExceptionTest
{
class Program
{
//this throws a NLogConfigurationException because of bad config. (like invalid XML)
private static Logger logger = LogManager.GetCurrentClassLogger();
static void Main()
{
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
}
and there is a mistake in the config, NLog throws:
throw new NLogConfigurationException("Exception occurred when loading configuration from " + fileName, exception);
But the user will see:
"Copy exception details to the clipboard":
System.TypeInitializationException was unhandled
Message: An unhandled exception of type 'System.TypeInitializationException' occurred in mscorlib.dll
Additional information: The type initializer for 'TypeInitializationExceptionTest.Program' threw an exception.
So the message is gone!
Questions
Why is innerException not visible? (tested in Visual Studio 2013).
Can I send more info to the TypeInitializationException? Like a message? We already sending an innerException.
Can we use another exception or are there properties on Exception so that more info is reported?
Is there another way to give (more) feedback to the user?
Notes
of course we have no influence on the program written by the user.
I'm one of the maintainers of NLog.
Do you like to test it by yourself? Checkout https://github.com/NLog/NLog/tree/TypeInitializationException-tester and start NLog/src/NLog.netfx45.sln
Edit:
please note that I'm the library maintainer, not the user of the library. I cannot change the calling code!
I'll just point out the underlying problem you are dealing with here. You are fighting a bug in the debugger, it has a very simple workaround. Use Tools > Options > Debugging > General > tick the "Use Managed Compatibility Mode" checkbox. Also untick Just My Code for the most informative debugging report:
If Just My Code is ticked then the exception report is less informative but still can be drilled down easily by clicking the "View Detail" link.
The option name is unnecessarily cryptic. What it really does is tell Visual Studio to use an older version of the debugging engine. Anybody that uses VS2013 or VS2015 will have this trouble with the new engine, possibly VS2012. Also the basic reason that this issue did not have be addressed in NLog before.
While this is a very good workaround, it is not exactly easy to discover. Nor would programmers particularly like to use the old engine, shiny new features like return value debugging and E+C for 64-bit code are not supported by the old engine. Whether this is a truly a bug, an oversight or a technical limitation in the new engine is hard to guess. This is excessively ugly so don't hesitate to label it "bug", I strongly recommend you take this to connect.microsoft.com. Everybody will be ahead when it gets fixed, I scratched my head over this at least once that I remember. Drilled it down by using Debug > Windows > Exceptions > ticked CLR Exceptions at the time.
A workaround for this very unfortunate behavior is sure to be ugly. You do have to delay raising the exception until program execution has progressed far enough. I don't know your codebase well enough, but delaying parsing the config until the first logging command ought to take care of it. Or store the exception object and throw it on the first log command, probably easier.
The reason I see is because the Type initialization of Entry point class is failed. Since no type was initialized, so the Type loader has nothing to report about the failed type in TypeInitializationException.
But if you change the Static initializer of logger to other class and then refer that class in Entry method. you'll get the InnerException on TypeInitialization exception.
static class TestClass
{
public static Logger logger = LogManager.GetCurrentClassLogger();
}
class Program
{
static void Main(string[] args)
{
var logger = TestClass.logger;
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
Now you'll get the InnerException because the Entry type was loaded to report the TypeInitializationException.
Hope now you get the idea to keep the Entry point clean and Bootstrap the application from Main() instead of static property of Entry point class.
Update 1
You can also utilize the Lazy<> to avoid the execution of configuration initialization at declaration.
class Program
{
private static Lazy<Logger> logger = new Lazy<Logger>(() => LogManager.GetCurrentClassLogger());
static void Main(string[] args)
{
//this will throw TypeInitialization with InnerException as a NLogConfigurationException because of bad config. (like invalid XML)
logger.Value.Info("Test");
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
Alternatively, try Lazy<> in the LogManager for logger instantiation so that the configuration initialization happens when actually the first log statement occurs.
Update 2
I analyzed the source code of NLog and seems like it's already implemented and It make sense. According to the comments on property "NLog should not throw exception unless specified by property LogManager.ThrowExceptions in LogManager.cs".
Fix - In the LogFactory class the private method GetLogger() has the initialization statement which is causing the exception to happen. If you introduce a try catch with the check of property ThrowExceptions then you can prevent the initialization exception.
if (cacheKey.ConcreteType != null)
{
try
{
newLogger.Initialize(cacheKey.Name, this.GetConfigurationForLogger(cacheKey.Name, this.Configuration), this);
}
catch (Exception ex)
{
if(ThrowExceptions && ex.MustBeRethrown())
throw;
}
}
Also it would be great to have these exceptions/errors stored somewhere so that It can be traced why Logger initialization failed because the they were ignored due to ThrowException.
I said in an earlier comment that I'm unable to reproduce your issue. Then it occurred to me you were only looking for it in the popup exception dialog, which doesn't display a show details link.
So here's how you can get at the InnerException anyway, because it definitely is there, except Visual Studio doesn't report it for some reason (probably because it's in the entry point type as vendettamit figured out).
So, when you run the tester branch, you get the following dialog:
And it doesn't show the View Details link.
The Copy exception detail to the clipboard isn't particularly helpful either:
System.TypeInitializationException was unhandled
Message: An unhandled exception of type 'System.TypeInitializationException' occurred in mscorlib.dll
Additional information: The type initializer for 'TypeInitializationExceptionTest.Program' threw an exception.
Now, dismiss the dialog with the OK button and head towards the Locals debug window. Here's what you'll see:
See? The InnerException definitely is there, and you found a VS quirk :-)
Problem is the static initialization happens when the class is first referenced. In your Program it happens even before the Main() method. So as rule of thumb - avoid any code that can fail in static initialization method. As for your particular problem - use lazy approach instead:
private static Lazy<Logger> logger =
new Lazy<Logger>(() => LogManager.GetCurrentClassLogger());
static void Main() {
logger.Value.Log(...);
}
So the initialization of logger will happen (and possibly fail) when you'll first access the logger - not in some crazy static context.
UPDATE
It is ultimately burden of user of your library to stick to the best practices. So if it were me I'd keep it as it is. There are few options though if you really have to solve it on your end:
1) Don't throw exception - ever - this is valid approach in logging engine, and how log4net works - i.e.
static Logger GetCurrentClassLogger() {
try {
var logger = ...; // current implementation
} catch(Exception e) {
// let the poor guy now something is wrong - provided he is debugging
Debug.WriteLine(e);
// null logger - every single method will do nothing
return new NullLogger();
}
}
2) wrap the lazy approach around the implementation of Logger class (I know your Logger class is much more complex, for sake of this problem let's assume it has just one method Log and it takes string className to construct Logger instance.
class LoggerProxy : Logger {
private Lazy<Logger> m_Logger;
// add all arguments you need to construct the logger instance
public LoggerProxy(string className) {
m_Logger = new Lazy<Logger>(() => return new Logger(className));
}
public void Log(string message) {
m_Logger.Value.Log(message);
}
}
static Logger GetCurrentClassLogger() {
var className = GetClassName();
return new LoggerProxy(className);
}
You'll get rid of this problem (the real initialization will happen while first log method is called and it is backward-compatible approach); only problem is you've added another layer (I don't expect any drastic downgrade of performance, but some logging engines are really into micro-optimization).
The only solution I see now is:
move the static initializes (fields) to a static constructor with a try catch
System.TypeInitializationException is always or almost always occurred from not correct initialisation the static members of a class.
You have to check LogManager.GetCurrentClassLogger() via debugger. I'm sure the error is occurred inside that part of code.
//go into LogManager.GetCurrentClassLogger() method
private static Logger logger = LogManager.GetCurrentClassLogger();
Also i suggest you double check your app.config and make sure you haven't included anything wrong.
System.TypeInitializationException is thrown whenever a static constructor throws an exception, or whenever you attempt to access a class where the static constructor threw an exception.
When .NET loads the type, it must prepare all it's static fields before the first time that you use the type. Sometimes, initialization requires running code. It is when that code fails that you get a System.TypeInitializationException.
According the docs
When a class initializer fails to initialize a type, a TypeInitializationException is created and passed a reference to the exception thrown by the type's class initializer. The InnerException property of TypeInitializationException holds the underlying exception.
TypeInitializationException uses the HRESULT COR_E_TYPEINITIALIZATION, that has the value 0x80131534.
For a list of initial property values for an instance of TypeInitializationException, see the TypeInitializationException constructors.
1) The InnerException is not visible it is very typical for this type of Exception. The version of Visual Studio doesn't matter (ensure that the "Enable the exception assistant" option is checked - Tools> Options>Debugging>General)
2) Usually the TypeInitializationException hides the real exception which can be viewed via InnerException. But the test example below shows how you can populate inner exception info:
public class Test {
static Test() {
throw new Exception("InnerExc of TypeInitializationExc");
}
static void Main(string[] args) {
}
}
But sometimes this NLogConfigurationException is "eaten" by an
System.TypeInitializationException if the first call to NLog is from a
static field/property.
Nothing strange. Someone missed the try catch block somewhere.
I have this property in my viewmodel.
public bool IsKWH
{
get { return _isKwh; }
set
{
if (value.Equals(_isKwh)) return;
_isKwh = value;
NotifyOfPropertyChange(() => IsKWH);
}
}
Sometimes (~1 in 10 times) when I close down my application I get the following error in NotifyOfPropertyChange:
An exception of type 'System.Threading.Tasks.TaskCanceledException' occurred in WindowsBase.dll but was not handled in user code
Additional information: A task was canceled.
I have a System.Threading.Timer in my view model that is making a webservice call to update this and many other properties.
I am using Caliburn.Micro and it seems to have started happening when I updated from 1.5 to 2.0.
Is there anyway to prevent this error from occurring?
It is possible that intermittently your application fails to dispose of any secondary threads that it is using before the application closes. This can often cause an error message such as the one you posted. Could I suggest trying the following:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
// close all active threads
Environment.Exit(0);
}
This should force the application to terminate all active threads before it closes. I recall having a similar problem and that particular little fix solved it. Might be worth giving it a try, let me know if it doesn't help and we can see what other solutions there might be. Hope this works for you.
FWIW, that fix didn't help me. the problem was coming from a 3rd party DLL that's dynamically loaded. I was unable to stop the exception from getting thrown, however I ignore the exception in the app exception handler:
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(
(sender2, args) =>
{
Exception ex = (Exception)args.ExceptionObject;
// unloading dragon medical one
if (ex is TaskCanceledException)
return; // ignore
I have a Windows Forms application with a single Editor class (that inherits from Form).
public partial class Editor : Form
{
public Editor()
{
InitializeComponent();
Load += Editor_Load;
}
private void Editor_Load(object sender, EventArgs e)
{
cmbConnections.DataSource = ConnectionManager.Connections;
cmbConnections.Visible = false;
}
}
Other than designer-generated code, this is the only code for the form (that contains only a single Combo Box (cmbConnections).
The ConnectionManager class is a static class with a static constructor. It's constructor does some initialization and then tests for some critical condition. If the condition is met, the constructor throws an exception. However, this exception does not break in the debugging mode in Visual Studio 2010. To test this, I've put only throw new Exception() in the ConnectionManager's static constructor. The ConnectionManager is used and therefor initialized (for the first time) in the Editor_Load event handler. Static constructor is called and exception thrown (visible only in output window). The rest of the Editor_Load event handler (cmbConnections.Visible = false;) is not executed, just as expected.
But what I don't understand is why did my VS2010 swallow the exception? It did not break the debug. It is not enclosed in any try/catch block. It continued with program execution with the main window. It almost seems as if the Editor_Load was executed on another thread.
I can see the messages in output window:
A first chance exception of type 'System.InvalidOperationException' occurred in Editor.exe
A first chance exception of type 'System.TypeInitializationException' occurred in Editor.exe
but the execution simply did not break in debug mode.
Here are some of my options that I believe may influence this behavior:
Project Properties->Build->General-> Optimize code is UNCHECKED.
Tools->Options->Debugging->General-> Enable Just My Code is CHECKED.
In exception settings, the checkbox for the "user-unhandled" is CHECKED.
Am I missing something? Is this behavior normal? I thought that VS2010 will throw on ANY unhandled exception. And here this one is unhandled and still does not break.
I think it is by design that you need to enable Managed (.NET) Exceptions 'Thrown' in the Exceptions Dialog (Ctrl-Alt-E).1
To avoid many spurious (handled) exceptions, I usually try to get close to the point where the initializer will be run and then check that checkbox just before continueing.
Also, if there are loader exceptions, be sure to check the nested inner exceptions or loader information in the exception: the exception itself is usually not that informative. I have frequently had to dig through 2 or more layers of wrapping exceptions in order to get at the actual error.
1 I can only guess as to why that is; My feeling is that the static type initializers are not considered to be run deterministically (many things could trigger it and the order is often undefined; it is just guaranteed that a type's static constructor will have been run before it is used, but it can be used at almost any point in the code, without you knowing or explicitely triggering that).
Therefore, it would be hard for the runtime to establish whether it was 'handled by user code' (no user should expect to handle it, because it doesn't know - deterministically - when the initializer will run).
However, this is conjecture on my part.
Catching Own First Chance Exceptions
AppDomain.CurrentDomain.FirstChanceException += FirstChanceException;
private static void FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
// I would like to log exceptions happening outside my assembly?
// But this event does not receive external FirstChanceExceptions
// (unlike Visual Studio debug output)
myLogger.Log(e.Exception);
}
Example
I would like to log A first chance exception of type 'System.IO.IOException' occurred in WindowsBase.dll
But not log A first chance exception of type 'System.DivideByZeroException' occurred in MyApp.exe
Solution?
Is there a way to get notified of those exceptions arising in dlls such as mscorlib.dll?
Note the interest is to log in the production release, not only in debugging.
Why
Exceptions that occur in external dll dependencies can cause trouble, even if they are handled there.
For example, due to an exception a null value may be returned from an external method (instead of returning the desired output of x) and even though my code mostly handles such abnormal output it is useful to know what exactly went wrong and where - because while I may be able to avoid fatal exceptions then more often than not that null value makes part of my app non-functional. So logging the external first chance exception would provide valuable information to help rectify the issue / turn that null into x. And this may be present in only given environments / for specific users etc...
You can use StackTrace class to check what is the source of the exception:
var stackTrace = new StackTrace(e.Exception);
var sourceFrame = stackTrace.GetFrame(0);
var throwingMethod = sourceFrame.GetMethod();
var sourceAssembly = throwingMethod.DeclaringType.Assembly;
var assemblyName = sourceAssembly.GetName().Name;
bool isMyApp = assemblyName == "MyApp";