SQL 作业无法 运行 C#.net 控制台应用程序,状态消息:403

SQL job failed to run a C#.net console application with an status message: 403

我有一个控制台应用程序,它使用凭据从“Windows 凭据管理器”连接 Share Point Online,并请求 Share Point Online 下载列表中的所有项目,并且进一步使用此信息启动程序SQL 服务器

我没有编写此类应用程序的经验,但特别是此应用程序在从 Visual Studio 执行或通过执行文件时可以正常工作。但是在同一台计算机上由 SQL Agent 执行时失败,错误代码为 403。

澄清一下:SQL 服务器在我开发应用程序和存储 Share Point 凭据的同一台计算机上运行。 我使用代理在我的 windows 帐户下开始工作,所以我想凭据没有问题。我的 windows 帐户在 SQL 服务器上具有系统管理员权限,在 OS 上具有管理员权限。 但是找了一天也不知道哪里出错了

请大家多多指教,告诉我哪里做错了

提前致谢。

SQL 作业出现输出错误:

Message
Executed as user: LAPTOP\username. Unhandled Exception:System.Net.WebException: 
The remote server returned an error: (403) Forbidden.     
at System.Net.HttpWebRequest.GetResponse()     
at Microsoft.SharePoint.Client.SPWebRequestExecutor.Execute()     
at Microsoft.SharePoint.Client.ClientContext.GetFormDigestInfoPrivate()     
at Microsoft.SharePoint.Client.ClientContext.EnsureFormDigest()     
at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()     
at SharePointTrigger.Program.GetNewItem(String targetSiteUrl, String listName, 
String filedName) in 
C:\Work\Korus\Pernod\Vista\Repose\ETL_LoadDataCSV\SharePointTrigger\Program.cs:line 114     
at SharePointTrigger.Program.Main(String[] args) in 
C:\Work\Korus\Pernod\Vista\Repose\ETL_LoadDataCSV\SharePointTrigger\Program.cs:line 40.  
Process Exit Code -532462766.  The step failed.

并且有控制台应用程序(没有 App.config 文件和 DatabaseOperation class。但是 DatabaseOperation class 只包含在 SQL 服务器上执行过程的方法) :

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using Microsoft.Graph;
using Microsoft.SharePoint.Client;
using OfficeDevPnP.Core.Utilities;
using SP = Microsoft.SharePoint.Client;
using System.Configuration;
using System.Collections.Specialized;
using static SharePointTrigger.DatabaseOperation;

namespace SharePointTrigger
{
    class Program
    {
        static void Main(string[] args)
        {
            //To get values from App.config
            string SQLServerName = ConfigurationManager.AppSettings.Get("SQLServerName");
            string SQLDatabaseName = ConfigurationManager.AppSettings.Get("SQLDatabaseName");
            string SQLProcedureName = ConfigurationManager.AppSettings.Get("SQLProcedureName");
            string SQLJobName = ConfigurationManager.AppSettings.Get("SQLJobName");
            string SPSiteURL = ConfigurationManager.AppSettings.Get("SPSiteURL");
            string SPListName = ConfigurationManager.AppSettings.Get("SPListName");
            string SPStatusColumnName = ConfigurationManager.AppSettings.Get("SPStatusColumnName");
            string SPLoadIdColumnName = ConfigurationManager.AppSettings.Get("SPLoadIdColumnName");
            string SSISVariable_name = ConfigurationManager.AppSettings.Get("SSISVariable_name");
            string SSISEnvironment_name = ConfigurationManager.AppSettings.Get("SSISEnvironment_name");
            string SSISFolder_name = ConfigurationManager.AppSettings.Get("SSISFolder_name");

            int itemCounter = 0;

            JobResult jobResult = new JobResult();

            List<MyItem> myItemList = GetNewItem(SPSiteURL, SPListName, SPStatusColumnName);           
            
            myItemList.Sort((x, y) => y.id.CompareTo(x.id));

            if (myItemList.Count() > 0)
            {
                //To avoid reload the same items
                foreach (MyItem item in myItemList)
                {
                    List<FieldValue> fieldValueList = new List<FieldValue>();

                    fieldValueList.Add(new FieldValue() { fieldName = SPStatusColumnName, fieldValue = "In progress" });

                    UpdateListItem(SPSiteURL, SPListName, item.id, fieldValueList);
                }
                
                //To start jon
                MyItem myItem = myItemList[0];
                int SPListId = myItem.id;

                SqlConnection sqlconnection = DatabaseOperation.GetSqlConnection(SQLServerName, SQLDatabaseName);
                jobResult = DatabaseOperation.StartSQLJob(sqlconnection, SQLProcedureName, SQLJobName, SSISVariable_name, SSISEnvironment_name, SSISFolder_name, SPListId);
            }

            //Update items fields Status, Loadid
            itemCounter = 0;

            foreach (MyItem myItem in myItemList)
            {
                if (itemCounter == 0)
                {
                    List<FieldValue> fieldValueList = new List<FieldValue>();

                    fieldValueList.Add(new FieldValue() { fieldName = SPStatusColumnName, fieldValue = jobResult.result });
                    fieldValueList.Add(new FieldValue() { fieldName = SPLoadIdColumnName, fieldValue = jobResult.loadId });

                    UpdateListItem(SPSiteURL, SPListName, myItem.id, fieldValueList);
                }
                else
                {
                    List<FieldValue> fieldValueList = new List<FieldValue>();

                    fieldValueList.Add(new FieldValue() { fieldName = SPStatusColumnName, fieldValue = "Missed" });

                    UpdateListItem(SPSiteURL, SPListName, myItem.id, fieldValueList);
                }

                itemCounter += 1;
            }
        }

        //Get all items fro the list
        private static List<MyItem> GetNewItem(string targetSiteUrl, string listName, string filedName)
        {
            List<MyItem> myItemList = new List<MyItem>();

            using (ClientContext context = new ClientContext(targetSiteUrl))
            {
                context.Credentials = CredentialManager.GetSharePointOnlineCredential(targetSiteUrl);

                Web myWeb = context.Web;
                SP.List myList = myWeb.Lists.GetByTitle(listName);

                SP.ListItemCollection listItemCollection = myList.GetItems(CamlQuery.CreateAllItemsQuery());

                context.Load(listItemCollection,
                            eachItem => eachItem.Include(
                                                        item => item,
                                                        item => item["Title"],
                                                        item => item["ID"],
                                                        item => item[filedName]    //Field: "Status"
                                                        )
                            ); 

                // ExecuteQuery will pull all data from SharePoint
                // which has been staged to Load()
                context.ExecuteQuery();
                
                foreach (SP.ListItem listItem in listItemCollection)
                {
                    if ((string)listItem[filedName] == "New")
                    {
                        MyItem myItem = new MyItem();

                        myItem.id = (int)listItem["ID"];
                        myItem.title = (string)listItem["Title"];
                        myItem.status = (string)listItem[filedName];

                        myItemList.Add(myItem);
                    }
                }
            }

            return myItemList;

        }
       
        //Update items fields
        static void UpdateListItem(string targetSiteUrl, string listName, int itemId, List<FieldValue> fieldValuesList)
        {

            using (ClientContext context = new ClientContext(targetSiteUrl))
            {
                context.Credentials = CredentialManager.GetSharePointOnlineCredential(targetSiteUrl);

                //List
                SP.List announcementsList = context.Web.Lists.GetByTitle(listName);

                //List item
                SP.ListItem listItem = announcementsList.GetItemById(itemId);

                foreach (FieldValue fieldValue in fieldValuesList)
                {
                    //Change field value
                    listItem[fieldValue.fieldName] = fieldValue.fieldValue;
                }
                
                listItem.Update();

                context.ExecuteQuery();
            }
        }

        private class MyItem
        {
            public int id;
            public string title;
            public string status;
        }

        private class FieldValue
        {
            public string fieldName;
            public string fieldValue;
        }
    }
}

作业步骤设置如下: CMD step

当使用 VS 时,它通常使用 build-in 网络服务器,据我所知 - 部署到真正的 IIS 可能会遇到麻烦。请看这里

https://en.it1352.com/article/530a9f2f660b4088a9637b7d294194af.html

无论如何 - 在某些情况下缺少用于身份验证的 TLS 会导致麻烦

您检查过 SQL 上的用户权限了吗? (here 创建和配置用户以使用 SQL 服务器代理作业的指南)

问题是我没有使用访问令牌进入网站。该应用程序在 Visual Studio 中运行良好,因为之前收到的访问令牌保存在缓存中。我使用此处 https://www.c-sharpcorner.com/article/sharepoint-csom-for-net-standard/

中的示例重写了这部分