问题标签 [pinvoke]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
2014 浏览

c# - 如何从通过 FtpCommand 运行的 FTP 命令获取结果?

我已经包装了大部分 wininet,没有任何问题,但现在我被卡住了。我正在尝试从 wininet.dll p/invoke FtpCommand,但我运行的每个命令都返回“500 语法错误”。甚至像 dir 或 ls 这样的简单命令。如果我使用 ftp.exe 连接到同一台服务器,则命令可以正常工作并返回预期结果。

这是方法定义:

以及我调用它的代码:

其他一切正常,我可以下载文件、上传文件并使用 FtpFindFirstFile() 模拟 dir 命令,但我似乎无法使用上述方法发送命令。

编辑

我的 SendCommand 代码是 SendCommand("DIR") 或 SendCommand("LS")。在阅读了其中一个答案后(在我编辑时看不到谁),我将其更改为 SendCommand("LIST") 并成功返回。

但是,我的问题是如何读取结果,我用什么来读取从 LIST 命令返回的数据,以便以可读的格式输出?

我更新了 SendCommand 方法以显示我计划如何读取返回的数据,但对于 bytesRead,我总是得到 0。我也尝试在 FtpCommand 调用中传递 dataSocket 接收的句柄,但如果我这样做,应用程序只会退出而没有错误。

编辑 2

我正在使用 InternetReadFile 从调用 FtpCommand 时返回的数据套接字句柄读取数据。我正在使用的 InternetReadFile 的方法签名是这样的:

最终编辑

在 codeplex 上发布了这段代码

0 投票
1 回答
2036 浏览

c# - 从 .NET 打印 API 检索设备上下文

我正在开发一个 .NET 应用程序来控制 DataCard 桌面卡打印机,但我偶然发现了一个问题。为了执行磁条和芯片编码,我必须调用本机打印机 API dll 中的函数来启用打印机交互模式。

我设法创建了 P/Invoke 代码来调用这个本机函数。但问题是该方法将打印机设备上下文句柄作为参数,并且必须在调用 Gdi32 StartDoc 函数之前调用。

在 .NET 打印 API 中,我确实可以从 Graphics 对象访问 hDC。但据我所知,Graphics 对象仅在调用 StartDoc 函数后可用。

所以我的问题是,是否有人知道在调用 StartDoc 之前检索上下文的方法?

0 投票
4 回答
4803 浏览

vb.net - 如何在 vb.net 中更改表单形状

我曾经使用以下代码在 VB 6.0 中更改表单形状:

以同样的方式,我使用 VB.NET 代码如下:

但在后一种情况下,我收到一条错误消息 - “未找到类型 'Form1' 上的公共成员 'hWnd'。”

我所做的?

0 投票
3 回答
652 浏览

visual-c++ - 从 Visual C++ 2005 dll 启动 .exe

有谁知道代码或对如何使用 Visual C++ 2005 启动 .exe 有想法?

如果是 Windows Mobile,则 dll 所在的环境。执行此操作的 C#P/Invoke

c#代码启动.exe

我在 C++ 中需要它的原因是因为在运行自定义 cab 安装程序时,我被迫使用本机 dll 来执行前后 intit 检查等。

非常感谢您的想法。托尼

0 投票
3 回答
1861 浏览

c# - P/Invoke 函数调用问题

我正在开发一个需要使用 P/Invoke 与本机 C API 交互的系统。现在我(又一次)偶然发现了一个我似乎无法以任何方式解决的问题。原始函数旨在根据指定使用哪种结构的参数返回两种结构。

C 头文件定义结构和功能如下:

我试图像这样实现 P/Invoke 包装器:

调用“GetCardId”似乎工作正常。调用它后,我在 CARDIDTYPE 实例中得到了合理的数据。但是,当我调用“GetCardStatus”时,问题就开始了。应返回的结构类型由“级别”参数定义,值为 1 应导致在“pData”中返回 CARD_INFO_1 结构。

该文档包含以下 C 示例:

我等效的 C# 实现是这样的:

当我执行此 C# 代码时,该方法返回 false 并且 Marshal.GetLastWin32Error() 返回 -1073741737(这对我来说没有多大意义)。我看不出这个调用为什么会失败,而且绝对不是这个错误代码。所以我怀疑我的 P/Invoke 包装器有问题。

我知道使用“byte[]”作为 pData 的类型可能不正确,但根据一些谷歌搜索,“LPBYTE”转换为“[Out] byte[]”。我想这样做的正确方法是将 pData 作为 IntPtr,并使用 Marshal.PtrToStructure(...) 创建结构。我试过这个,但结果是一样的。这是此场景的代码:

编辑: 我忘了提到的一件事是,如果我没有指定 EntryPoint = "_GetCardStatus@28",由于某种原因,GetCardStatus 调用会失败并出现未知的入口点异常。我包装的任何其他功能都没有发生这种情况,所以这让我有点疑惑。

0 投票
3 回答
265 浏览

c# - 理论上是否可以从 C# 访问任何库(也就是 PInvoke 在幕后做了什么)?

像很多地方一样,我的工作场所有遗留代码以及更现代的应用程序。例如,我们有一个仍然使用 Microsoft Fortran77 编译器的服务器应用程序。应用程序中较旧的部分是为 Visual Studio 6 C 编译器编写的,最近出现了一些使用 VS .Net 2008 C++ 编写新库的案例。程序/库有许多不同的机制来相互消费/通信,包括静态链接、共享内存(Windows 内存映射文件)、名称管道和 TCP 套接字。

是什么阻止了 C# 应用程序能够使用任何旧库,例如用过程语言编写的 Fortran77 库之一?

如果我的 C# 应用程序理解 Fortan77 或 C 库的文件格式并且能够找到它想要的过程调用,它是否可以编组托管对象,调用该过程并解组结果?

如果我将 .so 库文件从 Linux 复制到 Windows,并且我的 C# 应用程序理解文件格式,它是否可以调用该库中的函数?

我认为答案与初始化每个库/程序所需的各种 Fortran、C 等运行时有关。如果是这样,那么从根本上说,这些运行时是否与 CLR 大体相似(在 CLR 的情况下,它们具有不同的功能,例如内存管理等)?

编辑:

以另一种方式提出我的问题。如果外星人进来并给了我一个二进制库文件和文件格式规范,我可以从 C# 中使用它吗?

0 投票
4 回答
5508 浏览

c# - 在 DLL“ComCtl32”中找不到名为“TaskDialogIndirect”的入口点

我们有一台特定的 Vista x64 机器,在运行我们的 C# WinForms 应用程序时,它显示以下错误:

System.EntryPointNotFoundException:无法在 DLL“ComCtl32”中找到名为“TaskDialogIndirect”的入口点。

同样的代码在其他 Vista 机器上也能正常工作。出于某种原因,这台特定的 Vista 机器总是抛出这个异常。

我们如何解决这个问题?

0 投票
1 回答
3126 浏览

c# - 通过 P/Invoke 调用 GetGUIThreadInfo

我想将键盘输入发送到另一个进程中的窗口,而不将该窗口带到前台。我可以PostMessage用来伪造WM_KEYDOWNand WM_KEYUP; 我只需要知道哪个窗口句柄应该接收键盘输入——即,类似于GetFocus的东西,但用于另一个非活动应用程序。

GetGUIThreadInfo API 看起来很有希望——它为另一个应用程序返回一个hwndFocus。但是我没有运气让它在我的 64 位操作系统上通过 C# 工作。我已经从pinvoke.net复制(然后进一步调整)声明,但我得到的只是一个通用错误代码(下面有更多详细信息)。

我在调用 GetGUIThreadInfo 之前设置了 cbSize,因此我避免了最明显的潜在问题。

我正在运行 64 位 Vista,所以我不知道问题是我没有正确使用 API,还是它在 64 位中的工作方式不同——我还没有找到专门的代码示例说它在Win64中成功运行。

这是示例代码。我按照建议使用 GetWindowThreadProcessId ,所以我认为问题与混合线程 ID 和线程句柄无关:

window是一个有效的窗口句柄;GetWindowThreadProcessId返回一个非零线程句柄。但是调用GetGUIThreadInfoalways 返回false,并且异常消息总是“参数不正确”。

以防万一问题是GetGUIThreadInfo不知何故没有 64 位版本,我尝试将声明IntPtr中的所有 8-byte s更改GuiThreadInfo为 4-byte ints,但我仍然遇到相同的错误。

有没有人GetGUIThreadInfo在 Win64 上有一个有效的 C# 示例?或者,是否有另一种方法可以在不激活该应用程序的情况下找到另一个应用程序中的焦点子窗口句柄?

0 投票
4 回答
3481 浏览

c# - 在传递给非托管代码之前将委托固定在结构中

我正在尝试使用非托管 C dll 将图像数据加载到 C# 应用程序中。该库有一个相当简单的接口,您可以在其中传入一个包含三个回调的结构,一个接收图像的大小,一个接收每一行像素,最后一个在加载完成时调用。像这样(C# 托管定义):

以 st_ImageProtocol 开头的类型是委托:

对于我正在使用的测试文件,SetSize 应该被调用一次,然后 SendLine 将被调用 200 次(图像中的每一行像素一次),最后触发了 Done 回调。实际发生的是 SendLine 被调用 19 次,然后抛出 AccessViolationException 声称库试图访问受保护的内存。

我可以访问 C 库的代码(尽管我无法更改功能),并且在它调用 SendLine 方法的循环期间它不会分配或释放任何新内存,所以我的假设是委托本身是问题,我需要在传递它之前将其固定(我目前在委托本身内没有代码,除了一个计数器来查看它被调用的频率,所以我怀疑我在托管方面破坏了任何东西)。问题是我不知道该怎么做;我一直用来在非托管空间中声明结构的方法不适用于委托 (Marshal.AllocHGlobal()),而且我找不到任何其他合适的方法。代表本身是 Program 类中的静态字段,因此它们不应该被垃圾收集,但我猜运行时可能会移动它们。

Chris Brumme 的这篇博客文章说,委托在传递到非托管代码之前不需要固定:

显然,非托管函数指针必须指向一个固定地址。如果 GC 重新定位它,那将是一场灾难!这导致许多应用程序为委托创建固定句柄。这是完全没有必要的。非托管函数指针实际上是指我们动态生成以执行转换和封送处理的本机代码存根。此存根存在于 GC 堆外的固定内存中。

但是我不知道当委托是结构的一部分时这是否成立。这确实意味着可以手动固定它们,我对如何执行此操作或关于为什么循环运行 19 次然后突然失败的任何更好建议感兴趣。

谢谢。


编辑回答约翰的问题......

分配结构体的代码如下:

其中 _sendLineFunc 和 _imageProtocol 变量都是 Program 类的静态字段。如果我正确理解了它的内部结构,这意味着我将一个指向_imageProtocol 变量副本的非托管指针传递到 C 库中,但该副本包含对静态 _sendLineFunc 的引用。这应该意味着 GC 不会触及副本 - 因为它是非托管的 - 并且委托不会被收集,因为它仍在范围内(静态)。

该结构实际​​上作为另一个回调的返回值传递给库,但作为指针:

基本上还有另一种结构类型,它保存图像文件名和指向此回调的函数指针,库确定文件中存储的图像类型,并使用此回调为给定类型请求正确的协议结构。我的文件名结构的声明和管理方式与上面的协议相同,因此可能包含相同的错误,但由于此委托只被调用一次并且调用速度很快,所以我还没有遇到任何问题。


编辑更新

感谢大家的回复,但在又花了几天时间解决这个问题但没有任何进展后,我决定搁置它。万一有人感兴趣,我正在尝试为 Lightwave 3D 渲染应用程序的用户编写一个工具,一个不错的功能是能够查看 Lightwave 支持的所有不同图像格式(其中一些是相当奇特的)。我认为最好的方法是为 Lightwave 用于图像处理的插件架构编写一个 C# 包装器,这样我就可以使用他们的代码来实际加载文件。不幸的是,在针对我的解决方案尝试了一些插件之后,我遇到了各种我无法理解或修复的错误,我的猜测是 Lightwave 没有以标准方式调用插件上的方法,可能是为了提高运行外部代码的安全性(我承认在黑暗中野蛮刺伤)。暂时我将放弃图像功能,如果我决定恢复它,我会以不同的方式处理它。

再次感谢,即使我没有得到我想要的结果,我也通过这个过程学到了很多东西。

0 投票
3 回答
1055 浏览

.net - DllImport 和 ASP.NET

我在使用 DllImport 和 ASP.NET 时遇到了一些问题,因为当我使用导入的方法时,ASP.NET 会加载 Dll 并锁定文件,即使它完成使用后也是如此。有没有办法强制 ASP.NET 释放文件上的锁定?