必发bf88 2

编译错误
说明:
在编译向该请求提供服务所需资源的过程中出现错误。请检查下列特定错误详细信息并适当地修改源代码。

今天在编译一个Windows
Form程序时.突然发现一个问题.在本机开发环境[X64位]能够很好调用.等打包安装后放到32位机器是突然发现提示一个错误如下:

编译器错误信息: CS1595:
已在多处定义“BigTeam.Security.Admin.Controls.UserLists_ascx”;使用“c:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary
ASP.NET
Files\bbsx\9bf466b2\c521e5e7\assembly\dl2\fe062d3b\00900c07_9357c501\BigTeam.Security.DLL”中的定义

必发bf88 1

源错误:

具体异常信息如下:

行 27:    
行 28:    
[System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()]
行 29:     public class UserLists_ascx : UserLists{
行 30:        
行 31:         private static bool __initialized = false;

有关调用实时(JIT)调试而不是此对话框的详细信息,
请参见此消息的结尾。

************** 异常文本 **************
System.DllNotFoundException: 无法加载 DLL“Win32Project1.dll”:
找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。
   在 AndroidSkinTool.UnsafeNativeMethods.getKey()
   在 AndroidSkinTool.Forms.FormMain.btnRefresh_Click(Object sender,
EventArgs e) 位置
d:\C#Workspace\SkinToolCode_V6.1\Forms\FormMain.cs:行号 2708
   在 System.Windows.Forms.Control.OnClick(EventArgs e)
   在 System.Windows.Forms.Button.OnClick(EventArgs e)
   在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks)
   在 System.Windows.Forms.Control.WndProc(Message& m)
   在 System.Windows.Forms.ButtonBase.WndProc(Message& m)
   在 System.Windows.Forms.Button.WndProc(Message& m)
   在
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&
m)
   在
System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)

 

今天遇到的一个郁闷错误。可能是因为我改了名字空间!但我并没有定义多个程序集呀!这是为什么呢?
而我所看到确实有多个程序集!不知道是我什么地方搞错了!

  在编译选项里,我多加了一个程序集。原来的是BigTeam.Platform,而后来我想改为BigTeam.Security,我这样做了。编译后得到两个文件,而里面的内容基本上是一样。这时候加载页面的时候就出问题了,同样的名字空间里有同样的类,自然在加载的时候就会出现这样的问题了!删除其中一个就可以了(但要注意:一般情况下,你就算是有两个DLL文件,里面的内容一样也没关系,但就不能有两次编译后得到的两个内容一样的DLL文件,否则就会有上面的错误出现)!
  特别注意:在更改一次编译选项然后再更改回来且两次都有编译的时候,就要注意了,上面的错误一定会出现,而且可能使两次的版本不一样,所以记得删除里面的任何一个(这时候两个是冲突的,所以删除任何一个都可以使程序运行正常)。但要注意,你所删除的一定要是与编译选项不同的那一个,否则再编译的时候就会又得到一个错误了!

其实在应用程序中实现一个很简单的功能.
在。net程序中C#通过Dllimport方式来调用C++ DLL库.传递一个字符串而已.
而出现System.DllNotFoundException异常的原因主要存在如下几个问题:

首先需要确定调用C++
DLL是否正确导出.因为可以再开发环境正常运行.可见DLL已经成功导出.成功导入后.需要确认在.NET环境导入的方式是否正确.在导入前需要引用如下库:

   1:  using System.Runtime.InteropServices;

导出方法:

   1:  [DllImport("WindowsEntity1.dll",EntryPoint= "TA_Init3",CallingConvention = CallingConvention.StdCall)]

   2:  public static extern int TA_Init3(string IP, Int16 port,ushort SysCode, ushort TerminalNo);

如果导出方式也正确.还提示如上问题的话.这个时候我们则需要进一步分析调用C++DLL
有没有引用其他库或存在其他依赖.采用dependency
worker工具分析当前windowsEntity1 DLL引用依赖项 如下:

必发bf88 2

you see.可以看到当前win32Project1.DLL主要有两个依赖项
MSVCR110.DLL和KEREML32.DLL.
而MSVCR110在当前操作系统确实才导致了当前开始运行提示DLLNotFoundException异常信息.我们可以再项目Realse目录下添加改DLL或是把改DLL拷贝到System
32下保证系统环境中可见.
发现DLLNotFoundEXception异常则消失了.应用程序正常运行.这里需要注意一点.
在通过.NET 调用C++ DLL 时. 应用会首先在System
32系统环境查找是否具有MSVCR110.DLL依赖项.如果没有则继续在安装目录下寻找.如果两边都没有找到则会爆出DllNotFoundException异常信息.
因此简单方式有两种. 第一可以通过代码在调用注册该DLL信息.
另外可以直接把依赖的MSVCR110.DLL拷贝到realse目录下即可.

另外除了以上情况.还有一种特殊情况是.看运行环境是否安装了VC Runtime
library. 类似在VS2012 环境下默认是安装的.
有些机器没有安装或是采用VC6.0编译的DLL.所以为了免去打包安装的麻烦.可以通过安装相应VC运行时库或者直接把几个相应版本运行时的库文件直接放到可执行程序里面进行发布,从而省却安装过程.
这是一个比较直接的解决方案.

为了保证能够兼容32和64
两个平台.我在调用.NET程序设置编译选项为AnyCpu方式.却发现。net抛出如下异常信息:

Unhandled Exception:

System.BadImageFormatException: Could not load file or assembly
‘SourceCode.HostClientAPI, Version=4.0.0.0, Culture=neutral,
PublicKeyToken
=16a2c5aaaa1b130d’ or one of its dependencies. An attempt was made to
load a program with an incorrect format.
File name: ‘SourceCode.HostClientAPI, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=16a2c5aaaa1b130d’

也就是你现在看到的System.BadImageFormatException异常.针对这个问题.官方MSDN上说的很详细.Visual
Studio的编译选项 build中的platform存在有3个选项X64、Any
CPU和x86。X86表示只能在32位环境下运行,X64表示只能在64位环境下运行,Any
CPU表示你的程序集可以根据环境变化适应32位还是64位,但是如果你的程序集依赖于一个x86选项编译的程序集类似调用一个win32
C++ DLL,哪么你的程序集只能选择X86进行编译,而不能选择Any
CPU编译,如果使用Any
CPU编译.则这个时候会抛出System.BadImageFormatException异常信息.

而真正的原因是.如果你采用Anycpu方式进行编译.那么在64位机器默认的运行就是64位的,通常这情况是assembly需要调用一个32的COM库,只要用x86编译,那么程序就是以32位的程序,依靠wow64来运行的,就可以在64位系统上运行。所以,如果assembly需要使用win32库的话。正确的做法是把编译的选项设置X86来编译.即可.唯一点需求.保证调用的C++
DLL编译版本和调用版本一致才是原则所在.这样一来在32和64位则不会爆出如上异常问题.

在官方文档说了两个意外情况. 也是值得参考的.

如果您的应用程序使用了 32 位组件,请确保该应用程序始终采用 32
位应用程序的运行方式。

如果应用程序项目的“平台目标”属性设置为 AnyCPU,则编译后的应用程序在 64
位或 32 位模式中均可运行。如果采用 64 位应用程序运行方式,则实时 (JIT)
编译器便会生成 64 位本机代码。如果应用程序依赖于某个 32
位托管组件或非托管组件,则在 64
位模式中无法加载该组件。若要纠正此问题,请将项目的“平台目标”属性设置为
x86,然后重新编译。

确保未使用利用其他 .NET Framework 版本创建的组件。

如果使用 .NET Framework 1.0 或 .NET Framework 1.1
开发的应用程序或组件尝试加载使用 .NET Framework 2.0 SP1
或更高版本开发的程序集,或者使用 .NET Framework 2.0 SP1 或 .NET
Framework 3.5 开发的应用程序尝试加载使用 .NET Framework 4
开发的程序集,便会引发此异常。 BadImageFormatException
异常可能会报告作为编译时错误,或在运行时可能会引发该异常。有关示例,请参见
BadImageFormatException 类

参考资料:

关于疑难异常解答:system.BadImageFormatExcetpio.

admin

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注