In my application, WinDbg gets launched and I wondered if there was any way of sending certain commands through to WinDbg (for example sending the letter k (to show the callstack) from the C# application?
I've read around some use of user32.dll which has functions that can help with this but I am unclear of how to proceed and include it in my app.
Any help would be greatly appreciated.
Steve
If you want to fully control the debug engine, then you should just host it inside your C# application using the exposed COM interfaces.
You can find sample code for automating the debug engine in the WinDbg installation directory (e.g. C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x64\sdk\samples). This blog post shows how to get a stack trace using the API (in C), so you don't have to parse the output after issuing a k command.
The hardest part is just finding/creating all the IDebug* [ComImport] interfaces in C# for all the exposed objects. But once you have them, you would do something like this:
internal static class WinDbgBase
{
// STDAPI DebugCreate(__in REFIID InterfaceId, __out PVOID* Interface);
[DllImport("dbgeng.dll", EntryPoint = "DebugCreate", CallingConvention = CallingConvention.StdCall)]
public static extern int DebugCreate([In] ref System.Guid InterfaceId, ref System.IntPtr Interface);
}
Guid uuidof_IDebugClient4 = new Guid("{ca83c3de-5089-4cf8-93c8-d892387f2a5e}");
IntPtr pObj = IntPtr.Zero;
int hr = WinDbgBase.DebugCreate(ref uuidof_IDebugClient4, ref pObj);
IDebugClient4 _client = (IDebugClient4)Marshal.GetTypedObjectForIUnknown(pObj, typeof(IDebugClient4));
// QueryInterface the other objects
IDebugControl4 _control = (IDebugControl4)_client;
_client.AttachProcess(0, ProcessId, DEBUG_ATTACH.DEBUG_ATTACH_DEFAULT);
_control.WaitForEvent(DEBUG_WAIT.DEBUG_WAIT_DEFAULT, Win32.INFINITE);
...
If you are dealing with managed targets, then it is even possible to load up the SOS extension, get the managed stack (as previously mentioned) and then merge it with the native stack trace so that you can show the full stack with all the native to/from managed transitions.
References
- Listing of all Debugger COM objects
No need to send keystrokes. There's a more reliable way: see the WinDbg help for .ocommand. It works by sending commands through OutputDebugString, which is Debug.WriteLine() (Debug build) or Trace.WriteLine() (Release build) in .NET.
As you also start the debugger by yourself, you probably want to execute .ocommand immediately at startup which you can do by adding the -c command line switch:
windbg.exe -p <PID> -c ".ocommand <Magic>;g"
This approach is a quick any dirty way. #joshpoley`s answer is the cleaner way if you want a long term stable solution.
Note that for .NET the native callstack k might not be what you want. Try !clrstack or !dumpstack of the SOS extension (which you can load using .loadby sos clr or .loadby sos mscorwks depending on your .NET version).
Related
We have a .NET 4 based service that self hosts a WCF service with callbacks. We encapsulate this service in a .NET 4 dll that exposes COM objects. This service is used by a large variety of clients, the majority being .NET based.
Unfortunately we have some VB6 clients that we can not change and we are getting AccessViolationExceptions when some callback methods are invoked.
The way the service is structured is with callbacks is illustrated below.
MethodA invoked by VB6 Client, proxied through the .NET dll to the WCF service (has not returned yet)
WCF CallbackA invoked providing Enum status values
Possibly WCF CallbackB will be invoked requiring further input from the VB6 Client (This information can not be obtained at the start of MethodA and impacts the outcome of MethodA)
MethodA Returns
CallbackA (Works great, no Exceptions!) it is a OneWayOperation that provides an Enum, the VB application currently is writing this value to a RichTextbox.
CallbackB (Causes an AccessViolationException) is a Method that provides an object and expects a different object back with two value based properties back.
I feel this is some sort of an issue with attempting to create COM objects on a different thread than the main thread (since its currently hanging on MethodA). Unfortunately I am not sure how to correct this. We have control over the code within the service, the encapsulating dll and we can advise on code within the VB6 client.
We have our own VB6 testing application and we can bypass the AccessViolation error.... but it involves commenting out any code within the callback method (See code below) I have highlighted the lines that are causing the exception if left in "<----- Causes Exception". Any help is much appreciated, please let me know if you need more information.
Private Function ITerminalCallbackComClient_VerifySignature() As Long
Dim result As Long
'Not-Authorized = 0 and Authorized = 1'
result = 0
Dim msgResponse As Long
msgResponse = MsgBox("Signature Accepted?", vbYesNo + vbQuestion, "Signature Verification")
If msgResponse = vbYes Then
result = 1
End
End If
ITerminalCallbackComClient_VerifySignature = result
End Function
UPDATE 2014-11-13
The callback works while debugging in Visual Studio 6. But as soon as we "Make" the sample project it crashes when the callback is executed. If we remove the reference to the MsgBox and just map back a static value, it works as expected.
We have updated the Signature to our COM Interop to remove all object references and are not just returning a 0 or 1 to avoid object naming issues.
I have updated the VB6 callback code above.
Callback Contract
[CallbackBehaviorAttribute(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public abstract class PS_Terminal_Link_Callback : ITerminalCallback
{
public abstract long VerifySignature();
}
Service Contract
[ServiceContract(CallbackContract=typeof(ITerminalCallback))]
public interface ITerminal
{
*MethodA*
}
If that is VB6 code, LONG is a win32 integer in VB6. For compatability with 16 bit basic integers are 16 bit in VB6. Longs are 32 bit. You are putting a VB6 long (32 bit) into a VB6 integer (16 bit) in the message box line.
Your other object is private to you so we can't look up it's specs and docs.
You can also start in a debugger.
windbg or ntsd (ntsd is a console program and maybe installed). Both are also from Debugging Tools For Windows.
Download and install Debugging Tools for Windows
http://msdn.microsoft.com/en-us/windows/hardware/hh852363
Install the Windows SDK but just choose the debugging tools.
Create a folder called Symbols in **C:**
Start Windbg. File menu - Symbol File Path and enter
srv*C:\symbols*http://msdl.microsoft.com/download/symbols
then
windbg -o -g -G c:\windows\system32\cmd.exe /k batfile.bat
You can press F12 to stop it and kb will show the call stack (g continues the program). If there's errors it will also stop and show them.
Type lm to list loaded modules, x *!* to list the symbols and bp symbolname to set a breakpoint
If programming in VB6 then this environmental variable link=/pdb:none stores the symbols in the dll rather than seperate files. Make sure you compile the program with No Optimisations and tick the box for Create Symbolic Debug Info. Both on the Compile tab in the Project's Properties.
Also CoClassSyms (microsoft.com/msj/0399/hood/hood0399.aspx) can make symbols from type libraries.
Put a breakpoint on the COM call (use x *!* to find it).
Now you can examine parameters and/or see detailed exception info.
.
I'm writing a custom task scheduler, and I would like to know if there is any way of setting the processor affinity for the current thread on Mono (running on Linux).
For the .NET runtime running on Windows, I've managed to get this to work by following Lenard Gunda's Running .NET threads on selected processor cores article; however, his approach fails on Mono (and Linux) because:
It requires a P/Invoke call to GetCurrentThreadId in the Kernel32.dll library.
The Process.Threads property currently returns an empty collection on Mono.
Does anyone please have a workaround for this?
lupus's answer was on the right track, but it took me some further research to get this implemented (such as the P/Invoke signature for sched_setaffinity and the resolution of libc.so.6). Here's the working code (excluding error-handling) in case anyone needs it:
[DllImport("libc.so.6", SetLastError=true)]
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize,
ref ulong cpuset);
private static void SetAffinity(int processorID)
{
ulong processorMask = 1UL << processorID;
sched_setaffinity(0, new IntPtr(sizeof(ulong)), ref processorMask);
}
Edit: The above signature worked fine for my experiments, but refer to David Heffernan's answer (under my other question) for a suggested correction.
Note that you don't really have control of when a task gets run, that is up to the kernel.
Anyway, on Linux you will need to P/Invoke to sched_setaffinity() to bind a thread to a specific cpu.
See man sched_setaffinity for the interface.
I have a Windows Forms application running under .NET 4.0. This application imports a DLL which is available for:
32 bit
64 bit
Here is my code snippet:
[DllImport("my64Bit.dll"), EntryPoint="GetLastErrorText"]
private static extern string GetLastErrorText();
// Do some stuff...
string message = GetLastErrorText();
When calling this function (compiled for x64) the application just crashes. I can't even see any debug message in Visual Studio 2012. The identical code with the 32-bit-DLL (compiled for x86) works fine. The prototype is:
LPCSTR APIENTRY GetLastErrorText()
Unfortunately I don't have any further information about the DLL as it is a third-party product.
The function signature is quite troublesome. Whether your code will crash depends on what operating system you run. Nothing happens on XP, an AccessViolation exception is thrown on Vista and later.
At issue is that C functions returning strings need to typically do so by returning a pointer to a buffer that stores a string. That buffer needs to be allocated from the heap and the caller needs to release that buffer after using the string. The pinvoke marshaller implements that contract, it calls CoTaskMemFree() on the returned string pointer after converting it to a System.String.
That invariably turns out poorly, a C function almost never uses CoTaskMemAlloc() to allocate the buffer. The XP heap manager is very forgiving, it simply ignores bad pointers. Not the later Windows versions, they intentionally generate an exception. A strong enabler for the "Vista sucks" label btw, it took a while for programmers to get their pointer bugs fixed. If you have unmanaged debugging enabled then you'll get a diagnostic from the heap manager which warns that the pointer is invalid. Very nice feature but unmanaged debugging is invariably disabled when you debug managed code.
You can stop the pinvoke marshaller from trying to release the string by declaring the return value as IntPtr. You then have to marshal the string yourself with Marshal.PtrToStringAnsi() or one of its friends.
You still have the problem of having to release the string buffer. There is no way to do this reliably, you cannot call the proper deallocator. The only hope you have is that the C function actually returns a pointer to a string literal, one that's stored in the data segment and should not be released. That might work for a function that returns an error string, provided it doesn't implement anything fancy like localization. The const char* return type is encouraging.
You will need to test this to make sure there is no memory leak from not releasing the string buffer. Easy to do, call this function a billion times in a loop. If you don't get IntPtr.Zero as a return value and the program doesn't otherwise fall over with a out-of-memory exception then you're good. For 64-bit pinvoke you'll need to keep an eye on the test program's memory consumption.
Found it. The native function returns LPCSTR, i.e. the C# function cannot return a string. Instead an IntPtr must be returned like this:
[DllImport("my64Bit.dll"), EntryPoint="GetLastErrorText"]
private static extern IntPtr GetLastErrorText();
// Do some stuff...
IntPtr ptr = GetLastErrorText();
string s = Marshal.PtrToStringAnsi(ptr);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to Debug .net applications without Visual Studio
Hi i made a small program it works for me and for a few people
but its being crashed at a friend
how can i debug and learn which lines exactly causes error?
without installing visual studio
Best you can do is (and is a good coding practice) in a new buid add try catch exception block in methods with logging facility that logs(in catch block) in lets say a text file
Method Name (Find using new StackTrace()..GetFrame(1).GetMethod().Name or System.Reflection.MethodBase.GetCurrentMethod().Name),
its parameters and
Exception message.
If you don't mean "without installing a debugger" you could try using Mono.
You can use WinDbg which can be run portable (xcopy from an existing installation), and with the SoS add-on it can help a lot in debugging C# applications - even in post mortem. It might be difficult to grasp at first, but it's worth learning - it will come very useful in several situations.
SoS reference here : http://msdn.microsoft.com/en-us/library/bb190764.aspx
I have this quick cheat-sheet with what I found most useful (found somewhere on the internet and then enriched with time) :
Starting, Attaching, Executing and Exiting
Start -> All Programs -> Debugging Tools for Windows -> WinDbg
F6
attach to process
Ctrl-Break
interrupt debugee
.detach
detach from a process
g
continue debugee execution
q
exit WinDbg
Getting Help
?
help on commands that affect the debugee
.help
help on commands that affect the debugger
.hh command
view the on line help file
!help
help on the extension dll at the top of the chain (e. g., SOS)
Issuing Commands
up arrow, down arrow, enter
scroll through command history
Right mouse button
paste into command window
Examining the Unmanaged Environment
lmf
list loaded modules with full path
lmt
list loaded modules with last modified timestamp
~
list unmanaged threads
~thread s
select a thread for thread specific commands
!token -n
view thread permissions
k
view the unmanaged call stack
!runaway
view thread CPU consumption
bp
set a breakpoint
.dump path
dump small memory image
.dump /ma path
dump complete memory image
Working with Extension DLLs (e. g., SOS)
.chain
list extensions dlls
.load clr10\sos
load SOS for debugging framework 1.0 / 1.1 (use .unload to unload)
.loadby sos mscorwks
load SOS for debugging framework 2.0
.loadby sos clr
load SOS for debugging framework 4.0
SOS Commands
!threads
view managed threads
!clrstack
view the managed call stack
!dumpstack
view combined unmanaged & managed call stack
!clrstack -p
view function call arguments
!clrstack –l
view stack (local) variables
!name2ee module class
view addresses associated with a class or method
!dumpmt –md address
view the method table & methods for a class
!dumpmd address
view detailed information about a method
!do address
view information about an object
!dumpheap –stat
view memory consumption by type
!dumpheap –min size
view memory consumption by object when at least size
!dumpheap –type type
view memory consumption for all objects of type type
!gcroot address
view which object are holding a reference to address
!syncblk
view information about managed locks
SOS 2.0 Commands
!bpmd module method
set breakpoint
!DumpArray address
view contents of an array
!PrintException
view information about most recent exception
If you don't want to install any other debugger,
Then you should simply implement trace and log on each section of code carefully and then you can view the traces or errors on the text file..
Ways to implement trace and log:
use can use TraceListener class on system.diaognosis namespace
or use
Microsoft.Practices.EnterpriseLibrary.Logging namespace's class `Logger` to implement tracing:
syntax:
Logger.Write(message, "Trace", 0, 0, System.Diagnostics.TraceEventType.Information);
I am building on C++ dll, by writing code in C#.
I get an error, saying
LoaderLock was detected Message:
Attempting managed execution inside OS
Loader lock. Do not attempt to run
managed code inside a DllMain or image
initialization function since doing so
can cause the application to hang.
I tried seraching what this error exactly means, but I am drawing pointless articles, mostly saying that it's just a warning, and I should switch that off in Visual Studio.
The other solutions seem to be due to ITunes, or this problem occurring when programming with DirectX. My problem is connected to neither.
Can anybody explain, what this actually means?
you need to go to menu Debug -> Exceptions, open the Managed Debugging Assistants, find LoaderLock and uncheck
The general idea of loader lock:
The system runs the code in DllMain inside a lock (as in - synchronization lock). Therefore, running non-trivial code inside DllMain is "asking for a deadlock", as described here.
The question is, why are you trying to run code inside DllMain? Is it crucial that this code run inside the context of DllMain or can you spawn a new thread and run the code in it, and not wait for the code to finish execution inside DllMain?
I believe that the problem with manged code specifically, is that running managed code might involves loading the CLR and suchlike and there's no knowing what could happen there that would result in a deadlock... I would not heed the advice of "disable this warning" if I were you because most chances are you'll find your applications hangs unexpectedly under some scenarios.
UPDATE FOR .NET 4.0 AND MORE RECENT FRAMEWORKS
This is an old question asked at the time of .Net 2.0, when support for mixed mode DLLs had serious initialization problems, prone to random deadlocks. As of .Net 4.0, the initialization of mixed mode DLLs has changed. Now there are two separate stages of initialization:
Native initialization, called at the DLL's entry point, which includes native C++ run-time setup and execution of your DllMain method.
Managed initialization, executed automatically by system loader.
Since step #2 is performed outside of the Loader Lock, there is no deadlocks. The details are described at Initialization of Mixed Assemblies.
To ensure your mixed mode assembly can be loaded from a native executable, the only thing you need to check is that DllMain method is declared as native code. #pragma unmanaged could help here:
#pragma unmanaged
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
... // your implementation here
}
It is also important that any code that DllMain might call directly or indirectly is also unmanaged. It makes sense to limit the type of functionality used by DllMain so you trace all code reachable from DllMain and ensure it is all compiled with #pragma unmanaged.
Compiler helps a little by giving you warining C4747 if it detects that DllMain is not declared as unmanaged:
1> Generating Code...
1>E:\src\mixedmodedll\dllmain.cpp : warning C4747: Calling managed 'DllMain': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint
However compiler won't generate any warnings if DllMain indirectly calls some other managed function, so you need to ensure that never happens, otherwise your application could deadlock randomly.
kindly remind those VS2017 users that you need to disable "exception helper" instead of "exception assistant"(before VS2017) to prevent from loader lock error, which setting path is Debug->Exception. Just ran int to this problem and wasted 2 hours searching for solutions...
Press ctr d+e Then Expend Managed Debugging Assistants Node. Then Unchecked the LoaderLock.
Hope this will help you.
I recently got this error while creating an instance of an COM-Object written in native code:
m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy"));
This led to the described error. A "LoaderLock was detected"-Exception was thrown.
I overcame this error by creating the object-instance in an extra thread:
ThreadStart threadRef = new ThreadStart(delegate { m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy")); });
Thread myThread = new Thread(threadRef);
myThread.Start();
myThread.Join(); // for synchronization
I'm building a C++ CLR DLL (MSVS2015) that has to make calls into an unmanaged DLL and define unmanaged code. I use #pragma managed and #pragma unmanaged to control what mode it is in for a given area of the code.
In my case I simply put #pragma unmanaged in front of my DllMain() and this solved the problem.
It seemed to be thinking I wanted a managed version of DllMain().
The setting path in my visual studio 2017 instance is Debug -> Windows -> Exception Settings . The exception settings "window" showed up in the bottom tab group (as opposed to a separate window), took me a while to notice it. Search for "loader".
This problem occurs because of the way in which the debugger in Visual Studio runs managed applications that use Microsoft Foundation Classes version 8.0 in one or more DLL files.
Have a thorough reading at: http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx