Jump to content
Tuts 4 You

Clr Profiler - difficulties with communications


CodeExplorer

Recommended Posts

CodeExplorer

Clr Profiler - difficulties on communications - on tracing result result back from dll to main exe's listview.
I have an Visual Studio 2010 project, profiler.dll is made on C++, main exe interface is also made on C++.
I've set two environment variables:
Cor_Enable_Profiling=1
COR_PROFILER={DFEC737C-D0B1-4b86-A6FD-FDD998BEEB03}
and I start the process with CreateProcess
The problems comes that I can't log event information back to main exe interface - listview.
Profiler dll gets called inside traced process.

Already tried:
main exe:

    unsigned int wndHandle = (unsigned int)GetDlgItem(IDC_LIST1)->m_hWnd;

    char buffer[10];
    std::sprintf(buffer, "hWnd=%d", (unsigned int)GetDlgItem(IDC_LIST1)->m_hWnd);
    std::string m_hWnd_str(buffer);


    const DWORD buffSize = 65535;
    static char buffer[buffSize];
    if (GetEnvironmentVariableA("hWnd", buffer, buffSize))
    {
    clist_hwnd = (HWND)atoi(buffer);
 

void Profiler::InsertStringToList(char* strToAdd)
{

    
            LVITEM item;
            item.mask = LVIF_TEXT;
            item.pszText = _T("Column Text");
            item.iItem = 0;      // Item number
            item.iSubItem = 0;         // Sub item number (column number)
            ::SendMessageA(clist_hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);

...

}

InsertStringToList("string test")

It just crushes.
 

Link to comment

What kind of IPC are you using ?

I released the full code of my Tracer long time ago and I think you can use some parts of it to solve this.

I used WM_COPYDATA for IPC.

  • Like 1
Link to comment

how do you send data from the .NET process being profiled to the Process of the Profiler receiving data and viewing it ?

you need something like one of those methods for IPC.

Link to comment
CodeExplorer
1 hour ago, Kurapica said:

how do you send data from the .NET process being profiled to the Process of the Profiler receiving data and viewing it ?

you need something like one of those methods for IPC.

I previously posted some code , I was trying to send the message to windows handle - listview m_hWnd
pass the handle as Environment variable hWnd=%d
then receive environment variable and convert it back: clist_hwnd = (HWND)atoi(buffer);
then just send message to listview handle using SendMessageA apis
 

Quote

 

void Profiler::InsertStringToList(char* strToAdd)
{

    
            LVITEM item;
            item.mask = LVIF_TEXT;
            item.pszText = _T("Column Text");
            item.iItem = 0;      // Item number
            item.iSubItem = 0;         // Sub item number (column number)
            ::SendMessageA(clist_hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);

...

}

 

What is IPC? for what it stand for?
 

 

Edited by CodeExplorer
Link to comment

LVM_INSERTITEM deals with a structure that contains lots of pointers. Those pointers must be valid pointers and point to valid data inside your GUI process (=profiler.exe). You can't just take a random structure from one process and expect it to magically appear inside another process. (See more https://comp.os.ms-windows.programmer.win32.narkive.com/R6rjEbET/pointer-to-data-in-postmessage-lparam#post3)

That's where IPC (Inter Process Communication) comes into play. There are plenty of options (https://learn.microsoft.com/en-us/windows/win32/ipc/interprocess-communications) but @Kurapica already gave you possibly the easiest solution.

  • Like 2
Link to comment
CodeExplorer

I've succeed on the communication part, now data is send to main exe.
The problem is with adding string to listview:

 

LRESULT CALLBACK WMCOPYWNDPROC(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 
  LVITEM item;
  LPWM_DATASTRUCTURE lpMsg;
  if (uMsg == WM_COPYDATA) {
     lpMsg = (LPWM_DATASTRUCTURE)((COPYDATASTRUCT*)lParam)->lpData;

     lpMsg->Data[lpMsg->cbSize]='\0';  // mark the end of string

     switch(lpMsg->iMessage)
     {
        case    WM_DISPLAY_TEXT:
                //TPRINTF(_T("\n"));
                //TPRINTF(lpMsg->Data);
            //::MessageBoxA(NULL, lpMsg->Data, "Error!", MB_OK);
            if (CClrTracerMainDlg::clist_hwnd!=NULL)
            {
            item.mask = LVIF_TEXT;
            item.pszText =  (LPSTR)&lpMsg->Data;
            item.iItem = 0;      // Item number
            item.iSubItem = 0;         // Sub item number (column number)
            ::SendMessageA(CClrTracerMainDlg::clist_hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
            }

        break;

        case    WM_QUIT_SERVER:
                PostQuitMessage(0);
        break;
     }
     return 0;
  }        
  else
   return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}

 

I've initialized clist_hwnd like this:
    clist_hwnd = GetDlgItem(IDC_LIST1)->m_hWnd;
    DWORD myThreadID;
    HANDLE myHandle = ::CreateThread(0, 0, ServerThread, &clist_hwnd, 0, 0);

Problems comes on ::SendMessageA, program freezes, also noticed wrong value of iItem/mask/iSubItem and good value of item.pszText - how it is possible?
 

Link to comment

I think you should remove this "return 0;" in your WMCOPYWNDPROC

I checked my old Tracer GUI code and noticed this possible error in your code

image.png.ef3e9ad24fc5e50034c9120cb5200caf.png

Link to comment
  • 3 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...