解决.net开发问题的最终法宝

原创 2004年06月03日 16:37:00

这两天正在网上找工作。昨天一网友问了个问题,说SendMessage在.net中调用失败。
我看了看他的代码是用VB.net写的。于是我改用C#写了个小的测试程序
using System.Runtime.InteropServices;

[DllImport("user32.dll")]
private static extern long SendMessageW(int hwnd,int wMsg,int wParam,int lParam);

System.Diagnostics.Process[] p;
p=System.Diagnostics.Process.GetProcessesByName("notepad");
int i=p[0].Handle.ToInt32();
SendMessageW(i,16,0,0); 

(因为SendMessage分两个版本,一个是SendMessageA一个是SendMessageW,由于NT下内部使用的是SendMessageW,而SendMessageA的调用则是先将参数转换后再调用SendMessageW,所以这里我是用SendMessageW。)
这个程序的功能是查找一个记事本程序,然后向他发送关闭消息。
试验了一下,果然失败了。
开始我怀疑是.net的问题,因为一个网友曾经说过在VB中调用成功的代码在VB.net中调用失败了。于是我是用ILDASM对该程序进行反汇编。反编译后IL代码如下。
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
  // 代码大小       40 (0x28)
  .maxstack  4
  .locals init ([0] class [System]System.Diagnostics.Process[] p,
           [1] int32 i,
           [2] native int CS$00000002$00000000)
  IL_0000:  ldstr      "notepad"
  IL_0005:  call       class [System]System.Diagnostics.Process[] [System]System.Diagnostics.Process::GetProcessesByName(string)
  IL_000a:  stloc.0
  IL_000b:  ldloc.0
  IL_000c:  ldc.i4.0
  IL_000d:  ldelem.ref
  IL_000e:  callvirt   instance native int [System]System.Diagnostics.Process::get_Handle()
  IL_0013:  stloc.2
  IL_0014:  ldloca.s   CS$00000002$00000000
//这里是SendMessageW调用的部分将p[0].Handle.ToInt32()放入参数1
  IL_0016:  call       instance int32 [mscorlib]System.IntPtr::ToInt32()
  IL_001b:  stloc.1
  IL_001c:  ldloc.1
//放入16,参数2
  IL_001d:  ldc.i4.s   16
//放入0,参数3
  IL_001f:  ldc.i4.0
//放入0,参数4
  IL_0020:  ldc.i4.0
  IL_0021:  call       int64 TWin.Class1::SendMessageW(int32,
                                                       int32,
                                                       int32,
                                                       int32)
  IL_0026:  pop
  IL_0027:  ret
看不出有什么问题,本来我以为是不是某个值被装箱之类的操作了。一看所有参数都是标准的int32类型,这个可是值啊。
我并没有就此觉悟,反而还是执迷不悟的怀疑是.net出的问题。
于是运行程序,在SendMessageW(i,16,0,0)处设置断点,看看汇编码。(运行时,在代码的旁边有个反汇编的tab,通过它你就可以看到汇编码了)
0000004f  push        0   
00000051  push        0   
00000053  mov         ecx,edi
00000055  mov         edx,10h
0000005a  call        dword ptr ds:[009C50F8h]
00000060  nop
在Win32汇编中API函数的调用使用的方法是将参数值压入栈中(后进现出)的原则,所以参数压入顺序为4321。
汇编中的语句
0000004f  push        0   
00000051  push        0   
00000053  mov         ecx,edi
00000055  mov         edx,10h
都没错。唯一有可能出错的就是
0000005a  call        dword ptr ds:[009C50F8h]
于是问题很清楚了,.net调用API函数的方法没有错,是传递的参数出了错。用VC++的工具SPY++看看吧,果然发现句柄与p[0].Handle.ToInt32()不符。无意间发现p[0].MainWindowHandle与SPY++的结果相符,忽然间恍然大悟。大骂自己愚蠢分明需要给程序的窗体传送消息,你给那个进程ID传送,人家谁理你啊!
改用p[0].MainWindowHandle实验,记事本被关闭了。虽然犯了傻不过倒是总结了些解决.net出的问题的一些方法,如果你有些问题感到莫名其妙,找不到方法就不如用ILDASM去反编译一下,看看IL代码说不定有帮助,如果还不行,干脆就用看看汇编码,说不定问题就明白了。
告诉他后,他又问了我另一个问题,一个窗体如何得到自己的句柄呢,其实这个很简单,this.Handle.ToInt32()就是自己的句柄了。
  结尾打个广告吧,本人软开工作两年想找一份月薪3000元的北京的工作。有意者请与我联系fjl716@163.com

开发过程中遇到问题解决方法

自定义cell 时获取到的width 总是320: https://my.oschina.net/ioslighter/blog/390880 dyld: Library not load...
  • u013410274
  • u013410274
  • 2017年04月25日 09:46
  • 229

关于管理者应该拥有的的六十…

点点滴滴都是智慧原文地址:关于管理者应该拥有的的六十八个哲理作者:Harry_鹏一、用人之道      去过庙的人都知道,一进庙门,首先是弥陀佛,笑脸迎客,而在他的北面,则是黑口黑脸的韦陀。但相传在很...
  • feiniu5566
  • feiniu5566
  • 2013年10月30日 11:52
  • 658

事件冒泡的解决方案

1、事件冒泡:        在一个对象上触发某类事件(例如单击事件onclick事件),若果此对象定义了此事件的处理程序,那么就会调用这个处理程序;但是如果没有定义此事件的处理程序或者事件返回tr...
  • fb_01
  • fb_01
  • 2016年04月18日 17:03
  • 344

C#.NET开发中常用的技术问题汇总(持续更新)

C#.NET开发中常用的技术问题汇总 001.判断一个Form是否已关闭并释放,需要从引用和对象两方面来判断,     判断引用是否为null: mainfm == null     判断引用的对象是...
  • gyming
  • gyming
  • 2013年06月30日 21:53
  • 3227

开发过程中遇到问题该怎么办?

开发过程中遇到问题了怎么办日常开发过程中,总会遇到问题,那么遇到问题该怎么办呢?   首先我们把问题分成大的两类:业务问题、技术问题。一、业务问题这类问题一般跟你的需求和设计相关。大致分下列情况:1、...
  • shijing266
  • shijing266
  • 2017年05月05日 16:42
  • 1664

消息中间件(一)分布式系统事务一致性解决方案大对比,谁最好使?

在分布式系统中,同时满足“一致性”、“可用性”和“分区容错性”三者是不可能的。分布式系统的事务一致性是一个技术难题,各种解决方案孰优孰劣?在OLTP系统领域,我们在很多业务场景下都会面临事务一致性方面...
  • dreamsunday
  • dreamsunday
  • 2016年06月29日 18:37
  • 12540

分布式事务解决方案一之:可靠消息最终一致性

分布式事务解决方案一之:可靠消息最终一致性
  • zhangxiaomin1992
  • zhangxiaomin1992
  • 2017年08月10日 10:54
  • 1060

java学习中关于异常

java异常是java提供的用于处理程序中错误的一种机制。 语法:try{ 语句1; 语句2; }catch(sth1exception e){ 语句3; }catch(sth2exceptio...
  • hanjiangb
  • hanjiangb
  • 2017年07月27日 21:32
  • 72

JS冒泡事件解决方案

何为冒泡事件。 就是当设定了多个div的嵌套时;即建立了父子关系,当父div与子div共同加入了onclick事件时,当触发了子div的onclick事件后,子div进行相应的js操作。但是父div的...
  • lixin3273110c
  • lixin3273110c
  • 2013年09月25日 21:56
  • 577

自己开发过程中遇到的问题及解决办法

1. myeclipse+hibernate+junit 在进行测试时出现invalid project specified对话框原因:你的工程可能是复制过来的。而你改名字时前面的一个空格没去掉。2....
  • tianhandigeng
  • tianhandigeng
  • 2010年07月20日 09:01
  • 2000
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:解决.net开发问题的最终法宝
举报原因:
原因补充:

(最多只允许输入30个字)