Can't execute statement with VS Debugger Interop - c#

I'm writing a debugger extension VSPackage in which I want to execute a statement in the debugged process when a breakpoint is hit. In my extension code I have this:
void Initialize()
{
// ...standard vspackage init code omitted...
Globals.Init((DTE2)GetService(typeof(DTE)));
Globals.DebuggerEvents.OnEnterBreakMode += (dbgEventReason reason, ref dbgExecutionAction action) =>
{
try
{
var e1 = Globals.Application.Debugger.GetExpression("1+2");
Debug.WriteLine(e1.Value); // Prints "3"
Globals.Application.Debugger.ExecuteStatement("x = 1+2", 1000);
Debug.WriteLine("OK"); // Never prints this
}
catch (Exception ex)
{
Debug.WriteLine("Error: "+ex); // Nor this
}
}
}
When debugging this extension in a VS instance I load a trivial program looking like this
static void Main()
{
int x = 5;
Console.WriteLine("X is "+x); // Breakpoint on this line
}
When the breakpoint is hit in the debugged process the handler is called and the output window for the extension shows "3", so evaluating expressions works, but it never succeeds executing the statement. Nothing more is printed to the output window. No exception or timeout occurs and I can't continue debugging the process, the debugger appears to have crashed.
The globals class just holds the DTE and DebuggerEvents
public static class Globals
{
public static void Init(DTE2 dte)
{
Application = dte;
DebuggerEvents = dte.Events.DebuggerEvents;
}
public static DTE2 Application { get; private set; }
public static DebuggerEvents DebuggerEvents { get; private set; }
}
What am I doing wrong, or misunderstanding here?

This is an old question, but there is so little on Google about these issues, I thought I'd offer some help. Some important considerations:
Use GetExpresssion3(TreatAsStatement:=True), if possible, instead of ExecuteStatement (I could not get ExecuteStatement working properly).
The thread calling your delegate (OnEnterBreakMode) is the same thread that will need will to run again in order to execute your expression or statement. Therefore, call your GetExpression method on a new thread (Task.Run..)
You will have to monitor and manage the Reason value for OnEnterBreakMode. The initial Reason is UnwindFromException for the actual unhandled exception. Then, it is expected you are setting a variable, such as tempStack = New System.Diagnostics.StackTrace(True). OnEnterBreakMode will be called again following execution of this statement, but this time with Evaluation for the Reason. At this point you now call all of your GetExpressions to collect all of your data without additional OnEnterBreakMode calls.
Dim dte2 As EnvDTE80.DTE2 = GetGlobalService(GetType(EnvDTE.DTE))
Dim debugger5 as EnvDTE100.Debugger5 = Dte2.Debugger
Interesting design observation: System.Diagnostics.StackTrace is a very strangely designed class in the context of the rest of the .NET framework until you have to work on this project where you are extracting the StackTrace through this very technique and see the benefit of its otherwise odd design.

I was tinkering a lot with Visual Studio debugging, and the ultimate cause of freezing was always related to thread handling: VS allows any piece of code to run while debugging only in the main thread. Every other thread is disabled and in case your debug code depends on a different thread it will freeze too.
My guess: You initialized your DTE in a different thread than what you are debugging.
Assumed result: Delegate method tries to load the context of the initializing thread which is different from the debugged thread, and thus it is bound to get frozen.
Proposed solution: Don't use delegate method. They implicitly refer back to the original execution context. Instead register a regular method, and reinitialize your DTE in that context.

Related

C# Console application does work when started from Visual studio, after publishing it only runs for 3 cycles is this normal behaviour?

I made a C# console application (.NET CORE 5.0) to check every minute for changes in a MySQL database and send e-mails with the changes.
If I run this application directly from visual studio 2019, it works fine without any problems.
If I run it after I publish it, it only does 3 cycles and the console window stays open. No errors or anything else.
This first screenshot is from running via Visual Studio 2019
This is screenshot is from running directly from desktop after publish
static void Main(string[] args)
{
TimerCallback callback = new TimerCallback(DoStuff);
Timer stateTimer = new Timer(callback, null, 0, 1000);
for (; ; )
{
Thread.Sleep(100);
}
}
static public void DoStuff(Object stateInfo)
{
DataTable DtblEmployee = DatabaseClass.GetEmployeeList();
foreach (DataRow row in DtblEmployee.Rows)
{
foreach (var item in row.ItemArray)
{
string Str = RandomStringGenerator.GetRandomAlphanumericString(8);
DatabaseClass.EmployeeUpdate(item.ToString(), Str);
EmailClass.SendEmail(item.ToString(), Str);
}
}
Console.WriteLine("Last check was # {0}", DateTime.Now.ToString("h:mm:ss"));
Console.WriteLine("{0} e-mail(s) were send.", DtblEmployee.Rows.Count);
}
The program is supposed to run forever.
Would love to hear from you guys, if more information is needed please ask.
EDIT: Added extra code to show Database
public static void EmployeeUpdate(string Emailadress, string Password)
{
string connectionstring;
connectionstring = "server=1.1.1.1;user id=User;password=Pass;port=3306;persistsecurityinfo=True;database=Test";
connection = new MySqlConnection(connectionstring);
try
{
connection.Open();
var cmd = new MySqlCommand("UPDATE Users SET Password=#param_val_1, GeneratePassword=#param_val_3 where Username=#param_val_2", connection);
cmd.Parameters.AddWithValue("#param_val_1", Password);
cmd.Parameters.AddWithValue("#param_val_2", Emailadress);
cmd.Parameters.AddWithValue("#param_val_3", 0);
cmd.ExecuteScalar();
cmd.Dispose();
}
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
Console.WriteLine("Cannot connect to server. Contact administrator");
break;
case 1045:
Console.WriteLine("Invalid username/password, please try again");
break;
}
}
finally
{
connection.Close();
}
}
I strongly expect that the problem is that your Timer is being garbage collected and finalized, and that's stopping the callback from being executed.
When you run your code from Visual Studio in the debugger, the JIT is less aggressive about garbage collection, which is why it's working in that scenario.
The smallest change to fix that would be to add this line at the end of your Main method:
GC.KeepAlive(stateTimer);
Alternatively, as per quetzalcoatl's answer, you could use a using statement for the timer. Either option will have the desired effect of keeping the timer alive for the duration of the method.
An alternative I think you should explore would be to not use a timer at all, instead just loop within the Main method and call your DoStuff method directly. You'd still call Sleep within that loop, which would handle the timing aspect. Obviously that will affect the precise timing of how the code runs, but it's likely to end up being simpler to understand and simpler to debug.
Additionally, I'd suggest being a lot more intentional about your exception handling. Work out whether you want the code to stop looping if any one iteration throws an exception, and make that explicit in the code.
I 100% agree with JonSkeet about the reason.
It's the GC that cleans up the stateTimer variable. Right after this line, this variable becomes unused and the compiler is free to get rid of it from the stack, and then GC is free to get rid of the timer.
When you are running your application in different environments, the GC may be using different set rules. Debugging session, console app, IIS Application, module for SqlServer, etc - they all have different rules as for when and how aggressively run the GC. Under debugging session, it also MAY clean up this variable, but it also MAY do it hours or days later, maybe to give you more time to inspect things? Under free-running console app, it simply occurred sooner.
GC also has its hard rules that has to abide them always: if the variable is used, it cannot be purged.
JonSkeet suggested pinning the stateTimer, I disagree. It's a last-resort option.
Much better, just use USING directive, as the Timer is a IDisposable:
TimerCallback callback = new TimerCallback(DoStuff);
using(Timer stateTimer = new Timer(callback, null, 0, 1000))
for (; ; )
{
Thread.Sleep(100);
}
The variable is still unused, you can even get rid of it and write
using(new Timer(callback, null, 0, 1000))
but even now, the using() statement will remember that Timer object and prevent GC from cleaning it up too soon. (It has to remember that object to be able to call Dispose() when the loop ends..)

Multiple thread access to Excel

I have two methods, method1, method2, both have lock(App) where App is a static instance in the same class.
App is a static instance in a shared project Helper
void method1()
{
lock(Helper.App)
{
ExcelApp.FormulaCell.AddComments(errMsg);
}
}
void method2()
{
lock(Helper.App)
{
//plot data (an 2-D array) to cells
var dataRng = ExcelApp.CurrentSheet.Cells(Formulacell.Row + 1, Formulacell.Column + 1);
dataRng = dataRng.get_Resize(n, m);
dataRng.Value2 = data;
}
}
method1, method2 are called by many threads.
I want at one time only method1 or method2 run
The issue is they seem not.
in method1 & method2, I plot some data to Excel, I get Exception
Name:COMException
Message:Exception from HRESULT: 0x800AC472
I googled and find the exception is caused by Excel Application is not ready.
There is no UI gesture, so I conclude the exception is caused by the two methods try to write to Excel at the same time.
Please check if youre calling an async methods to excell.
If so, this is the problem, even though you used locks, the actual calls are running in the same time.
Try to wait till the excell methods ends.
Ofir

Make my COM assembly call asynchronous

I've just "earned" the privilege to maintain a legacy library coded in C# at my current work.
This dll:
Exposes methods for a big legacy system made with Uniface, that has no choice but calling COM objects.
Serves as a link between this legacy system, and another system's API.
Uses WinForm for its UI in some cases.
More visually, as I understand the components :
*[Big legacy system in Uniface]* ==[COM]==> [C# Library] ==[Managed API]==> *[Big EDM Management System]*
The question is: One of the methods in this C# Library takes too long to run and I "should" make it asynchronous!
I'm used to C#, but not to COM at all. I've already done concurrent programming, but COM seems to add a lot of complexity to it and all my trials so far end in either:
A crash with no error message at all
My Dll only partially working (displaying only part of its UI, and then closing), and still not giving me any error at all
I'm out of ideas and resources about how to handle threads within a COM dll, and I would appreciate any hint or help.
So far, the biggest part of the code I've changed to make my method asynchronous :
// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
errMsg = "";
try {
Action<string> asyncOp = AsyncComparedSearch;
asyncOp.BeginInvoke(application, null, null);
} catch (ex) {
// ...
}
return 0;
}
private int AsyncComparedSearch(string application) {
// my actual method doing the work, that was the called method before
}
Any hint or useful resource would be appreciated.
Thank you.
UPDATE 1:
Following answers and clues below (especially about the SynchronizationContext, and with the help of this example) I was able to refactor my code and making it to work, but only when called from another Window application in C#, and not through COM.
The legacy system encounters a quite obscure error when I call the function and doesn't give any details about the crash.
UPDATE 2:
Latest updates in my trials: I managed to make the multithreading work when the calls are made from a test project, and not from the Uniface system.
After multiple trials, we tend to think that our legacy system doesn't support well multithreading in its current config. But that's not the point of the question any more :)
Here is a exerpt of the code that seems to work:
string application;
SynchronizationContext context;
// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
this.application = application;
context = WindowsFormsSynchronizationContext.Current;
Thread t = new Thread(new ThreadStart(AsyncComparedSearchAndShowDocs));
t.Start();
errMsg = "";
return 0;
}
private void AsyncComparedSearch() {
// ANY WORK THAT AS NOTHING TO DO WITH UI
context.Send(new SendOrPostCallback(
delegate(object state)
{
// METHODS THAT MANAGE UI SOMEHOW
}
), null);
}
We are now considering other solutions than modifying this COM assembly, like encapsulating this library in a Windows Service and creating an interface between the system and the service. It should be more sustainable..
It is hard to tell without knowing more details, but there are few issues here.
You execute the delegate on another thread via BeginInvoke but you don't wait for it. Your try\catch block won't catch anything as it has already passed while the remote call is still being executed. Instead, you should put try\catch block inside AsyncComparedSearch.
As you don't wait for the end of the execution of remote method (EndInvoke or via callback) I am not sure how do you handle the results of the COM call. I guess then that you update the GUI from within AsyncComparedSearch. If so, it is wrong, as it is running on another thread and you should never update GUI from anywhere but the GUI thread - it will most likely result with a crash or other unexpected behavior. Therefore, you need to sync the GUI update work to GUI thread. In WinForms you need to use Control.BeginInvoke (don't confuse it with Delegate.BeginInvoke) or some other way (e.g. SynchronizationContext) to sync the code to GUI thread. I use something similar to this:
private delegate void ExecuteActionHandler(Action action);
public static void ExecuteOnUiThread(this Form form, Action action)
{
if (form.InvokeRequired) { // we are not on UI thread
// Invoke or BeginInvoke, depending on what you need
form.Invoke(new ExecuteActionHandler(ExecuteOnUiThread), action);
}
else { // we are on UI thread so just execute the action
action();
}
}
then I call it like this from any thread:
theForm.ExecuteOnUiThread( () => theForm.SomeMethodWhichUpdatesControls() );
Besides, read this answer for some caveats.

How does Visual Studio evaluate properties while debugging in C#?

In the past, I've been burned by the "side-effects-in-an-accessor" issue when debugging; meaning that I've had caches being initialised without my breakpoints being triggered (since it was already paused in visual studio). And so I've been wondering about the mechanism that Visual Studio uses to execute code "out-of-order", so as to evaluate properties in a debugger. It would seem to me that this would circumvent the CLR?
So the question: How is this done from a technical standpoint? Articles explaining it would be helpful.
Looks like VS2012 (and probably earlier versions as well) executes the property's getter using the "Main Thread" or maybe the thread that hit the breakpoint.
This is my testing code:
static class TestSideEffects
{
public static void Test()
{
Console.WriteLine("Main Thread: {0}", Thread.CurrentThread.ManagedThreadId);
var o = new TestSubject();
Console.WriteLine("Property Value: {0}", o.IntGetValueNoSe());
}
}
class TestSubject
{
private int _prop=0;
public int TheProperty
{
get
{
Console.WriteLine("Thread accessing the property: {0}", Thread.CurrentThread.ManagedThreadId);
return ++_prop;
}
}
public int IntGetValueNoSe(){return _prop; }
}
I set two breakpoints: on the 3rd line of the Test method and in the getter itself, and every time I hover my mouse over the o instance - it executes the getter without triggering the other breakpoint. It uses the same (main in this case) thread.
This is the output of the test program:
Main Thread: 8
Thread accessing the property: 8
Thread accessing the property: 8
Thread accessing the property: 8

"Debug only" code that should run only when "turned on"

I would like to add some C# "debug only" code that only runs if the person debugging requests it. In C++, I used to do something similar to the following:
void foo()
{
// ...
#ifdef DEBUG
static bool s_bDoDebugOnlyCode = false;
if (s_bDoDebugOnlyCode)
{
// Debug only code here gets executed when the person debugging
// manually sets the bool above to true. It then stays for the rest
// of the session until they set it to false.
}
#endif
// ...
}
I can't do exactly the same in C# since there is no local statics.
Question: What is the best way to accomplish this in C#?
Should I use a private class static field with C# preprocessor directives (#if/#endif DEBUG)?
Should I use the Conditional attribute (to hold the code), and then a private class static field (not surrounded by C# preprocessor directives #if/#endif DEBUG?).
Something else?
An instance variable would probably be the way to do what you want. You could make it static to persist the same value for the life of the program (or thread depending on your static memory model), or make it an ordinary instance var to control it over the life of an object instance. If that instance is a singleton, they'll behave the same way.
#if DEBUG
private /*static*/ bool s_bDoDebugOnlyCode = false;
#endif
void foo()
{
// ...
#if DEBUG
if (s_bDoDebugOnlyCode)
{
// Code here gets executed only when compiled with the DEBUG constant,
// and when the person debugging manually sets the bool above to true.
// It then stays for the rest of the session until they set it to false.
}
#endif
// ...
}
Just to be complete, pragmas (preprocessor directives) are considered a bit of a kludge to use to control program flow. .NET has a built-in answer for half of this problem, using the "Conditional" attribute.
private /*static*/ bool doDebugOnlyCode = false;
[Conditional("DEBUG")]
void foo()
{
// ...
if (doDebugOnlyCode)
{
// Code here gets executed only when compiled with the DEBUG constant,
// and when the person debugging manually sets the bool above to true.
// It then stays for the rest of the session until they set it to false.
}
// ...
}
No pragmas, much cleaner. The downside is that Conditional can only be applied to methods, so you'll have to deal with a boolean variable that doesn't do anything in a release build. As the variable exists solely to be toggled from the VS execution host, and in a release build its value doesn't matter, it's pretty harmless.
What you're looking for is
[ConditionalAttribute("DEBUG")]
attribute.
If you for instance write a method like :
[ConditionalAttribute("DEBUG")]
public static void MyLovelyDebugInfoMethod(string message)
{
Console.WriteLine("This message was brought to you by your debugger : ");
Console.WriteLine(message);
}
any call you make to this method inside your own code will only be executed in debug mode. If you build your project in release mode, even call to the "MyLovelyDebugInfoMethod" will be ignored and dumped out of your binary.
Oh and one more thing if you're trying to determine whether or not your code is currently being debugged at the execution moment, it is also possible to check if the current process is hooked by a JIT. But this is all together another case. Post a comment if this is what you2re trying to do.
You could try this if you only need the code to run when you have a debugger attached to the process.
if (Debugger.IsAttached)
{
// do some stuff here
}
If you want to know whether if debugging, everywhere in program.
Use this.
Declare global variable.
bool isDebug=false;
Create function for checking debug mode
[ConditionalAttribute("DEBUG")]
public static void isDebugging()
{
isDebug = true;
}
In the initialize method call the function
isDebugging();
Now in the entire program. You can check for debugging and do the operations.
Hope this Helps!
I think it may be worth mentioning that [ConditionalAttribute] is in the System.Diagnostics; namespace. I stumbled a bit when I got:
Error 2 The type or namespace name 'ConditionalAttribute' could not be found (are you missing a using directive or an assembly reference?)
after using it for the first time (I thought it would have been in System).

Categories