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/
中的示例重写了这部分
我有一个控制台应用程序,它使用凭据从“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/
中的示例重写了这部分