我的 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 -> Options -> Projects and Solutions -> Web Projects -> 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?