为什么调用了Close()后,进程还是没有关闭的?

GrimAngel 2009-11-22 09:39:04
这个程序是我参照这里做出来的:

http://yhchinabest.blog.163.com/blog/static/2900648520077331548893/
不是为什么。。我调用了Close()后,用进程管理器看,Excel还在运行的,有高手可

以解释下并给个方法我关了它么?
程序退出了,COM不在了,但如果别人多次操作的话。。会有10几个COM进程在无为占

着内存总不是一件好事吧。

如果要源码可以到这里拿
www.126.com
帐号:CSDNtest1
密码:CSDNtest

代码主要如下:
_Application oApp; //Excel进程对象
Workbooks oWorkbooks; //工作簿集合
_Workbook oWorkbook; //工作簿对象
Worksheets oWorksheets; //工作表集合
_Worksheet oWorksheet; //工作表
Range oRange; //代表某一单元格、某一行、某一列、

某一选定区域
void CMy1Dlg::OnButton1()
{
// TODO: Add your control notification handler code here
CString str1 = "c:\\CJWL081.xls";
char *buf1 = str1.GetBuffer(str1.GetLength());
NewApplication();
Open(buf1);
Read(1);
Close();

oWorksheet.ReleaseDispatch();
oApp.ReleaseDispatch();
oRange.ReleaseDispatch();
oWorkbooks.ReleaseDispatch();
oWorkbook.ReleaseDispatch();
oWorksheets.ReleaseDispatch();

CannotFindN.RemoveAll();
SearchName1.RemoveAll();
SearchName2.RemoveAll();
Name.RemoveAll();
FetionID.RemoveAll();
Telephone.RemoveAll();
Telephone1.RemoveAll();
}

void CMy1Dlg::NewApplication()
{
if (!oApp.CreateDispatch("Excel.Application",NULL))
{
AfxMessageBox("创建Excel服务失败!");
exit(1);
}
oWorkbooks=oApp.GetWorkbooks(); //获取当前工作簿集合
}

void CMy1Dlg::Open(char *pFilename)
{
oWorkbook=oWorkbooks.Open

(pFilename,vtMissing,vtMissing,vtMissing,vtMissing, //打开一个Excel文件


vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMi

ssing,vtMissing,vtMissing); //并指定其为当前工作簿
}

void CMy1Dlg::Read(int Value)
{
oWorksheets=oWorkbook.GetWorksheets(); //获得工作表集合
oWorksheet=oWorksheets.GetItem(_variant_t((long)1)); //假定只有一张


oRange=oWorksheet.GetRange(_variant_t("A1"),vtMissing); //选择第一


_variant_t Value2=oRange.GetItem(_variant_t((long)1),_variant_t((long)1));
CString str = (LPCTSTR)_bstr_t(Value2);
MessageBox(str);
}


void CMy1Dlg::Close()
{
oWorkbook.Close(vtMissing,vtMissing,vtMissing); //关闭当前工作簿
oApp.Quit(); //退出进程
}
...全文
715 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
GrimAngel 2009-11-26
  • 打赏
  • 举报
回复
再次谢谢楼上的帮助。
WaistCoat14 2009-11-25
  • 打赏
  • 举报
回复
oRangeV.DetachDispatch(); oRangeV->ReleaseDispatch
oRange.DetachDispatch(); oRange->oRange.ReleaseDispatch();
GrimAngel 2009-11-25
  • 打赏
  • 举报
回复
对不起,我上面说错了一点,我更正为:我查过GetItem的定义,里面好像是以这样结束的喔“return result;”这个result是这样定义的“VARIANT result;”
WaistCoat14 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 grimangel 的回复:]
先谢楼上的继续帮助。。
嗯。。不太明白你想说些什么。
这两句是什么?。。。
你的意思是把“oRangeV.DetachDispatch();”改成“oRangeV->ReleaseDispatch ”
把“oRange.DetachDispatch(); ”改成“oRange->oRange.ReleaseDispatch();”么。
试过了。。编译失败。。
[/Quote]

不好意思,回复错误

oRangeV.DetachDispatch();->oRangeV.ReleaseDispatch();
oRange.DetachDispatch();->oRange.ReleaseDispatch();
GrimAngel 2009-11-25
  • 打赏
  • 举报
回复
先谢楼上的继续帮助。。
嗯。。不太明白你想说些什么。
这两句是什么?。。。
你的意思是把“oRangeV.DetachDispatch();”改成“oRangeV->ReleaseDispatch ”
把“oRange.DetachDispatch(); ”改成“oRange->oRange.ReleaseDispatch();”么。
试过了。。编译失败。。
WaistCoat14 2009-11-25
  • 打赏
  • 举报
回复
因为Range的GetItem的返回值是VARINAT类型,你调试可以看到返回的VARIANT变量的vt为VT_DISPATCH,说明返回的是一个IDispath指针。

因为是Range对象的GetItem返回值,从而判断出返回的为一个Range的对象指针。
GrimAngel 2009-11-25
  • 打赏
  • 举报
回复
顶一下
GrimAngel 2009-11-25
  • 打赏
  • 举报
回复
终于可以关闭了,谢谢楼上多次的帮助我。。。
这位高手,可以说给我听你是怎么知道是“Range对象GetItem返回值还是一个Range对象,而这个对象你没有释放”这个原因以至Excel不能关闭的呢?。。。
就是说你是怎么找出原因的呢?。。可以的话请告诉下我吧,不过你已经帮我了好多了,你可以选择不答,分数一样全给你了,呵呵。。
GrimAngel 2009-11-24
  • 打赏
  • 举报
回复
先谢楼主替我想办法,我查过GetItem的定义,里面好像是以这样结束的喔“return result;”这个result是这样定义的“LPDISPATCH result”,我用是office2003的。唉,真是不灭的Excel啊,我用你的方法,Excel还是死在那里没关闭,天啊,我的代码现在是这样了,和你的应该是一致的,求解答。
CString str1 = "c:\\CJWL081.xls";
char *buf1 = str1.GetBuffer(str1.GetLength());
/*NewApplication();
Open(buf1);
Read(1);*/
oApp.CreateDispatch("Excel.Application",NULL);
oWorkbooks=oApp.GetWorkbooks(); //获取当前工作簿集合
oWorkbook=oWorkbooks.Open(buf1,vtMissing,vtMissing,vtMissing,vtMissing, //打开一个Excel文件
vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing); //并指定其为当前工作簿
oWorksheets=oWorkbook.GetWorksheets(); //获得工作表集合
oWorksheet=oWorksheets.GetItem(_variant_t((long)1)); //假定只有一张表
oRange=oWorksheet.GetRange(_variant_t("A1"),vtMissing); //选择第一列

oRangeV.AttachDispatch(oRange.GetItem(_variant_t((long)1),_variant_t((long)1)).pdispVal);
//_variant_t Value2=oRangeV.GetValue2();
//CString str = (LPCTSTR)_bstr_t(Value2);
//MessageBox(str);
oRangeV.DetachDispatch();
oRange.DetachDispatch();
oWorksheet.ReleaseDispatch();

oWorksheets.ReleaseDispatch();
oWorkbook.Close(vtMissing,vtMissing,vtMissing); //关闭当前工作簿
oWorkbook.ReleaseDispatch();
oWorkbooks.Close();
oWorkbooks.ReleaseDispatch();

oApp.Quit(); //退出进程
oApp.ReleaseDispatch();

CannotFindN.RemoveAll();
SearchName1.RemoveAll();
SearchName2.RemoveAll();
Name.RemoveAll();
FetionID.RemoveAll();
Telephone.RemoveAll();
Telephone1.RemoveAll();
WaistCoat14 2009-11-24
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 grimangel 的回复:]
多谢楼上的继续帮助,你的方法很好,让我知道了哪里出现让Excel不能退出的地方:
当这句出现时就不能退出Excel了
_variant_t Value2=oRange.GetItem(_variant_t((long)1),_variant_t((long)1));

我很菜,还在思考这是为什么。。。
[/Quote]

我今天测试了下,是因为Range对象GetItem返回值还是一个Range对象,而这个对象你没有释放。正确的做法是:

void COfficeTestDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
CApplication oApp;
oApp.CreateDispatch(_T("Excel.Application"));
CWorkbooks books;
books = oApp.get_Workbooks();
CWorkbook book;

book = books.Open(_T("E:\\test.xls"), vtMissing,vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,vtMissing, vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing );

CWorksheets sheets;
sheets = book.get_Worksheets();
CWorksheet sheet;
sheet = sheets.get_Item(_variant_t((LONG)1));
CRange range;
range = sheet.get_Range(_variant_t("B4"),vtMissing);
CRange rangV;
rangV.AttachDispatch(range.get_Item(_variant_t((LONG)1), _variant_t((LONG)2)).pdispVal);
_variant_t value = rangV.get_Value2();
rangV.ReleaseDispatch();

range.ReleaseDispatch();

sheet.ReleaseDispatch();
sheets.ReleaseDispatch();

book.ReleaseDispatch();
books.Close();
books.ReleaseDispatch();

oApp.Quit();
oApp.ReleaseDispatch();

//OnOK();
}


我用VS2003测试的,可以在导入类与你的VC6有差别,但原理是一样的,你自己改改就行了.
GrimAngel 2009-11-24
  • 打赏
  • 举报
回复
顶一下
GrimAngel 2009-11-24
  • 打赏
  • 举报
回复
多谢楼上的继续帮助,你的方法很好,让我知道了哪里出现让Excel不能退出的地方:
当这句出现时就不能退出Excel了
_variant_t Value2=oRange.GetItem(_variant_t((long)1),_variant_t((long)1));

我很菜,还在思考这是为什么。。。
WaistCoat14 2009-11-23
  • 打赏
  • 举报
回复
释放要按顺序,顺序与获取的相反。

也就是子对象要在父对象前释放。

例如:
oWorksheets=oWorkbook.GetWorksheets();
oRange=oWorksheet.GetRange(_variant_t("A1"),vtMissing);

释放顺序是先oRange,再oWorksheets,然后oWorkbook。


其他地方LZ你自己都改下。

GrimAngel 2009-11-23
  • 打赏
  • 举报
回复
嗯。。Tr0j4n不好意思。。我居然令人不爽了,忏悔中~~~~~~~~~~~~~~~
至于你说我没有Release,但下在这些都是释放内存空间的吧。

oWorksheet.ReleaseDispatch();
oApp.ReleaseDispatch();
oRange.ReleaseDispatch();
oWorkbooks.ReleaseDispatch();
oWorkbook.ReleaseDispatch();
oWorksheets.ReleaseDispatch();

jameshooo的话我不太能理解,所以我只能按照jameshooo所说的去尽量去试,但结果是失败了。。
希望有个好心的高手帮我解决这个问题好么?。。源码的下载地方我也拿出来了的说。。。
ProgrammerNO1 2009-11-23
  • 打赏
  • 举报
回复
jameshooo说的很清楚了,如果关不掉只能说明还有其他的进程调用了Excel相关接口没有释放
WaistCoat14 2009-11-23
  • 打赏
  • 举报
回复
我觉得还是释放顺序问题,一步步调试看下:
先测试这句能不能关闭:

oApp.CreateDispatch("Excel.Application",NULL);
oApp.Quit();
oApp.ReleaseDispatch();


如果可以,再测试:
oApp.CreateDispatch("Excel.Application",NULL);
oWorkbooks=oApp.GetWorkbooks();
oWorkbooks.ReleaseDispatch();
oApp.Quit();
oApp.ReleaseDispatch();


然后:
oApp.CreateDispatch("Excel.Application",NULL);
oWorkbooks=oApp.GetWorkbooks();
oWorkbook=oWorkbooks.Open(pFilename,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing);
oWorkbook.ReleaseDispatch();
oWorkbooks.Close();
oWorkbooks.ReleaseDispatch();
oApp.Quit();
oApp.ReleaseDispatch();



以此类推。。。。
GrimAngel 2009-11-23
  • 打赏
  • 举报
回复
顶上去一下先。
MoXiaoRab 2009-11-23
  • 打赏
  • 举报
回复
LZ态度让人很不爽
bragi523 2009-11-23
  • 打赏
  • 举报
回复
up
jameshooo
雪影 2009-11-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 grimangel 的回复:]
引用 8 楼 jameshooo 的回复:
顺序设计得不好,这个Close()不符合释放顺序,不能放到一块。大致顺序应该是:
oWorkbook.Close

oXXX.ReleaseDispatch
...
oXXX.ReleaseDispatch

oApp.Quit
oApp.ReleaseDispatch

另,EXCEL作为进程外组件,当你的程序完全释放组件后,EXCEL进程退出是有延时的,可能要等数秒甚至数十秒,EXCEL必须完成所有的内部人物。


先谢了这位高手,但我已经依照你的指示做了喔,按钮事件结束后,我等了5分钟,那Excel.exe还是在进程中没结束掉。
[/Quote]

jameshooo说的很清楚了,如果关不掉只能说明还有其他的进程调用了Excel相关接口没有释放
加载更多回复(12)

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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