2014-09-02 122 views
1

我想從C#傳遞一個字符串到C++的DLL。我在dll中接收的字符串是一些奇怪的字符。這是我的代碼。從C#傳遞字符串到C++的dll

在C++中的dll:

#include "stdafx.h" 
#include <tlhelp32.h> 
#include <tchar.h> 
#include "ProcessCheckerDll.h" 
#include <fstream> 
#include <algorithm> 
#include <iostream> 
#include <stdio.h> 
#include <psapi.h> 
#include "Shlwapi.h" 
#include <string> 
#include <windows.h> 


namespace ProcessCheck 
{ 
string GetRunningProcessFromHierarchy(char* argStrRoot) 
{ 
    char ch; 
    printf("Reached here 1."); 
    scanf_s("%c",&ch); 

    std::string strRoot(argStrRoot,strlen(argStrRoot)); 
    printf_s("strRoot = %s",strRoot); 
    std::ifstream input("d:\\filelist.txt"); 
    std::string line; 

    printf("Reached here 2."); 
    scanf_s("%c",&ch); 

    //printf("cdsroot=%ls",strRoot); 

    std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), ::tolower); 
    std::vector<std::string> collection; 
    string result=""; 


    printf("Reached here 3."); 
    scanf_s("%c",&ch); 

    HANDLE hProcessSnap=nullptr; 
    HANDLE hProcess; 
    PROCESSENTRY32 pe32; 
    DWORD dwPriorityClass; 


    while(std::getline(input, line)) 
    { 
     //Get the file name from path 
     std::wstring strPathFromTextFile = std::wstring(line.begin(), line.end()); 
     LPCWSTR absolutePathToFile = strPathFromTextFile.c_str(); 
     LPCWSTR onlyFileName = PathFindFileName(absolutePathToFile); 

     // Take a snapshot of all processes in the system. 
     hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
     if(hProcessSnap == INVALID_HANDLE_VALUE) 
     { 
      printf("Failed to get the snapshot of running processes"); 
      return result; 
     } 

     pe32.dwSize = sizeof(PROCESSENTRY32); 

     // Retrieve information about the first process and exit if unsuccessful 
     if(!Process32First(hProcessSnap, &pe32)) 
     { 
      printf("Failed to get the first process from the list"); 
      CloseHandle(hProcessSnap);  // clean the snapshot object 
      return result; 
     } 

     // Now walk the snapshot of processes, and display information about each process in turn 
     do 
     { 
      LPCWSTR processFileName = pe32.szExeFile; 

      if(lstrcmpi(onlyFileName,processFileName)==0) 
      { 
       //If file name is same, check if path starts with cdsroot 
       HANDLE processHandle = NULL; 
       TCHAR filePath[MAX_PATH]; 

       processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); 


       if (processHandle != NULL) 
       { 
        if (GetModuleFileNameEx(processHandle, NULL, filePath, MAX_PATH) == 0) 
        { 
         printf("\nFailed to get module filename."); 
        } 
        else 
        { 
         std::wstring w_str(filePath); 
         std::string absolutePath(w_str.begin(), w_str.end()); 
         std::transform(absolutePath.begin(), absolutePath.end(), absolutePath.begin(), ::tolower); 

         printf_s("Absolute path = %s", absolutePath); 
         printf_s("Matching with cdsroot = %s",strRoot); 
         if(absolutePath.find(strRoot)==0) 
         { 
          std::wstring processName(processFileName); 
          std::string strProcess(processName.begin(),processName.end()); 
          printf_s("\nROOT match for Process name = %s",strProcess); 

          if (std::find(collection.begin(), collection.end(), strProcess) == collection.end()) 
          { 
           collection.push_back(strProcess); 
           printf_s("\nAdding to collection Process name = %s",strProcess); 
           result = result + strProcess + ";"; 
          } 
         } 
        } 
        CloseHandle(processHandle); 
       } 
       else 
       { 
        printf("\nFailed to open process."); 
       } 
      } 
     } 
     while(Process32Next(hProcessSnap, &pe32)); 
    } 

    CloseHandle(hProcessSnap); 
    printf("Returning result %s", result); 
    scanf_s("%c",&ch); 
    return result; 
} 
} 

頭文件包含:

#include <stdexcept> 
#include <vector> 
using namespace std; 

namespace ProcessCheck 
{ 
extern "C" { __declspec(dllexport) string GetRunningProcessFromHierarchy(char* argStrRoot); } 
} 

而在C#代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Runtime.InteropServices; 

namespace ProcCheckTest 
{ 
class Program 
{ 

    [DllImport("C:\\Users\\himanshu\\Documents\\Visual Studio 2012\\Projects\\ProcessCheck\\Release\\ProcessCheckerDll.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern string GetRunningProcessFromHierarchy([MarshalAs(UnmanagedType.LPStr)] string strRoot); 

    static void Main(string[] args) 
    { 
     string strRoot = "C:\\test\\today_16.6"; 
     string returnValue = GetRunningProcessFromHierarchy(strRoot); 
    } 
} 
} 

,我傳遞的字符串是「C :\ test \ today_16.6「但是當我在dll代碼中打印相同的內容時,它會打印奇怪的字符。 這裏有什麼問題?

+3

請不要發佈您的整個代碼時,問題顯示在小片段 - http://stackoverflow.com/help/mcve。 – 2014-09-02 07:08:18

+0

它可能是文化設置,但我的猜測是你正在使用錯誤的變量類型來抵消字符串的字節。至於你需要什麼,我不記得在分鐘 – Sayse 2014-09-02 07:08:21

+0

請確保,你不會混淆unicode與ANSI。爲DllImport設置適當的屬性參數。 – Spook 2014-09-02 07:16:02

回答

2

的主要問題似乎是在這裏:

printf_s("strRoot = %s",strRoot); 

的問題是,strRootstd::string類型,但格式字符串需要char*。將其更改爲:

printf_s("strRoot = %s",strRoot.c_str()); 

或直接使用argStrRoot

您的其他問題是函數的返回值。目前您將返回std::string。你不能用p/invoke編組。您需要返回char*。更重要的是,編組人員會將其收到的指針作爲返回值調用CoTaskMemFree。所以你需要分配你回來的char*CoTaskMemAlloc

相關問題