首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么c#无法从非托管dll获取正确的参数值

C#是一种面向对象的编程语言,它在与非托管代码(如C++)进行交互时,可能会遇到从非托管DLL获取正确参数值的问题。以下是对这个问题的完善且全面的答案:

在C#中,无法直接从非托管DLL获取正确的参数值的原因主要有以下几点:

  1. 数据类型不匹配:非托管DLL中的函数可能使用了与C#不同的数据类型,例如C++中的指针、结构体等。在调用非托管DLL函数时,需要进行数据类型的转换和适配,否则无法正确获取参数值。
  2. 内存管理问题:非托管DLL中的函数可能使用了自己的内存管理方式,而C#使用的是垃圾回收机制。在调用非托管DLL函数时,需要确保内存的正确分配和释放,否则可能导致参数值获取错误。
  3. 调用约定不匹配:非托管DLL中的函数可能使用了与C#不同的调用约定(Calling Convention),例如stdcall、cdecl等。在调用非托管DLL函数时,需要使用正确的调用约定,否则可能导致参数值获取错误。

为了解决从非托管DLL获取正确参数值的问题,可以采取以下方法:

  1. 使用平台调用(Platform Invocation Services,P/Invoke):C#提供了P/Invoke机制,可以通过声明DLLImport特性来引入非托管DLL中的函数,并使用Marshal类进行数据类型转换和内存管理。可以参考微软官方文档中的P/Invoke教程(https://docs.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke)。
  2. 使用COM互操作性(COM Interop):如果非托管DLL是基于COM(Component Object Model)的,可以使用C#的COM互操作性功能进行交互。可以使用Visual Studio自动生成的互操作性代码,或者手动编写互操作性代码。可以参考微软官方文档中的COM互操作性教程(https://docs.microsoft.com/en-us/dotnet/standard/native-interop/com-interop)。
  3. 使用托管C++(Managed C++):如果非托管DLL是使用C++编写的,可以考虑将其转换为托管C++,然后再与C#进行交互。托管C++可以直接调用非托管代码,并提供更好的类型安全性和内存管理。可以参考微软官方文档中的托管C++教程(https://docs.microsoft.com/en-us/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp)。

总结起来,要从非托管DLL获取正确的参数值,需要进行数据类型转换、内存管理、调用约定匹配等操作。通过使用P/Invoke、COM互操作性或托管C++等方法,可以实现C#与非托管DLL的交互,并正确获取参数值。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

.NETC# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法

句柄(可在 dll 入口函数中获取);而我们是托管代码 dwThreadId 是线程 Id,传入 0 则为全局所有线程,否则传入特定线程 Id 需要注意坑 模块句柄传什么?...本文一开始被注释掉代码中,我使用 Marshal 直接托管程序集中获取了模块句柄。 这里需要说明,托管程序集不能注入到其他进程,因此也不可以挂接钩子。...通过调试也能发现这两个入口模块是相同: 至于为什么可以用 user32.dll。...所以更推荐使用前一小节中提供 LoadLibrary 函数来获取模块句柄,而不是获取当前托管模块句柄。...办法总还是有的: 可以考虑做托管 dll,专门用来挂接; 可以考虑使用 SetWinEventHook,这个是不用注入到目标进程; 可以考虑使用 System.Windows.Automation

1.2K20

C#中DllImport用法汇总

大家在实际工作学习C#时候,可能会问:为什么我们要为一些已经存在功能(比如Windows中一些功能,C++中已经编写好一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在功能呢...其功能是提供托管DLL导出函数进行调用所必需信息。DllImport属性应用于方法,要求最少要提供包含入口点dll名称。...这个问题最常出现在使用第三方托管DLL组件时候,我也同样是这时出问题,Asp.Net Team官方解决方案如下: 首先需要确认你引用了哪些组件,那些是托管,哪些是非托管.托管很好办,直接被使用需要引用...实际上,你拷贝到bin没有任何帮助,因为CLR会把文件拷贝到一个临时目录下,然后在那运行web,而CLR只会拷贝托管文件,这就是为什么我们明明把托管dll放在了bin下却依然提示不能加载模块了。...我们托管定义开始: typedef struct _SYSTEM_POWER_STATUS { BYTE  ACLineStatus; BYTE  BatteryFlag

2K10
  • 模拟隐蔽操作 - 动态调用(避免 PInvoke 和 API 挂钩)

    使用它,我们展示了如何内存或磁盘动态调用托管代码,同时避免 API 挂钩和可疑导入。...此外,此 API 让您可以轻松地在 C#内存中调用托管代码(传递参数并接收输出),而无需执行一些像自注入 shellcode 这样变通方法。 我们通过Delegates魔力实现了这一点。....如果将此与通常在 C#内存中调用托管代码方式(通过自注入 shellcode)进行比较,这会容易得多! 定义委托工作方式类似。您可以定义一个类似于定义变量委托。...DInvoke 库为每个托管函数提供了一个托管包装函数。包装器通过确保正确传递参数并返回正确类型对象来帮助用户。 值得注意是:PInvoke 比 DInvoke 对数据类型更宽容。...您必须以完全正确方式编组数据,确保您传入数据结构在内存中格式和布局与托管代码所期望相同。您还必须指定正确调用约定。这很烦人。

    2.1K00

    net开发平台regasm注册,gacutil 工具

    (1).regasm.exe文件是什么 首先regasm.exe工具是用来注册net平台这种托管语言编写dll类库,包括com扩展。为什么不是regsvr32 呢?...因为net平台生成并不是真正二进制文件,无法使用regsvr32 进行注册。... /i D:\wwwroot\c#\Wpc\Wpc\bin\Debug\Wpc.dll 全局注册需要两步,最后一步操作将你dll文件放到全局程序集缓存目录C:\Windows\Microsoft.NET...gacutil.exe文件必须安装Visual Studio ide并且使用ide提供命令行工具使用 (5).全局注册后想换为全局注册需要先卸载全局,卸载命令 C:\Windows\Microsoft.NET...(6).低版本regasm不能注册高net版本dll (7).一般推荐全局注册,只要不删除dll即可,毕竟gacutil文件官方不提供

    47600

    通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?

    那么在C#角度,那些脱离了.NET提供诸如垃圾回收器这样环境管制,就是对应 托管了。 托管异常 我们编写程序有的模块是由托管代码编写,有的模块则调用了托管代码。...,当你打上这行命令并按回车后,必须满足几个条件,1.是.cs后缀c#格式文件,2.是 代码语法等检测分析必须正确,3.是 使用类库必须有出处(引用dll),当然 因为我是编译为控制台程序,所以还必须得有个静态...托管堆模型 而引用类型相比值类型就有点特殊,newobj创建一个引用类型,因其类型内引用对象可以指向任何类型,故而无法准确得知其固定大小,所以像对于引用类型这种无法预知容易产生内存碎片动态内存,我们把它放到托管堆中存储...托管世界内存不需要我们打理,我们无法代码中得知具体托管对象大小,你如果想追求对内存最细微控制,显然C#并不适合你,不过类似于有关内存把控这部分功能模块,我们可以通过托管语言来编写,然后通过...,仅仅是.NET平台上,因此它只限制于托管代码,我们可以直接调用托管代码或进程通信间接调用托管代码等多个手段来突破对托管代码 操作资源限制。

    2.7K63

    通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?

    那么在C#角度,那些脱离了.NET提供诸如垃圾回收器这样环境管制,就是对应 托管了。...托管异常 我们编写程序有的模块是由托管代码编写,有的模块则调用了托管代码。...,当你打上这行命令并按回车后,必须满足几个条件,1.是.cs后缀c#格式文件,2.是 代码语法等检测分析必须正确,3.是 使用类库必须有出处(引用dll),当然 因为我是编译为控制台程序,所以还必须得有个静态...托管世界内存不需要我们打理,我们无法代码中得知具体托管对象大小,你如果想追求对内存最细微控制,显然C#并不适合你,不过类似于有关内存把控这部分功能模块,我们可以通过托管语言来编写,然后通过...,仅仅是.NET平台上,因此它只限制于托管代码,我们可以直接调用托管代码或进程通信间接调用托管代码等多个手段来突破对托管代码 操作资源限制。

    4.5K30

    托管C++、C++CLI、CLR

    不过,通过使用特殊关键字,C# 数据可以被标记为托管数据。Visual C++数据在默认情况下是非托管数据,即使在使用 /CLR 开关时也不是托管。   ...另外,一个托管类也完全可以成为 .NET 框架成员,由此可以带来好处是,它可以与其他语言编写正确地进行相互操作,如托管C++类可以Visual Basic类继承等。...2、为什么使用托管C++   除了可以充分发挥.NET框架新特性外,使用托管C++还有下列好处:   (1) 由于在同一个应用程序中,甚至是同一个文件中,我们可以同时使用托管C++和传统托管C+...(2) 使用托管可以任何一个.NET框架兼容语言中调用一个C++组件,也可调用托管DLL、其它库以及类等。   (3) 可以直接托管代码中访问.NET框架。   ...一个__gc类不能从一个托管类中继承,且不能包含它派生托管类。但一个__gc类最多可以从一个托管类中继承。   B. 一个__gc类不能定义成一个友元类或包含一个友元成员函数。

    2.9K40

    C++ .NET编程:托管C++概述

    默认情况下,C#、Visual Basic 和 JScript.NET 数据是托管数据。不过,通过使用特殊关键字,C# 数据可以被标记为托管数据。...另外,一个托管类也完全可以成为 .NET 框架成员,由此可以带来好处是,它可以与其他语言编写正确地进行相互操作,如托管C++类可以Visual Basic类继承等。...(3) 托管C++空项目:用来创建一个空托管项目,该项目只含有支持托管扩展正确编译和链接开关选项。使用它能将一个已有的C++源文件进入到一个托管环境中。    ...一个__gc类不能从一个托管类中继承,且不能包含它派生托管类。但一个__gc类最多可以从一个托管类中继承。    B. 一个__gc类不能定义成一个友元类或包含一个友元成员函数。...代码中可以看出设置和获取属性成员函数名称中分别使用了set_和get_,这样编译器会自动生成一个伪成员变量Size,这个变量名是set_和get_成员函数后面的名称。

    1.5K20

    红队技巧之F#利用

    援引微软官方解释: F # 是一种函数编程语言,可方便编写正确且可维护代码。F # 编程主要涉及如何定义自动推断和通用化类型和函数。...至于为什么要学习F#,其实也是跟C#道理是一样,在某些特殊情况下,我们可以利用F#来达到我们目的,原常景如下: This customer really locked down their environment...但这并不意味着我们便无法在内存中运行我们F#程序,我们可以使用托管代码方法来运行任意我们F#程序。...比较好demo就是: https://github.com/etormadiv/HostingCLR 也就是用托管来加载CLR实现内存加载。...实现过程如下: 1.将CLR加载到进程中:调用CLRCreateInstance函数以获取ICLRMetaHost或ICLRMetaHostPolicy接口,调用ICLRMetaHost方法来获取有效

    1.5K30

    2019-3-7-手把手教你PInvoke

    ---- 这个时候你就会接触到一些美妙dll,比如user32.dll,kernal32.dll 当然这些是非托管代码,我们在.net中无法直接使用,所以我们会需要使用PInvoke进行调用 于是你会使用...DllImport特性标记一个方法,引入托管函数 比如 我们希望弹出一个消息框,就会使用下面这个函数,添加DllImport特性,表明哪个dll引入方法 public class Win32 {...; } 接着我们Syntax中找到函数签名 ? 这里比较麻烦是4个参数需要转换为对应托管类型,有时候还会涉及一些结构体和指针。 这里我们先看一下Parameters ?...最后一个是UINT,我们直接在c#中有对应uint 这么一看是不是就更加能够理解了呢。...实操 再来一个简单例子,我们期望获取HID设备接口GUID 方法给到你们,是HidD_GetHidGuid 先看requirements.txt,发现DLL 是Hid.dll ?

    89230

    使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流

    因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵 如果你跟随这篇文章实现了播放器,那你会得到一个高效率,低cpu占用(单路720p视频解码播放占用1%左右cpu),且代码和引用精简(无其他托管托管...安装好dxsdk后我们得到c#托管引用dll   第二步是修改ffmpeg源码并编译,我们要修改源码只有一个文件十余行,而且是增量修改。...将msys自带link重命名避免冲突 打开msys,查看变量是否正确 ? 检查变量正确性 编译ffmpeg ....进行可能异常处理(实际上还是推倒重来)   番外篇:C#对DiretX调用封装 上文中我们使用DirectX方式看起来即COM组件,又C-DLLP/Invoke,难道DirectX真有托管代码...答案是否定C#dll当然也是调用系统d3d9.dll

    3.3K11

    ILRuntime热更新

    项目/教程地址:传送门 IL热更优点: 1、无缝访问C#工程现成代码,无需额外抽象脚本API 2、直接使用VS2015进行开发,ILRuntime解译引擎支持.Net 4.6编译DLL 3、执行效率是...除了默认 AppDomain,正在使用托管COM接口方法 或托管类型方法宿主还可要求CLR创建额外 AppDomain。AppDomain是为了提供隔离而设计 。...=cc7b13ffcd2ddd51”引用 解决方案:我默认工程文件框架为4.6.0,更改到更高版本再进行编译即可生成dll 顺利生成dll文件 安装调试器 报错:安装无法将此扩展安装到所有选定产品...大规模数值计算:如果在热更内需要进行大规模数值计算,则可以开启ILRuntime在2.0版中加入寄存器模式来进行优化 避免使用foreach:尽量避免使用foreach,会不可避免地产生GC。...使用MonoBehaviour->不建议) 09.Reflection(主工程反射DLL类型) 热更DLL中使用反射跟原生C#没有区别 Demo主要介绍主工程反射热更DLL类型 void OnHotFixLoaded

    2.4K30

    程序员级别鉴定书(.NET面试问答集锦)

    这里问是强名称概念。Assembly.Load("foo.dll")加载程序集方法是否正确? 强签名程序集与强签名程序集有何不同? DateTime 可以为null吗? 什么是 JIT?...因为同样一个名称文件可能有不同版本和区域,此时单独靠文件名称,可能会造成不能确定程序集正确性。 Assembly.Load("foo.dll")加载程序集方法是否正确?...Finalize只释放托管资源; Dispose释放托管托管资源 Finalize和Dispose共享相同资源释放策略,因此他们之间也是没有冲突。 Using()模式有用吗?...为什么用,或为什么不用它? Debug和Release编译产出物不一样,Release下无调试信息,如Assert无法使用。对程序运行速度而言,无明显区别。...先调用了this(),即无构造函数,再调用了自身构造函数。 因为未对a参数进行处理,故无用。 This是什么?可以在静态方法中调用 this 吗?

    1.8K70

    一文看懂 .NET 异常处理机制、原则以及最佳实践

    StackOverflow 表示栈溢出,这通常说明实现代码时候写了不正确显式或隐式递归 OutOfMemoryException 表示托管堆中已无法分出期望内存空间,或程序已经没有更多内存可用了...AccessViolationException 这说明使用托管内存时发生了错误 BadImageFormatException 这说明了加载 dll 并不是期望中托管 dll TypeLoadException...表示托管堆中已无法分出期望内存空间,或程序已经没有更多内存可用了 AccessViolationException 这说明使用托管内存时发生了错误 BadImageFormatException...这说明了加载 dll 并不是期望中托管 dll TypeLoadException 表示类型初始化时候发生了错误 环境错误: IOException 下各种子类 Win32Exception 下各种子类...AccessViolationException 当出现此异常时,说明托管内存中发生了错误。如果要解决问题,需要从托管代码中着手调查。 这个异常是访问了不允许内存时引发

    78441

    .NET Core多线程 (1) Thread与Task

    时间和空间角度理解线程开销 (1)多线程优点 提高响应能力 main thread:更新UI东西 work thread:耗时操作 提高程序性能 1个力工:1个月...10个力工:3天~5天 (2)线程有哪些开销 空间上开销 数据结构上开销 C#:Thread CLR:Thread(C++写) OS:Thread 线程栈开销...dllmain 托管dll 上面上游 dllmain thread 在start时 会通知这些 托管dll thread 在exit时 也会通知这些托管dll(资源清理)...Task:基于ThreadPool上层封装 线程池使用及分析其设计思想 (1)为什么要使用线程池?...Task及如何运用其编排能力 (1)Task设计思想 为什么会出现Task: 获取Thread返回值比较麻烦 多个Thread串行实现比较麻烦 Thread父子关系实现比较麻烦(比如

    49930

    C#面试题

    Attribute特性就是关联了一个目标对象一段配置信息,本质上是一个类,其为目标元素提供关联附加信息,这段附加信息存储在dll元数据,它本身没什么意义。运行期以反射方式来获取附加信息。...using() 只是一种语法形式,其本质还是try…finally结构,可以保证Dispose始终会被执行。 8. 解释一下C#析构函数?为什么有些编程建议里不推荐使用析构函数呢?...finalize不能保证立即释放托管资源,Finalizer被执行时间是在对象不再被引用后某个不确定时间;而dispose一调用便释放托管资源。...Dispose一调用便释放托管资源; Finalize不能保证立即释放托管资源,Finalizer被执行时间是在对象不再被引用后某个不确定时间; 11. .NET中托管堆中是否可能出现内存泄露现象...比如: 不正确使用静态字段,导致大量数据无法被GC释放; 没有正确执行Dispose(),托管资源没有得到释放; 不正确使用终结器Finalize(),导致无法正常释放资源; 其他不正确引用,导致大量托管对象无法

    77520

    苏州同程旅游学长给我全面的面试知识库

    我们已经介绍了50多种基本知识,以推进常见C#面试问题和答案 2、什么是C#C#是一种面向对象,类型安全托管语言,由.Net框架编译以生成Microsoft中间语言。...不,不能执行多个类似类型捕获块。一旦执行了正确捕获代码,控制就会转移到finally块,然后执行finally块之后代码。 5、 public,static和void之间有什么区别?...我们可以轻松地将自定义控件添加到多个应用程序(如果共享Dll)。因此,如果它们是私有的,那么我们可以将其复制到dll到Web应用程序bin目录中,然后添加引用并可以使用它们。...他们有自己设计和代码背后。用户控件文件扩展名为ascx。 17、 C#密封类是什么? 当我们想限制继承类时,我们创建密封类。密封修饰符,用于防止类派生。...当我们希望对象与它们一起释放任何托管资源时,将调用Dispose()。另一方面,Finalize()用于相同目的,但不能保证对象垃圾回收。 28、什么是循环引用?

    3K20

    C# DllImport用法

    大家在实际工作学习C#时候,可能会问:为什么我们要为一些已经存在功能(比如Windows中一些功能,C++中已经编写好一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在功能呢...答案是肯定,大家可以通过C#DllImport直接调用这些功能。...DllImportAttribute 属性提供对托管 DLL 导出函数进行调用所必需信息。作为最低要求,必须提供包含入口点 DLL 名称。...我们托管定义开始: typedef struct _SYSTEM_POWER_STATUS { BYTE  ACLineStatus; BYTE  BatteryFlag; BYTE ...,因此我们使用 byte 作为该 enum 基本类型 示例四:处理字符串 二 C# 中调用C++代码 int 类型 [DllImport(“MyDLL.dll”)] //返回个int 类型

    98610

    【C++静态私有字段】+【C# .cctor】+【C++ if(条件断点)】

    前言 最近进行托管托管频繁操作,遇到了一些坑记录下。分别为标题标注:C++静态私有字段访问,C#全局静态构造函数.cctor,以及C++ if(延伸条件断点)。...这里.cctor函数是这个模块静态默认构造函数。它运行在托管Main入口之前,运行在System.Private.Corelib.dll之后。如果你想要在托管Main函数之前做一些事情,它是首选。...C#代码里面不能够编辑它,可以通过Mono.Cecil对托管DLL添加这个函数。..."); } 这里有一个坑需要注意,比如本例中对ConsoleApp5.dll程序集进行了..cctor函数添加,形成了新modified.dll托管DLL,这里需要注意,这两个托管DLL...保留你需要运行托管DLL,以及xxx.runtimeconfig.json运行时文件即可。其它文件全部删掉,即可正常运行。在.NET8里面,这是一个巨坑,查找了很久才发现。

    7710
    领券