![](/img/trans.png)
[英]How to check Sharepoint connectivity before ClientContext.ExecuteQuery
[英]SharePoint ClientContext.ExecuteQuery works in c# application but crashes in DLL
我编写了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未经授权”,并且不会崩溃。 如果我已经登录,它也不会崩溃?
在尝试了C#测试应用程序之后,我在Delphi XE8上进行了同样的尝试,并且同样有效,因此最终我不得不在XE8中编写一个中间DLL。
我注意到,将TLB从C#DLL导入XE8时,其行为与D2007不同,因为它在构建时抱怨其他缺少的TLB,尤其是system.windows.forms库(和某些依赖项)。 我不确定这是否与XE8正常工作以及D2007失败有关,但希望它能很好地帮助其他需要解决方法的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.