Нужно получить строку, содержащую цепочку вызывающих модулей
Всем привет и заранее спасибо. Мне нужно получить строку, содержащую цепочку вызывающих модулей:
Консольное приложение C# exe (C# 1.exe), которое содержит только функцию Main, в которой вызывается функция FunctionDLL() библиотеки C# 2.dll
Main() { FunctionDLL() }
Библиотека C# (C# 2.dll), которая содержит одну функцию FunctionDLL (), эта функция вызывает функцию GetModulePaths () из библиотеки C ++ C ++ 3.dll
public static string FunctionDLL() { return GetModulePaths(); }
Библиотека C++ (C++ 3.dll), которая содержит одну функцию GetModulePaths () и возвращает строку, содержащую цепочку вызывающих модулей. Мне нужно получить список полных путей к модулям строгого порядка, например::
"C:\Projects\C# 1.exe C:\Projects\C# 2.dll C:\Projects\C++ 3.dll"
РЕШЕНО невозможно получить из неуправляемого кода стектрэйс (и пути к вызывающим модулям соответсвенно) на управляемый код, который его вызывает. максимум что я смог получить из неуправляемой С++ DLL - это путь к .Net модулю clr.dll из управляемого - можно. смотри пример тут:
https://www.codeproject.com/Articles/17386/Get-the-calling-module-that-invoked-your-function
Ответы (1 шт):
Невозможно получить из неуправляемого кода стектрэйс (и пути к вызывающим модулям соответсвенно) на управляемый код, который его вызывает. Для решения проблемы можно создать C++ библиотеку смешанного типа (mixed type, Common Language Runtime Support (/clr)). Здесь анализируется, является ли полученный с помощью метода CaptureStackBackTrace() модуль модулем управляемого кода, это происходит с помощью вызова метода управляемого кода (С++/CLI) IsDotNetRuntime. И если это модуль управляемого кода, то с помощью метода GetDotNetCallerFileName() получаем путь к нему. Вот пример управляемого кода в этой библиотеке:
int GetDotNetCallerFileName(string& module)
{
int res = FALSE;
try
{
Assembly^ callerAssembly = Assembly::GetCallingAssembly();
if (callerAssembly == nullptr)
return FALSE;
String^ sysdir = System::Runtime::InteropServices::RuntimeEnvironment::GetRuntimeDirectory();
//skip all .net framework assemblies and calls from the same assembly
String^ strCallerPath = callerAssembly->Location;
String^ directoryName = nullptr;
if (strCallerPath != nullptr)
directoryName = Path::GetDirectoryName(strCallerPath) + "\\";
while (directoryName != nullptr && (String::Compare(sysdir, directoryName, true) == 0)
|| callerAssembly == Assembly::GetExecutingAssembly())
{
strCallerPath = nullptr;
callerAssembly = callerAssembly->GetCallingAssembly();
directoryName = nullptr;
if (strCallerPath != nullptr)
directoryName = Path::GetDirectoryName(strCallerPath) + "\\";
strCallerPath = callerAssembly->Location;
}
pin_ptr<const wchar_t> wch = PtrToStringChars(strCallerPath);
size_t convertedChars = 0;
size_t sizeInBytes = ((strCallerPath->Length + 1) * 2);
errno_t err = 0;
char* ch = (char*)malloc(sizeInBytes);
err = wcstombs_s(&convertedChars,
ch, sizeInBytes,
wch, sizeInBytes);
if (err == 0)
module = ch;
free(ch);
res = TRUE;
}
catch (Exception^ e)
{
Console::WriteLine(e->Message);
}
finally
{
}
return res;
}
BOOL IsDotNetRuntime(char* callerModulePath)
{
//check for .net runtime path
String^ path = Marshal::PtrToStringAnsi((IntPtr)callerModulePath);
String^ directoryName;
directoryName = Path::GetDirectoryName(path) + "\\";
String^ sysdir = RuntimeEnvironment::GetRuntimeDirectory();
if (String::Compare(sysdir, directoryName, true) == 0)
return TRUE;
return FALSE;
}