惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
V
Vulnerabilities – Threatpost
GbyAI
GbyAI
P
Proofpoint News Feed
L
LINUX DO - 热门话题
P
Palo Alto Networks Blog
A
About on SuperTechFans
T
Tenable Blog
M
MIT News - Artificial intelligence
IT之家
IT之家
I
Intezer
D
DataBreaches.Net
爱范儿
爱范儿
T
Threatpost
C
CERT Recently Published Vulnerability Notes
云风的 BLOG
云风的 BLOG
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
K
Kaspersky official blog
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
Y
Y Combinator Blog
Cyberwarzone
Cyberwarzone
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Darknet – Hacking Tools, Hacker News & Cyber Security
H
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
Spread Privacy
Spread Privacy
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
AWS News Blog
AWS News Blog
博客园 - 聂微东
C
Check Point Blog
S
Securelist
有赞技术团队
有赞技术团队
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
MongoDB | Blog
MongoDB | Blog
D
Docker
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tailwind CSS Blog
L
Lohrmann on Cybersecurity
G
Google Developers Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog

博客园 - James

Send-only Mail Server with Exim on Ubuntu 10.04 LTS Change hostname on Ubuntu without reboot 51IT最全的自动化测试工具QTP资料 QTP如何启动应用程序(转) - James - 博客园 找出用户表中有重复密码的用户 如何改变Linux Kennel中的shmmax参数 如何在C语言中使用constructor和destructor,gcc环境 如何在Ubuntu上update gem for ruby 1.9.1的版本 google疯了 - James - 博客园 碰巧遇到一些智力面试题,解答一下 避免在电脑上浪费时间的好办法 如何在Postgresql中产生自己的集合function 用RJS写的检测用户名和email是否存在 ajax check username available in rails MSN Messager密码 - James - 博客园 重新开始Blog生活 准备用C#写一个Blog的客户端,大家看看功能缺哪些,哪些不需要? Apache 2 + PHP Windows安装指南(官方版本) .Text Blog .95中一个Unicode的bug - James
PInvoke 白话文
James · 2004-08-12 · via 博客园 - James

白话文,就是简单实用的意思,这是我以前的学习笔记。

1, PInvoke什么意思? Platform Invocation Services
2, 干什么用?  导入外部函数?什么是外部函数,就是不属于.Net托管的函数。
3,如何用?看下面的例子。用[DllImport(dllname)]来实现,但是首先要把System.Runtiime.InteropServices using进来。但是不using也行,就要敲全称,随你便了。

[DllImport("user32.dll")]

         static extern int MessageBoxA(int hWnd,

                                          string msg,

                                          string caption,

                                          int type );

         private void button1_Click(object sender, System.EventArgs e)

         {

              MessageBoxA( 0, "Msg:hello", "Caption:Hello",0 );

         }
4,万一我的程序中已经有了一个函数叫MessageBoxA怎么办?这时候,可以使用EntryPoint来帮忙,下面的例子中,你把自己的函数定义为MyMsg.
[DllImport("user32.dll",EntryPoint="MessageBoxA")]

         static extern int MyMsg(int hWnd,

                                          string msg,

                                          string caption,

                                          int type );

         private void button1_Click(object sender, System.EventArgs e)

         {

              MyMsg( 0, "Msg:hello", "Caption:Hello",0 );

         }


5,charset如何使用?****A的是Ansi编码,****W的是unicode编码,如何使用charset,看你的函数调用而定。2K以后都用unicode了,前面的9x都是ansi编码,但是这是缺省的,微软给9x打布丁支持unicode不算。

API有两个版本: A(ASNI)版本和W(Unicode)版本. A版本调用时候会用ANSI来封送字符串,一般是win95/98上。W版本用Unicode来封送,在NT,2K和XP上。

.Net和win32交互的时候,默认是使用CharSet.Ansi来传送。

在 DllImportAttribute.ExactSpelling 字段为 true 时(它是 Visual Basic .NET 中的默认值),平台调用将只搜索您指定的名称。例如,如果指定 MessageBox,则平台调用将搜索 MessageBox,如果它找不到完全相同的拼写则失败。

ExactSpelling 字段为 false(它是 C++ 托管扩展和 C# 中的默认值),平台调用将首先搜索未处理的别名 (MessageBox),如果没有找到未处理的别名,则将搜索已处理的名称 (MessageBoxA)。请注意,ANSI 名称匹配行为与 Unicode 名称匹配行为不同。

         //CharSet.Ansi will call MessageBoxA

         //CharSet.Unicode will call MessageBoxW

         [DllImport("user32.dll",EntryPoint="MessageBox",CharSet=CharSet.Ansi)]

         static extern int MyMsg(int hWnd,

                                          string msg,

                                          string caption,

                                          int type );

         private void button1_Click(object sender, System.EventArgs e)

         {

              MyMsg( 0, "Msg:hello", "Caption:Hello",0 );

         }

6,Dll里面的callback函数如何实现?看下面这个例子:

delegate bool CallBackDef( int hWnd, int lParm );

         [DllImport("user32.dll")]

              static extern int GetWindowText( int hWnd,

                                                   StringBuilder text,

                                                   int count );

         [DllImport("user32.dll")]

              static extern int EnumWindows(CallBackDef callback, int lParam );

         static bool PrintWindow(int hWnd, int lParm )

         {

              StringBuilder text = new StringBuilder(255);

              GetWindowText( hWnd, text, 255 );

              Console.WriteLine( text.ToString() );

              return true;

         }

         private void button1_Click(object sender, System.EventArgs e)

         {

              CallBackDef callBack = new CallBackDef( PrintWindow );

              EnumWindows( callBack, 0 );

         }


7,MarshalAs如何用,什么时候用?
在MessageBox传递string去Dll的时,C#编译器知道Win32LPSTR等价与一个C#字符串。但是如果想覆盖默认.Net行为, 这时候就需要MarshallAs
[DllImport("user32.dll", CharSet=CharSet.Unicode )]

              static extern int MessageBox( int hWnd,

                                               [MarshalAs(UnmanagedType.LPWStr)]

                                               string msg,

                                               [MarshalAs(UnmanagedType.LPWStr)]

                                               string caption,

                                               int type);

8,我怎么知道要调用的函数在那个dll了?
这个问题我不会比你更清楚,特殊的函数应该在你特殊的dll中。Win32中常用的几个dll是user32.dll, kernel32.dll和GDI32.dll.用dumpbin -exports kernel32.dll可以看到这个dll所有的API函数。

9,相互之间传递struct怎么办?我是说传递很复杂的struct?
传递一个结构,这个要用到StructLayoutAttribute属性。比如:

PtInRect 具有以下非托管签名:
BOOL PtInRect(const RECT *lprc, POINT pt);
请注意,由于函数需要指向 RECT 类型的指针,必须通过引用来传递 Rect 结构。
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]

public struct Point

{

     public int x;

     public int y;

}  

[StructLayout(LayoutKind.Explicit)]

public struct Rect

{

     [FieldOffset(0)] public int left;

     [FieldOffset(4)] public int top;

     [FieldOffset(8)] public int right;

     [FieldOffset(12)] public int bottom;

}  

class Win32API

{

     [DllImport("User32.dll")]

     public static extern bool PtInRect(ref Rect r, Point p);

}

10,哪里有不错的教程,我可以学到更详细的东西?
google一下多的是。MSDN里面也有一些不错的教程:(vs.net 2003)

平台调用数据类型
提供托管数据类型及其相应的非托管数据类型的列表。
封送字符串
描述如何通过值、通过引用、在结构中、在类中和在数组中传递字符串。
封送类、结构和联合
描述如何通过值传递类,如何传递各种结构以及如何传递具有值和混合类型的联合。
封送类型数组
描述如何通过值传递多维整数数组以及如何通过引用传递一维数组。
其他封送处理示例
描述影响 Interop 封送处理行为的垃圾回收和线程处理的各个方面。

11,最后,这位大哥,你说了很多,我想问一个对我来说最关键的问题,我看了你的东西,似是而非,不会用怎么办?

这位兄弟勇气可嘉,我给你准备了一个站点。这里有一个PInvoke的Add-In tools for Visual Studio.Net,几乎所有的Win32 API都有。安装了以后,基本不用自己写了。

http://www.pinvoke.net