问题描述
具体问题如下,后台开了4个进程,4个进程分别从不同的目录启动,我希望能指定某个进程打开文件(比如“d:1.dat”),需要先找到这几个进程,然后通过不同的启动目录进行区别进行调用首先尝试的是找到进程,然后通过发送快捷键组合,后来发现成功不了,问题见另外一个链接。http://bbs.csdn.net/topics/391019530早上想到了干脆模拟资源管理器双击文件使进程打开文件的方式,用spy抓取消息分析。正确的消息是:<00019>000603CESWM_COPYDATAhwndFrom:0009075Epcds:0030FD30[wParam:0009075ElParam:0030FD30]于是根据另外一个帖子http://bbs.csdn.net/topics/300042944写出代码,但是我的消息发送失败。stringstr=@"s:1.datance";COPYDATASTRUCTcopyData;copyData.dwData=newIntPtr(0x0009075E);//IntPtr.Zero;copyData.cbData=Encoding.Default.GetByteCount(str.ToCharArray(),0,str.Length);copyData.lpData=str;IntPtrptr=Marshal.AllocHGlobal((IntPtr)(Marshal.SizeOf(copyData)));Marshal.StructureToPtr(copyData,ptr,true);SendMessage(wh,WM_COPYDATA,-1,(int)ptr)
抓取消息显示发送失败<00197>000603CESWM_COPYDATAhwndFrom:FFFFFFFFpcds:0030FD40[wParam:FFFFFFFFlParam:0030FD40]<00198>000603CERWM_COPYDATAfProcessed:False[lResult:00000000]经过对比,发现正确的cbData(26)比错误的cbData(12)数字大。我如何能知道正确消息里面存储lpData的具体内容是啥?
解决方案
本帖最后由 aquayhy 于 2015-04-18 10:29:35 编辑
解决方案二:
刚刚经过测试,把文件名修改为11.datance,抓到正确的cbData变成了28,也就是说文件名中一个字符占两个字节。s:1.datance共13个字符(加上后面的),乘以2为26。如果认为数据应该以unicode方式发送,一个字符占两个字节,尝试着在代码里面把"s:1.datance"里面每个字符前面插上多余的,也不成功。主要原因是不知道lpData数据发送的到底是啥,无法照样进行修改
解决方案三:
经过调试,现在有所进展unsafepublicstructCOPYDATASTRUCT{publicvoid*dwData;publicintcbData;[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]publicstringlpData;}stringstr="s:\a.dat";//IntPtrstrPtr=Marshal.StringToHGlobalAnsi(str);COPYDATASTRUCTcopyData;copyData.dwData=(void*)3735941134;//IntPtr.Zero;copyData.cbData=(str.Length+1)*2;copyData.lpData=str;IntPtrptr=Marshal.AllocHGlobal((IntPtr)(Marshal.SizeOf(copyData)));Marshal.StructureToPtr(copyData,ptr,true);WinHWND.SendMessage(wh.HWND,WinHWND.WM_COPYDATA,0xC080E,(int)ptr);——这里的0xC080E是为了和抓取的正确消息一致,应该是发送的消息的进程,测试修改没有什么影响。
这次能出现打开对话框的画面了,但是提示是无法载入“XXXXXXXXX”:系统找不到指定的文件。应该是发送的lpData内容有问题,不会查,也不会修改。
解决方案四:
瞎猜的“诡媚”开发方法效率太低了。真正的男人都去选择任何一种靠谱的进程间通讯方法搞开发去了。
解决方案五:
引用3楼sp1234的回复:
瞎猜的“诡媚”开发方法效率太低了。真正的男人都去选择任何一种靠谱的进程间通讯方法搞开发去了。
网上搜了一下进程间通讯方法总结为了能在两个进程之间进行通讯,由以下几种方法可供参考: 1、剪贴板Clipboard:在16位时代常使用的方式,CWnd中提供支持 2、窗口消息标准的Windows消息以及专用的WM_COPYDATA消息SENDMESSAGE()接收端必须有一个窗口 3、使用共享内存方式(SharedMemory) a.设定一块共享内存区域HANDLECreateFileMapping(HANDLE,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCSTR) 产生一个file-mapping核心对象LPVOIDMapViewOfFile(HANDLEhFileMappingObject,DWORDdwDesiredAcess,DWORDdwFileOffsetHigh,DWORDdwFileOffsetLow,DWORDdwNumberOfBytesToMap); 得到共享内存的指针 b.找出共享内存 决定这块内存要以点对点(peertopeer)的形式呈现每个进程都必须有相同的能力,产生共享内存并将它初始化。每个进程都应该调用CreateFileMapping(),然后调用GetLastError().如果传回的错误代码是ERROR_ALREADY_EXISTS,那么进程就可以假设这一共享内存区域已经被别的进程打开并初始化了,否则该进程就可以合理的认为自己排在第一位,并接下来将共享内存初始化。 还是要使用client/server架构中只有server进程才应该产生并初始化共享内存。所有的进程都应该使用HANDLEOpenFileMapping(DWORDdwDesiredAccess,BOOLbInheritHandle,LPCTSTRlpName); 再调用MapViewOfFile(),取得共享内存的指针 c.同步处理(Mutex) d.清理(Cleaningup)BOOLUnmapViewOfFile(LPCVOIDlpBaseAddress);CloseHandle() 4、动态数据交换(DDE)通过维护全局分配内存使的应用程序间传递成为可能 其方式是再一块全局内存中手工放置大量的数据,然后使用窗口消息传递内存指针.这是16位WIN时代使用的方式,因为在WIN32下已经没有全局和局部内存了,现在的内存只有一种就是虚存。 5、消息管道(MessagePipe) 用于设置应用程序间的一条永久通讯通道,通过该通道可以象自己的应用程序访问一个平面文件一样读写数据。 匿名管道(AnonymousPipes) 单向流动,并且只能够在同一电脑上的各个进程之间流动。 命名管道(NamedPipes) 双向,跨网络,任何进程都可以轻易的抓住,放进管道的数据有固定的格式,而使用ReadFile()只能读取该大小的倍数。 可以被使用于I/OCompletionPorts 6、邮件槽(Mailslots) 广播式通信,在32系统中提供的新方法,可以在不同主机间交换数据,在WIN9X下只支持邮件槽客户 7、Windows套接字(WindowsSocket) 它具备消息管道所有的功能,但遵守一套通信标准使的不同操作系统之上的应用程序之间可以互相通信。 8、Internet通信它让应用程序从Internet地址上载或下载文件 9、RPC:远程过程调用,很少使用,因其与UNIX的RPC不兼容。 10、串行/并行通信(Serial/ParallelCommunication) 它允许应用程序通过串行或并行端口与其他的应用程序通信11、COM/DCOM通过COM系统的代理存根方式进行进程间数据交换,但只能够表现在对接口函数的调用时传送数据,通过DCOM可以在不同主机间传送数据。最重要的问题在于:负责打开文件的程序根本就不是我写的,是现成的程序,没有源码、没有任何接口。已经关联过了后缀名,如果直接用系统打开,会调用随机哪个进程进行打开。这个作为学习来研究的。
解决方案六:
没弄清楚,你是要做什么?如果是经由windows资源管理器打开的程序,他的起动参数里面就有。prosess可以非常简单的获得。
解决方案七:
引用5楼zanfeng的回复:
没弄清楚,你是要做什么?如果是经由windows资源管理器打开的程序,他的起动参数里面就有。prosess可以非常简单的获得。
比如双击一个txt程序,启动ultraedit,如果再双击另外一个txt,还是会调用这个ultraedit打开,这个时候传入的参数是什么样的?上面仅仅是个例子。我想通过类似的传入参数的方法,将文件所在的位置字符串,送入某个已有进程内,让它启动该文件。但是目前一直没有成功。