我编写了C#代码来搜索站点内SharePoint列表中的特定文件类型,并在列表视图中显示文件名。 代码在C#windows应用程序中运行得非常好,但是当它被编译成C#DLL并从Delphi2007应用程序调用时,它会在第一次调用ClientContext.ExecuteQuery()时崩溃。没有异常或错误消息 - Delphi应用程序停止运行。
真正奇怪的部分是我的Delphi测试应用程序有一个Web浏览器组件,如果我使用它导航到站点上的顶级列表,则DLL可以正常工作。
因此,问题是,如果我没有先登录到网站,为什么DLL中的第一个ExecuteQuery调用会失败?
这是C#代码:
public void ListFiles()
{
string LContains = "<Contains><FieldRef Name='FileLeafRef'/> <Value Type ='Text'>{0}</Value></Contains>";
string LNotEqual = "<Contains><FieldRef Name='FileLeafRef'/><Value Type ='Text'>{0}</Value></Contains>";
string LWhereQuery = "";
switch (comboFileType.SelectedIndex)
{
case 0: LWhereQuery = string.Format(LContains, ".DOC"); break;
case 1: LWhereQuery = string.Format(LContains, ".PDF"); break;
case 2: LWhereQuery = string.Format(LNotEqual, "xxxx"); break;
}
Uri LUri = new Uri(SharePointURL);
using (SP.ClientContext LContext = new SP.ClientContext(SharePointURL))
{
System.Net.CredentialCache cc = new System.Net.CredentialCache();
if (!string.IsNullOrEmpty(Domain))
cc.Add(LUri, AuthenticationType, new System.Net.NetworkCredential(UserName, Password, Domain));
else
cc.Add(LUri, AuthenticationType, new System.Net.NetworkCredential(UserName, Password));
LContext.Credentials = cc;
LContext.AuthenticationMode = SP.ClientAuthenticationMode.Default;
var LWeb = LContext.Web;
lvItems.BeginUpdate();
try
{
try
{
SP.List LList = LWeb.Lists.GetByTitle(DefaultListName);
SP.CamlQuery LQuery = new SP.CamlQuery();
LQuery.ViewXml = "<View Scope='RecursiveAll'><Query><Where>"
+ LWhereQuery
+ "</Where></Query><RowLimit> 30 </RowLimit></View>";
SP.ListItemCollection LItems = LList.GetItems(LQuery);
LContext.Load(LItems);
LContext.ExecuteQuery(); **<<<< Crash happens here**
foreach (SP.ListItem LItem in LItems)
{
SP.File LFile = LItem.File;
LContext.Load(LFile);
LContext.ExecuteQuery();
var LViewItem = new ListViewItem();
try { LViewItem.Text = LFile.Name; }
catch { LViewItem.Text = "!Error"; }
try { LViewItem.SubItems.Add(LFile.TimeLastModified.ToString()); }
catch { LViewItem.SubItems.Add("!Error"); }
if (LFile.CheckOutType != Microsoft.SharePoint.Client.CheckOutType.None)
{
try { LViewItem.SubItems.Add(LFile.CheckedOutByUser.LoginName); }
catch { LViewItem.SubItems.Add("!Error"); }
}
else
LViewItem.SubItems.Add("Not checked out.");
try { LViewItem.Tag = LFile.ServerRelativeUrl; }
catch { LViewItem.Tag = "!Error"; }
lvItems.Items.Add(LViewItem);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex);
}
}
finally
{
lvItems.EndUpdate();
}
}
代码位于DLL中对话框窗体的.cs中。表单按原样显示,只有当我单击按钮进行搜索时才会发生崩溃。
我将一些调试代码放入检查所有字符串参数等(通过将它们写入文本文件)并且它们都没问题。
我尝试通过将D2007应用程序指定为“启动外部程序”来尝试从VS调试DLL,但是我无法使断点工作,并且在它崩溃的时候说:类型的未处理异常' System.StackOverflowException'发生在Microsoft.SharePoint.Client.Runtime.dll 中,并建议我可能有一个无限递归调用但是,如前所述,如果我已经登录到站点并浏览到顶级列表,所以我不认为这是一个递归调用。
更新:我通过将Delphi exe复制到与DLL相同的目录来完成调试工作。
我尝试过使用ExceptionHandlingScope,但它没有帮助。这就是崩溃时的样子:
范围没有异常,错误消息为空。我尝试了范围内的一些内涵,但无济于事。
整个代码块都在try..catch中,我尝试将ExecuteQuery行包装在它自己的try..catch中,但没有任何东西可以捕获它。每次我点击继续时,应用程序都会崩溃。
我还尝试在加载网页之前设置执行查询,但它仍然崩溃了。
我认为这必须与凭证有关?如果我故意输入错误的用户名,我会得到一个礼貌的'401 Unauthorized'回来并且没有崩溃。如果我已经登录,它也不会崩溃吗?
答案 0 :(得分:0)
在尝试使用C#测试应用程序后,我尝试使用Delphi XE8,这也很有效,所以最后我在XE8中编写了一个中间DLL。
我注意到,当将TLB从C#DLL导入XE8时,它的行为与D2007的不同之处在于它在构建时抱怨其他缺少的TLB - 特别是system.windows.forms库(以及一些依赖项)。我不确定这是否与XE8工作和D2007失败有关,但希望它能帮助其他需要解决方法的人。