.NET中调用API的问题

licry01 2006-07-14 05:05:29
是个很老的问题,就是在调用Excel后,excel不能正常退出的,我想用api来强制结束打开的excel进程。


VB6中api的声明:
Public Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Long, lpdwProcessId As Long) As Long

Public Declare Function OpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

Public Declare Function TerminateProcess Lib "kernel32" Alias "TerminateProcess" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long

根据约定(vb6中的long在vb.net中用Integer)在.NET中声明为:
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" Alias "GetWindowThreadProcessId" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer

Private Declare Function OpenProcess Lib "kernel32.dll" Alias "OpenProcess" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer

Private Declare Function TerminateProcess Lib "kernel32.dll" Alias "TerminateProcess" (ByVal hProcess As Integer, ByVal uExitCode As Integer) As Integer

大概的代码如下:

dim oExcel As Excel.Application
Dim hwnd As Integer, pid As Integer,rtv as Integer ,h as Integer

oExcel = New Excel.Application
hwnd = oExcel.Hwnd
rtv = GetWindowThreadProcessId(hwnd , pid)

If pid > 0 Then
Response.Write("[[[ " + pid.ToString() + " ]]]" + hwnd.ToString)
h = OpenProcess(1, 1, pid)
TerminateProcess(h, 0)
End If
oExcel.quit()

出现的问题是pid老是返回0,郁闷死了,怎么也想不明白,后来到google游荡了半天,把声明改成下面的:
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" Alias "GetWindowThreadProcessId" (ByVal hwnd As IntPtr, ByRef lpdwProcessId As IntPtr) As IntPtr

代码也改为:

dim oExcel As Excel.Application
Dim hwnd As IntPtr, pid As IntPtr,rtv as IntPtr ,h as Integer

oExcel = New Excel.Application
hwnd = New IntPtr(oExcel.Hwnd)
rtv = GetWindowThreadProcessId(hwnd , pid)

If pid > 0 Then
Response.Write("[[[ " + pid.ToString() + " ]]]" + hwnd.ToString)
h = OpenProcess(1, 1, pid)
TerminateProcess(h, 0)
End If
oExcel.quit()

问题依旧!!我开始怀疑托管代码对api的调用是否有效,一气之下,我从任务管理器中把上次没结束的execl的进程id直接写死,
h = OpenProcess(1, 1, 2780)
TerminateProcess(h, 0)
结果是可以强制关闭进程的,调用api是没有问题的。


通过一下小测试,我个人觉得是窗口句柄参数传递的问题:

Private Declare Function GetWindow Lib "user32.dll" Alias "GetWindow" (ByVal hwnd As IntPtr, ByVal wCmd As Integer) As IntPtr

hwnd = New IntPtr(oExcel.Hwnd)
hwnd1 = GetWindow(hwnd, 5)

hwnd1始终返回0。


敬请高手指点指点,将不胜感激!!!



...全文
418 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
licry01 2006-07-14
  • 打赏
  • 举报
回复
奇怪了,我换到winform环境下就没有一点问题了,怎么调用excel都用正常退出;用api也能完成退出。看来不是参数传递的问题,是我的应用环境的问题,我是应用在web方面的,呵呵。

结贴了
cracher 2006-07-14
  • 打赏
  • 举报
回复
比如
Public Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
需要转换为
Public Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Integer, lpdwProcessId As Integer) As Integer
cracher 2006-07-14
  • 打赏
  • 举报
回复
.net声明API时,必须把所有的long类型转换为integer
.net的integer已经是32位的
hhjjhjhj 2006-07-14
  • 打赏
  • 举报
回复
问题不在数据类型上,如下我在winform中可以得到值
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer

Sub tt()
Dim pid As Integer, rtv As Integer, xlapp As Object
xlapp = CreateObject("excel.application")
rtv = GetWindowThreadProcessId(xlapp.hwnd, pid)
MsgBox(pid)
xlapp.quit()
End Sub
EricBai 2006-07-14
  • 打赏
  • 举报
回复
要得到窗口句柄可以使用 Me.Handle.ToInt32()
EricBai 2006-07-14
  • 打赏
  • 举报
回复
哦,对了,顺便说一下你的api定义中应该将所有的long类型转换成Integer,因为vb6中的long(32位)对应.net中的integer(32位)
EricBai 2006-07-14
  • 打赏
  • 举报
回复
如果有多余的进程就是说,曾经没有正确关闭设置nothing过,用进程管理器把多余的关闭,运行你的程序试试看。如果正常的close并且设置nothing的话,应该没有多余的进程了,我以前碰到过和你一样的问题。就是这个原因。
hhjjhjhj 2006-07-14
  • 打赏
  • 举报
回复
用getobject试试

x=getobject(nothing,"excel.application")
x.quit()
licry01 2006-07-14
  • 打赏
  • 举报
回复
就是有啊
没有的话,我就不会想强制关它了。
EricBai 2006-07-14
  • 打赏
  • 举报
回复
进程管理里面有没有多余Excel的进程?
licry01 2006-07-14
  • 打赏
  • 举报
回复
Catch ex As Exception
Response.Write(ex.ToString)
End Try

Response.Write(ex.ToString)这句代码没有被执行到,说明前面没有错误产生



EricBai 2006-07-14
  • 打赏
  • 举报
回复
你是不是已经产生过一次错误了?也就是说有一次没有设置nothing的情况,只要有一次没有设置nothing的话,你下次就算nothing了也还是没有用,需要Ctrl+Alt+Del,在Task管理里面删除你调用的那个Excel进程。
另外,如果出现意外了,也必须设置nothing,我看到你的 Catch ex As Exception 后面没有设置nothing的代码啊(只要设置nothing 不用 close了)。
licry01 2006-07-14
  • 打赏
  • 举报
回复
我的不行啊
这是我原来的代码:
Try
oBook.Save()
oBook.Close()
oBooks.Close()
oExcel.Quit()

ReleaseComObject(oSheet)
ReleaseComObject(oBook)
ReleaseComObject(oBooks)
ReleaseComObject(oExcel)
oSheet = Nothing
oBook = Nothing
oBooks = Nothing
oExcel = Nothing

Catch ex As Exception
Response.Write(ex.ToString)
End Try

我这样做了,excel还是不能正常退出,我才想到要用api强制退出的.
EricBai 2006-07-14
  • 打赏
  • 举报
回复
我解决这个问题的方法就是:
1. close 所有要 close的
2. 将与Excel操作有关的对象都设置为nothing

16,553

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧