HRESULT GetInstalledClrRuntimes(ICLRMetaHost *clrMetaHost, std::vector<std::wstring>& clrRuntimeList)
{
    HRESULT hr = S_OK;		
    clrRuntimeList.clear();

    IEnumUnknown* runtimeEnumerator = nullptr;
    hr = clrMetaHost->EnumerateInstalledRuntimes(&runtimeEnumerator);
    if (SUCCEEDED(hr)) {
        WCHAR currentRuntime[50];
        DWORD bufferSize = ARRAYSIZE(currentRuntime);
        IUnknown* runtime = nullptr;
        while (runtimeEnumerator->Next(1, &runtime, NULL) == S_OK)
        {
            ICLRRuntimeInfo* runtimeInfo = nullptr;
            hr = runtime->QueryInterface(IID_PPV_ARGS(&runtimeInfo));
            if (SUCCEEDED(hr))
            {
                hr = runtimeInfo->GetVersionString(currentRuntime, &bufferSize);
                if (SUCCEEDED(hr))
                {
                    clrRuntimeList.push_back(std::wstring(currentRuntime));
                }
                runtimeInfo->Release();
            }
            runtime->Release();
        }
        runtimeEnumerator->Release();
        hr = S_OK;
    }

    return hr;
}
VOID StartAssembly(vector<wstring> const& params) 
{
	ICLRMetaHost *pMetaHost = NULL;
    HRESULT hr;
    hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost,
        (LPVOID*)&pMetaHost);

    if (SUCCEEDED(hr))
    {
        IEnumUnknown *peunkRuntimes;
        hr = pMetaHost->EnumerateInstalledRuntimes(&peunkRuntimes);
        if (SUCCEEDED(hr))
        {
            // *** FINDING LATEST RUNTIME ***
            IUnknown *punkRuntime;
            ICLRRuntimeInfo *prtiLatest = NULL;
            WCHAR szLatestRuntimeVersion[MAX_PATH];
            while (peunkRuntimes->Next(1, &punkRuntime, NULL) == S_OK)
            {
                ICLRRuntimeInfo *prtiCurrent;
                hr = punkRuntime->QueryInterface(IID_PPV_ARGS(&prtiCurrent));
                if (SUCCEEDED(hr))
                {
                    if (!prtiLatest)
                    {
                        hr = prtiCurrent->QueryInterface(IID_PPV_ARGS(&prtiLatest));
                        if (SUCCEEDED(hr))
                        {
                            DWORD cch = ARRAYSIZE(szLatestRuntimeVersion);
                            hr = prtiLatest->GetVersionString(szLatestRuntimeVersion, &cch);
                        }
                    }
                    else
                    {
                        WCHAR szCurrentRuntimeVersion[MAX_PATH];
                        DWORD cch = ARRAYSIZE(szCurrentRuntimeVersion);
                        hr = prtiCurrent->GetVersionString(szCurrentRuntimeVersion, &cch);
                        if (SUCCEEDED(hr))
                        {
                            if (wcsncmp(szLatestRuntimeVersion, szCurrentRuntimeVersion, cch) < 0)
                            {
                                hr = prtiCurrent->GetVersionString(szLatestRuntimeVersion, &cch);
                                if (SUCCEEDED(hr))
                                {
                                    prtiLatest->Release();
                                    hr = prtiCurrent->QueryInterface(IID_PPV_ARGS(&prtiLatest));
                                }
                            }
                        }
                    }
                    prtiCurrent->Release();
                }
                punkRuntime->Release();
            }
            peunkRuntimes->Release();

            // *** STARTING CLR ***
            if (SUCCEEDED(hr))
            {
                ICLRRuntimeHost *prth;
                hr = prtiLatest->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&prth);
                if (SUCCEEDED(hr))
                {
					hr = prth->Start();
					if (SUCCEEDED(hr))
					{
						DWORD dwRet = 0;
						hr = prth->ExecuteInDefaultAppDomain(params.at(0).c_str(), params.at(1).c_str(), 
							params.at(2).c_str(), params.at(3).c_str(), &dwRet);
						// hr = 0x80131513 (System.MissingMethodException)

						if (SUCCEEDED(hr))
						{
							// *** Success ***
							MessageBox(GetDesktopWindow(), L"Successfully called managed function.", L"Success", MB_OK);
						}
						hr = prth->Stop();
					}
					prth->Release();
                }
            } 
        }
        pMetaHost->Release();
    }
}
Exemple #3
0
STDAPI AttachProfiler(int pid, LPCWSTR wszTargetVersion, LPCWSTR wszProfilerPath, ProfConfig * pProfConfig, BOOL fConsoleMode)
{
    HMODULE hModule = NULL;
    LPVOID pvClientData = NULL;
    DWORD cbClientData = 0;
    HRESULT hr;

    ICLRMetaHost * pMetaHost = NULL;
    IEnumUnknown * pEnum = NULL;
    IUnknown * pUnk = NULL;
    ICLRRuntimeInfo * pRuntime = NULL;
    ICLRProfiling * pProfiling = NULL;

    g_fConsoleMode = fConsoleMode;

    DWORD dwProfileeProcessID = (DWORD) pid;

    CLSID clsidProfiler;
    CLSIDFromString(PROFILER_GUID_WCHAR, &clsidProfiler);
    
    DWORD dwMillisecondsMax = pProfConfig->dwDefaultTimeoutMs;

    bool fCLRFound = false;

    //---------------------------------------------------------------------------------------
    // GET AND CALL API
    //---------------------------------------------------------------------------------------

    hModule = LoadLibrary(L"mscoree.dll");
    if (hModule == NULL)
    {
        Log(L"LoadLibrary mscoree.dll failed.  hr=0x%x.\n", hr = HRESULT_FROM_WIN32(GetLastError()));
        goto Cleanup;
    }

    // Note: This is the ONLY C export we need out of mscoree.dll.  This enables us to
    // get started with the metahost interfaces, and it's all COM from that point
    // forward.
    CLRCreateInstanceFnPtr pfnCreateInstance = 
        (CLRCreateInstanceFnPtr)GetProcAddress(hModule, "CLRCreateInstance");
    if (pfnCreateInstance == NULL)
    {
        Log(L"GetProcAddress on 'CLRCreateInstance' failed.  hr=0x%x.\n", hr = HRESULT_FROM_WIN32(GetLastError()));
        goto Cleanup;
    }

    hr = (*pfnCreateInstance)(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID *)&pMetaHost);
    if (FAILED(hr))
    {
        Log(L"CLRCreateInstance IID_ICLRMetaHost' failed.  hr=0x%x.\n", hr);
        goto Cleanup;
    }

    // Cross-user attach requires the SE_DEBUG_NAME privilege, so attempt to enable it
    // now.  Even if the privilege is not found, the CLRProfiler still continues to attach the target process.
    // We'll just fail later on if we do try to attach to a different-user target process.
    HRESULT hrEnableDebugPrivilege = EnableDebugPrivilege();
    
    HANDLE hndProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProfileeProcessID);
    if (hndProcess == NULL)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        //If EnableDebugPrivilege is not successful, let the customer know running CLRProfiler as administrator may solve the problem.
        if (hrEnableDebugPrivilege == E_FAIL) 
        {
            Log(L"CLRProfiler can not open the target process %d (error: 0x%x), probably because CLRProfiler could not enable the debug privilege (error: 0x%x).  \n"
                L"Please run the CLRProfiler as administrator and try again.", dwProfileeProcessID, hr, hrEnableDebugPrivilege);
        }
        else
        {
            Log(L"OpenProcess failed.  hr=0x%x.\n", hr);
        }
        goto Cleanup;
    }

    // One process may have multiple versions of the CLR loaded.  Grab an enumerator to
    // get back all the versions currently loaded.
    hr = pMetaHost->EnumerateLoadedRuntimes(hndProcess, &pEnum);
    if (FAILED(hr))
    {
        Log(L"EnumerateLoadedRuntimes' failed.  hr=0x%x.\n", hr);
        goto Cleanup;
    }

    while (pEnum->Next(1, &pUnk, NULL) == S_OK)
    {
        hr = pUnk->QueryInterface(IID_ICLRRuntimeInfo, (LPVOID *) &pRuntime);
        if (FAILED(hr))
            goto LoopCleanup;
       
        WCHAR wszVersion[30];
        DWORD cchVersion = ARRAY_LEN(wszVersion);
        hr = pRuntime->GetVersionString(wszVersion, &cchVersion);
        if (SUCCEEDED(hr) && _wcsnicmp(wszVersion, wszTargetVersion, min(cchVersion, wcslen(wszTargetVersion))) == 0)
        {
            fCLRFound = true;
            hr = pRuntime->GetInterface(CLSID_CLRProfiling, IID_ICLRProfiling, (LPVOID *)&pProfiling);
            if (FAILED(hr))
            {
                Log(L"Can not get the ICLRProfiling interface. Error: 0x%x.", hr);
                break;
            }
            // Here it is!  Attach the profiler!
            // The profilee may not have access to the profler dll 
            // Give it a try.
            hr = pProfiling->AttachProfiler(dwProfileeProcessID,
                                            dwMillisecondsMax,
                                            &clsidProfiler,
                                            wszProfilerPath,
                                            (LPVOID)pProfConfig,
                                            sizeof(*pProfConfig));


            if(FAILED(hr))
            {
                if (hr == ERROR_TIMEOUT)//ERROR_TIMEOUT 
                {
                    Log(L"CLRProfiler timed out to attach to the process.\nPlease check the event log to find out whether the attach succeeded or failed.");
                }
                else if (hr == COR_E_UNAUTHORIZEDACCESS)//0x80070005
                {
                    Log(L"CLRProfiler failed to attach to the process with error code 0x80070005(COR_E_UNAUTHORIZEDACCESS).\n"
                        L"This may occur if the target process(%d) does not have access to ProfilerOBJ.dll or the directory in which ProfilerOBJ.dll is located.\n"
                        L"Please check event log for more details.", pid);
                }
                else if (hr == CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE)
                {
                    Log(L"Profiler initialization failed because the target process is running with concurrent GC enabled. Either\n"
                        L"  1) turn off concurrent GC in the application's configuration file before launching the application, or\n" 
                        L"  2) simply start the application from CLRProfiler rather than trying to attach CLRProfiler after the application has already started.");
                }
                else
                {
                    Log(L"Attach Profiler Failed 0x%x, please check the event log for more details.", hr);
                }
                    
            }

            pProfiling->Release();
            pProfiling = NULL;
            break;
        }

LoopCleanup:
        if (pRuntime != NULL)
        {
            pRuntime->Release();
            pRuntime = NULL;
        }

        if (pUnk != NULL)
        {
            pUnk->Release();
            pUnk = NULL;
        }
    }

    if (fCLRFound == false)
    {
        Log(L"No CLR Version %s is loaded into the target process.", wszTargetVersion);
        hr = E_FAIL;
    }



Cleanup:

    if (pRuntime != NULL)
    {
        pRuntime->Release();
        pRuntime = NULL;
    }

    if (pUnk != NULL)
    {
        pUnk->Release();
        pUnk = NULL;
    }

    if (pEnum != NULL)
    {
        pEnum->Release();
        pEnum = NULL;
    }

    if (pMetaHost != NULL)
    {
        pMetaHost->Release();
        pMetaHost = NULL;
    }

    if (hModule != NULL)
    {
        FreeLibrary(hModule);
        hModule = NULL;
    }

    return hr;
}