动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   .Net → 阅读文章

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

作者来源: 
阅读 2754 人次 , 2006-3-29 4:35: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

 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:实现自己的ASP.NET宿主系统
· 下一篇:如何在ASP.NET中显示数据库中的数据
· 一个简单的ASP.NET Forms 身份认证
· 细细品味ASP.NET(三)
· Visual Studio.NET版本比较(中文版)
· 迁移到 ASP .NET:需考虑的重要问题(1)
· 在团队开发环境中使用 Visual Studio .NET(一)


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077