在进行 Visual Studio 自动化时,是否有更好的方法来处理 RPC_E_CALL_REJECTED 异常?
这就是我目前正在做的事情:
protected void setupProject()
{
bool lbDone = false;
int liCount = 0;
while (!lbDone && liCount < pMaxRetries)
{
try
{
pProject.ProjectItems.Item("Class1.cs").Delete();
lbDone = true;
}
catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001)
{
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
现在我在大多数对 EnvDTE 内容的调用周围都有 try catch 块,并且它运行得很好。我遇到的问题是当我循环遍历集合并对每个项目执行一次操作时。
foreach(ProjectItem pi in pProject.ProjectItems)
{
// do something to pi
}
有时我会在 foreach(ProjectItem pi in pProject.ProjectItems)
行中遇到异常。
由于我不想在收到 RPC_E_CALL_REJECTED 异常时重新启动 foreach 循环,所以我不确定我能做什么。
编辑回答评论: 是的,我正在从另一个程序自动化 VS,是的,我通常同时使用 VS 来做其他事情。我们有一个应用程序读取 xml 文件,然后根据 xml 文件生成大约 50 个 VS 解决方案。这通常需要几个小时,所以我会在发生这种情况时尝试做其他工作。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
此 MSDN 页面上有一个解决方案:如何:修复“应用程序正忙”和“呼叫被被呼叫者拒绝”错误。它展示了如何实现 COM IOleMessageFilter 接口,以便它自动重试调用。
There is a solution on this MSDN page: How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors. It shows how to implement a COM IOleMessageFilter interface so that it will automatically retry the call.
首先,汉斯不想这么说,但“如何做到这一点”的最佳答案是“不要这样做”。如果可能的话,只需将 Visual Studio 的单独实例用于自动化和其他工作即可。
您需要将问题陈述放在可以处理错误的地方。您可以通过使用 in 整数索引而不是 foreach 来完成此操作。
First, Hans doesn't want to say so but the best answer to "how to do this" is "don't do this". Just use separate instances of visual studio for your automation and your other work, if at all possible.
You need to take your problem statement out somewhere you can handle the error. You can do this by using in integer index instead of foreach.
我对MSDN推荐的方法不太幸运,而且看起来相当复杂。我所做的是将重试逻辑包装成一个通用的实用函数,就像在原来的帖子中一样。您可以这样调用它:
“call”函数调用该函数(作为 lambda 表达式传入),并在必要时重试。因为它是一个通用函数,所以您可以使用它来调用任何 EnvDTE 属性或方法,并且它将返回正确的类型。
下面是该函数的代码:
正如原始文章所述,对于 EnvDTE 集合的 foreach 可能会出现问题,因为循环期间存在隐式调用。因此,我使用“调用”函数来获取 Count 属性,然后使用索引进行迭代。它比 foreach 更难看,但是“call”函数使它没有那么糟糕,因为周围没有那么多 try...catch。例如:
I didn't have much luck with the recommended way from MSDN, and it seemed rather complicated. What I have done is to wrap up the re-try logic, rather like in the original post, into a generic utility function. You call it like this:
The 'call' function calls the function (passed in as a lambda expression) and will retry if necessary. Because it is a generic function, you can use it to call any EnvDTE properties or methods, and it will return the correct type.
Here's the code for the function:
As the original post says, foreach over EnvDTE collections can be a problem as there are implicit calls during the looping. So I use my 'call' function to get the Count proprty and then iterate using an index. It's uglier than foreach, but the 'call' function makes it not so bad, as there aren't so many try...catches around. For example:
我使用 C# 读取/写入 Excel 时遇到同样的错误。奇怪的是,它在调试模式下工作,但在已部署的机器上不起作用。我只是将 Excel 应用程序更改为可见,并且它可以正常工作,尽管速度慢了大约两倍。在屏幕上动态打开和关闭 Excel 应用程序很烦人,但这似乎是 Excel 最简单的解决方法。
I was getting the same error using C# to read/write to Excel. Oddly, it worked in debug mode but not on a deployed machine. I simply changed the Excel app to be Visible, and it works properly, albeit about twice as slow. It is annoying to have an Excel app open and close dynamically on your screen, but this seems to be the simplest work-around for Excel.