С# обмен данными с DLL C++ - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте уважаемые ГУРУ!

Функция DLL на с++

в результате работы формирует строку типа

_bstr_t

Эту строку нужно передать в код на

С#

Делаю ледующим образом: 1. На С# получаю указатель на выделенный блок памяти и передаю его параметром в функцию dll на С++ 2. В DLL создается строка с типом _bstr_t ID, которая преобразуется в массив char и записывается по адресу переданному из С#в параметре Проблема: В С# приходит не вся строка, а только

"BaseBoard="

Само значение _bstr_t BaseBoard не передается. То есть передается только

константная часть

строки ID Если передать

только переменную_bstr_t BaseBoard

то выскакивает исключение что передаваемое значение не может быть NULL Хотя когда DLL функция тестируется как консольное приложение то все работает, Переменная _bstr_t ID содержит и константную часть и значение переменной _bstr_t BaseBoard. Помогите пожалуйста найти грабли. Заранее благодарен всем откликнувшимся . С#
[DllImport(@"D:\\ProjectsC++\\DLL\\MyDLL\\Debug\\MyDLL.dll",
                        EntryPoint = "GetString",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.Cdecl)]
 
public static extern int GetString(IntPtr pComputerName); 

var pComputerName = Marshal.AllocHGlobal(256);
// Вызываем описанную внешнюю функцию
GetString(pComputerName, ref size);
// Переводим результат в управляемый вид
var str = Marshal.PtrToStringUni(pComputerName);
//Освобождаем выделенную память
Marshal.FreeHGlobal(pComputerName);
С++:
define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>#
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
 
extern "C" __declspec(dllexport)  int GetString(char *pMemory)
{
    HRESULT hres;
    // Step 1: -------------------------------------------------- 
    // Initialize COM. ------------------------------------------
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);  
    if (FAILED(hres)) 
    { 
        cout << "Failed to initialize COM library. Error code = 0x"  
            << hex << hres << endl; 
        return 1;                  // Program has failed. 
    }
    // Step 2: -------------------------------------------------- 
    // Set general COM security levels --------------------------
    hres =  CoInitializeSecurity( 
        NULL,  
        -1,                          // COM authentication 
        NULL,                        // Authentication services 
        NULL,                        // Reserved 
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication  
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation   
        NULL,                        // Authentication info 
        EOAC_NONE,                   // Additional capabilities  
        NULL                         // Reserved 
        );
    if (FAILED(hres)) 
    { 
        cout << "Failed to initialize security. Error code = 0x"  
            << hex << hres << endl; 
        CoUninitialize(); 
        return 1;                    // Program has failed. 
    }      
    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------
    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance( 
        CLSID_WbemLocator,              
        0, 
        CLSCTX_INPROC_SERVER,  
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres)) 
    { 
        cout << "Failed to create IWbemLocator object." 
            << " Err code = 0x" 
            << hex << hres << endl; 
        CoUninitialize(); 
        return 1;                 // Program has failed. 
    }
    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method 
    IWbemServices *pSvc = NULL; 
    // Connect to the root\cimv2 namespace with 
    // the current user and obtain pointer pSvc 
    // to make IWbemServices calls. 
    hres = pLoc->ConnectServer( 
         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace 
         NULL,                    // User name. NULL = current user 
         NULL,                    // User password. NULL = current 
         0,                       // Locale. NULL indicates current 
         NULL,                    // Security flags. 
         0,                       // Authority (for example, Kerberos) 
         0,                       // Context object  
         &pSvc                    // pointer to IWbemServices proxy 
         );   
 
    if (FAILED(hres)) 
    { 
        cout << "Could not connect. Error code = 0x"  
             << hex << hres << endl; 
        pLoc->Release();      
        CoUninitialize(); 
        return 1;                // Program has failed. 
    }
    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
    // Step 5: -------------------------------------------------- 
    // Set security levels on the proxy -------------------------
    hres = CoSetProxyBlanket( 
       pSvc,                        // Indicates the proxy to set 
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
       NULL,                        // Server principal name  
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx  
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx 
       NULL,                        // client identity 
       EOAC_NONE                    // proxy capabilities  
    );
 
    if (FAILED(hres)) 
    { 
        cout << "Could not set proxy blanket. Error code = 0x"  
            << hex << hres << endl; 
        pSvc->Release(); 
        pLoc->Release();      
        CoUninitialize(); 
        return 1;               // Program has failed. 
    }
  // Step 6: -------------------------------------------------- 
    // Use the IWbemServices pointer to make requests of WMI ----
  // For example, get the name of the operating system 
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery( 
        bstr_t("WQL"),  
        bstr_t("SELECT * FROM Win32_BaseBoard"), 
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,  
        NULL, 
        &pEnumerator); 
    
    if (FAILED(hres)) 
    { 
        cout << "Query for operating system name failed." 
            << " Error code = 0x"  
            << hex << hres << endl; 
        pSvc->Release(); 
        pLoc->Release(); 
        CoUninitialize(); 
        return 1;               // Program has failed.
    }
    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0; 
    while (pEnumerator) 
    { 
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,  
            &pclsObj, &uReturn); 
        if(0 == uReturn) 
        { 
            break; 
        } 
        VARIANT vtProp;
        // Get the value of the Name property 
        hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);  //BSTR vtProp
    _bstr_t BaseBoard(vtProp.bstrVal);
    _bstr_t ID = "BaseBoard=" + BaseBoard; 
    [B]//преобразуем _bstr_t ID в массив char и записываем его по переданному в параметре адресу[/B]
    strcpy_s(pMemory, ID.length() + 1, (LPCSTR)ID);
 
        VariantClear(&vtProp); 
        pclsObj->Release(); 
    }
    // Cleanup 
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
    
    return 0;
}

Решение задачи: «С# обмен данными с DLL C++»

textual
Листинг программы
string wmiQuery = "SELECT * FROM Win32_OperatingSystem";
 
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher ( wmiQuery ))
{
   ManagementObjectCollection retObjectCollection = searcher.Get ( );
 
   foreach (ManagementObject retObject in retObjectCollection)
   {
       string result = retObject["Name"];
       break;
   }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

15   голосов , оценка 4.067 из 5