2014-10-01 71 views
4

我的目標是隻有一個可執行文件。將託管程序合併到非託管C++可執行文件

  • 是否有可能將託管的.exe文件合併到非託管的.exe文件中?

有很多關於各地做事的其他方式(合併非託管代碼到託管項目),但我一直沒能找到有關去另一個方向的任何信息。

背景:

它是一個系統的要求/兼容性檢查。
我已經使用.NET 2中的C#編寫了它的大部分代碼。
但是,只有在確定系統至少安裝了.NET 2時,纔會運行此部分。
這就是"DotNetVersionIdentifier.exe"發揮作用。
無論.NET框架是否安裝,它都會運行unmanaged code。如果安裝了.NET 2.0或更高版本,我已經修改了代碼以運行我的C#程序,或者報告自定義消息,而不是顯示已安裝的.NET版本的對話框。

  • 我想收拾C++可執行文件裏面的C#程序,所以我只需要分發單個.exe

我使用ILMerge嘗試過,但因爲我的非託管代碼沒有按」牛逼編譯成中間語言,它崩潰...

ILMerge doesn't accept unmanaged code...

我可以在我的C#項目添加到C++的解決方案,但它仍然編譯成兩個獨立的可執行文件。

這種方法:How to Append Data to the End of an .EXE File聽起來像一個迷人,但過時的黑客攻擊。

這個想法好像可能有效:How to embed an exe inside another exe as a resource and then launch it我現在正在研究它。

+0

所以你在找什麼樣的幫助,對SO?事實上,您可以將文件添加爲託管或本地應用程序的資源,將其保存並以您建議的鏈接運行。 – 2014-10-01 14:29:17

+0

我還沒有得到它的工作,所以我只是把我的探測器,看看是否可能有另一種/更好的方式。 – 2014-10-01 14:30:49

+0

對我而言仍然不清楚......資源是直接的方式來做你要求的標題(如果它對你的情況是好的 - 你的電話)......鏈接的文章看起來很合理......「我應該手動檢測.Net 2.0安裝「將作爲意見爲主的話題。 – 2014-10-01 14:40:56

回答

2

我設法通過使用Resources,as outlined here來實現我的目標。

以下是我的工作原理。 (我是新的C++,所以讓我知道,如果你看到任何愚蠢)

  • 編譯託管代碼爲單個文件
  • 重命名託管代碼可執行文件.TXT
  • 創建一個新的Visual C++ Win32控制檯應用程序
  • 新增項目 - 資源文件(.RC)
  • 打開的資源文件,添加資源,選擇進口,輸入 「TEXT」 作爲類型
  • 修改「DWORD大小」相匹配的管理.txt文件

其餘的可以用代碼轉儲解釋的大小。
希望這會幫助別人(像我這樣的C++新手......)

#include "stdafx.h" 
#include "resource.h" 
#include "windows.h" 
#include "iostream" 
#include <string> 
#include <sstream> 

using namespace std; 

namespace std 
{ 
    HRSRC hrsrc = NULL; 
    HGLOBAL hGlbl = NULL; 
    BYTE *pExeResource = NULL; 
    HANDLE hFile = INVALID_HANDLE_VALUE; 
    DWORD size = 8192; //hardcoding the size of the exe resource (in bytes) 
    HINSTANCE g_Handle = NULL; 
    HINSTANCE hInstance = NULL; // Passing NULL uses the instance that started the process(CSMerged.exe). 

    template <typename T> 
    string NumberToString(T pNumber) 
    { 
     ostringstream oOStrStream; 
     oOStrStream << pNumber; 
     return oOStrStream.str(); 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    hrsrc = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_TEXT1), _T("TEXT")); 
    if (hrsrc == NULL) 
    { 
     cout << "hrsc is null! \n"; 
     cin.get(); // leave the console open. 
     return FALSE; 
    } 

    hGlbl = LoadResource(hInstance, hrsrc); 
    if (hGlbl == NULL) 
    { 
     cout << "hGlbl is null! \n"; 
     cin.get(); // leave the console open. 
     return FALSE; 
    } 

    pExeResource = (BYTE*)LockResource(hGlbl); 
    if (pExeResource == NULL) 
    { 
     cout << "pExeResource is null! \n"; 
     cin.get(); // leave the console open. 
     return FALSE; 
    } 

    hFile = CreateFile(L"ManagedCode.exe", GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

    if (hFile != INVALID_HANDLE_VALUE) 
    { 
     DWORD bytesWritten = 0; 
     WriteFile(hFile, pExeResource, size, &bytesWritten, NULL); 
     CloseHandle(hFile); 
    } 

    PROCESS_INFORMATION pi; 
    STARTUPINFO si; 
    ZeroMemory(&si, sizeof(STARTUPINFO)); 
    si.cb = sizeof(STARTUPINFO); 
    int ret = CreateProcess(L"ManagedCode.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 

    if (ret == 1) { return 0; } // the process started successfully, so I'm done here. 
    else 
    { 
     cout << "CreatePrecess returns " + NumberToString(ret) + ". \n"; 
     cin.get(); // leave the console open 
    } 

    return 0; 
} 

RESOURCE.H - 這是自動生成的,與修改Recource.rc一起時,我使用的進口VS2013的資源GUI。

//{{NO_DEPENDENCIES}} 
// Microsoft Visual C++ generated include file. 
// Used by Resource.rc 
// 
#define IDR_TEXT1      101 

// Next default values for new objects 
// 
#ifdef APSTUDIO_INVOKED 
#ifndef APSTUDIO_READONLY_SYMBOLS 
#define _APS_NEXT_RESOURCE_VALUE  102 
#define _APS_NEXT_COMMAND_VALUE   40001 
#define _APS_NEXT_CONTROL_VALUE   1001 
#define _APS_NEXT_SYMED_VALUE   101 
#endif 
#endif 

我應該在添加一些其他的事情,我不得不改變,以使在Windows XP上這個運行:

  • 確保平臺的目標是Win32的
  • 設置配置屬性>常規>平臺工具集「Visual Studio 2013 - Windows XP(x120_xp)」
  • 設置配置屬性> C/C++>代碼生成> Runt IME圖書館「多線程(/ MT)
相關問題