SharePoint ClientContext.ExecuteQuery在c#应用程序中工作但在DLL

时间:2016-06-29 12:28:31

标签: c# delphi sharepoint 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,但它没有帮助。这就是崩溃时的样子:

StackOverflow error in MSSP client runtime dll

范围没有异常,错误消息为空。我尝试了范围内的一些内涵,但无济于事。

整个代码块都在try..catch中,我尝试将ExecuteQuery行包装在它自己的try..catch中,但没有任何东西可以捕获它。每次我点击继续时,应用程序都会崩溃。

我还尝试在加载网页之前设置执行查询,但它仍然崩溃了。

我认为这必须与凭证有关?如果我故意输入错误的用户名,我会得到一个礼貌的'401 Unauthorized'回来并且没有崩溃。如果我已经登录,它也不会崩溃吗?

1 个答案:

答案 0 :(得分:0)

在尝试使用C#测试应用程序后,我尝试使用Delphi XE8,这也很有效,所以最后我在XE8中编写了一个中间DLL。

我注意到,当将TLB从C#DLL导入XE8时,它的行为与D2007的不同之处在于它在构建时抱怨其他缺少的TLB - 特别是system.windows.forms库(以及一些依赖项)。我不确定这是否与XE8工作和D2007失败有关,但希望它能帮助其他需要解决方法的人。