我的 C++ 程序集是如何从 C# 控制台应用程序而不是 ASP.NET 中看到的?

Posted

技术标签:

【中文标题】我的 C++ 程序集是如何从 C# 控制台应用程序而不是 ASP.NET 中看到的?【英文标题】:How comes my C++ assembly is seen from a C# console application but not an ASP.NET one? 【发布时间】:2018-01-18 20:20:18 【问题描述】:

我写了一个 C++ dll。它有一个函数,返回双精度 1.0。

我尝试在 C# 控制台应用程序中使用它:

namespace MyNameSpace


    class Program
        
        [DllImport(@"C:\path\to\my\dll\myDll.dll")]
        static extern double SendOne();

        static void Main(string[] args)
        
            double i = SendOne();
            Console.WriteLine(i);
        
    

这行得通。

然后我尝试在一个 ASP.NET 应用程序中使用它,用一个空的 MVC 应用程序创建,然后添加一个控制器和一个视图:

控制器/HomeController.cs:


    public class HomeController : Controller
    
        [DllImport(@"C:\path\to\my\dll\myDll.dll")]
        static extern double SendOne();

        // GET: Home
        public ActionResult Index()
        
            double i = SendOne();
            ViewBag["result"] = i;
            return View();
        
    

Views/Home/Index.cshtml

@
    Layout = null;


<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div> 
        This is some text and the result : @ ViewBag["result"]
    </div>
</body>
</html>

这不起作用,并返回一个 BadImageFormatException。

在所有三个项目中,我手动将平台配置为 Debug / x64(来自默认的 Debug / AnyCPU)。

这是堆栈跟踪的底部:(第一行手动翻译自法语)

[BadImageFormatException: Impossible charge the file or assembly '[Name of the ASP.NET Project]' or one of its dependencies. Attempt to load a program of incorrect format.]
System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +0
System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +36
System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +152
System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection) +77
System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +21
System.Reflection.Assembly.Load(String assemblyString) +28    System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +38

堆栈跟踪顶部:HttpException 0x80004005。

ASP.NET 项目和 C# 控制台应用程序是同一个 Visual Studio 2017 解决方案中的两个项目,它们不相互引用并且我单独启动。

我不明白 ASP.NET 项目和 C# 控制台应用程序之间存在的差异可能导致本机 C++ Dll 加载在 C# 控制台应用程序中工作并在 ASP.NET 项目中失败。

有人知道这个问题或对我可以尝试什么有建议吗?谢谢。

【问题讨论】:

【参考方案1】:

BadImageFormatException 在程序尝试加载位数不匹配的模块时引发。帽子是 64,但进程尝试加载 32 位模块,反之亦然。因此,似乎 ASP 进程是来自控制台应用程序的缓冲位。

【讨论】:

我很确定控制台应用程序是 64 位的,因为我可以成功地使用我认为只能在 64 位环境中运行的库中的 dll 函数。这意味着 ASP.NET 进程在某种程度上是 32 位的,尽管我使用 x64 编译项目。怎么会 ?我的 ASP.NET 项目创建的准确回溯是 ASP.NET Web 应用程序 (.NET Framework) > 添加控制器和视图 > 配置管理器 > 平台 > > x64 / 调试。勾选创建新的解决方案平台似乎并不重要。如果有帮助,我可以记录我的简约项目创建。【参考方案2】:

感谢@DavidHeffernan 的回答,我的研究让我想到了这个问题:Compile ASP.NET to 64 BIT

哪个有替代答案可以解决我的问题:无论 ASP.NET 编译为 32 位还是 64 位,IIS Express 的 调试器 以 32 位运行,这会发生冲突使用 64 位 C++ dll。

需要更改调试器的版本,这可以在Visual Studio -&gt; Options -&gt; Projects and Solutions -&gt; Web Projects -&gt; Use the 64 bits version of IIS Express for web sites and projects完成。

【讨论】:

这不是我给你的答案吗? @DavidHeffernan 我找不到“缓冲位数”的含义,所以我认为它意味着不同的位数,但我从一开始就将 ASP.NET 版本编译为 64 位,如我的回答。在这里我要说明的是,即使我确实将 ASP.NET 编译为 64 位,调试器默认为 32 位,即使在 64 位编译模式下也是如此!以及如何解决它。 您似乎对问题的答案和问题的解决方案感到困惑。 我的问题是“有什么问题”,所以说它与位数相关并不像说它来自调试器的位数那样精确。您确实通过告诉我问题的性质引导我找到了解决方案,但我认为我会为未来的用户提供更完整的答案。 没关系。我认为您不了解该网站的工作原理。您的答案是指问题中不存在的各种细节。具体到你。我想我回答了所提出的问题,很抱歉您不同意。

以上是关于我的 C++ 程序集是如何从 C# 控制台应用程序而不是 ASP.NET 中看到的?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 .exe 从 C++ 项目复制到 C# 项目的输出目录?

从本机 C++ 调用 C#,而不使用 /clr 或 COM?

如何从 C++ 后台任务(Windows 通用应用程序)调用 C# 函数?

如何使用 C++ 静态库编译 C# 应用程序?

从 C++ 库方法返回的“char*”获取 C# 字符串?

使用命名管道将图像从 C++ 发送到 C# 应用程序