使用Microsoft Graph API的C# SharePoint站点备份异常求助
我开发了一款C#应用,通过Microsoft Graph API备份SharePoint站点管理员区域的所有文件。目前有多个SharePoint项目站点,其中近130个站点备份成功,但有200个站点无法被识别或备份失败。
环境信息
- 开发工具:Visual Studio Community
- NuGet包:Microsoft.Graph、Azure.Identity
- 认证方式:ClientSecretCredential
- Graph API版本:使用最新版
- 目标目录:文件下载至
D:\DownloadedFiles
问题详情
- 多数失败站点无明确错误提示,仅文件未被下载
- 失败发生在驱动器项检索或处理阶段,但日志未捕获到具体错误信息
- 已对比正常与异常站点的配置XML、home.aspx文件,仅ID存在差异;确认两类站点权限设置、访问用户一致,所有列表均存在
已采取的排查步骤
- 验证站点设置:对比正常与异常站点的XML配置及home.aspx文件,仅ID不同
- 检查权限:确认两类站点权限配置、访问用户完全一致(包含管理员中心与SharePoint直接设置)
- 确认列表:验证所有列表在两类站点中均存在
- 错误日志:已实现详细错误日志,但未捕获到具体错误内容
核心代码
using Azure.Identity; using Microsoft.Graph; using Microsoft.Graph.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; class Program { private static string clientId = "anonymized"; private static string tenantId = "anonymized"; private static string clientSecret = "anonymized"; private static string downloadPath = @"D:\DownloadedFiles\"; static async Task Main(string[] args) { try { var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret); var graphClient = new GraphServiceClient(clientSecretCredential); // Testing connection Console.WriteLine("Testing connection to SharePoint..."); var sites = await graphClient.Sites.GetAsync(); if (sites != null) { Console.WriteLine("Connected to SharePoint. Listing all active sites..."); foreach (var site in sites.Value) { if (site.WebUrl.Contains("sharepoint.com") && !site.WebUrl.Contains("personal")) { Console.WriteLine($"Site: {site.DisplayName}, URL: {site.WebUrl}, ID: {site.Id}"); string sitePath = Path.Combine(downloadPath, site.DisplayName ?? site.Id); Directory.CreateDirectory(sitePath); // Processing site contents await ProcessSite(graphClient, site.Id, sitePath); } } } else { Console.WriteLine("Failed to connect to SharePoint or no sites found."); } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } static async Task ProcessSite(GraphServiceClient graphClient, string siteId, string path) { try { // Processing drives of the site await ProcessDrives(graphClient, siteId, path); // Retrieving subsites var subSites = await graphClient.Sites[siteId].Sites.GetAsync(); if (subSites.Value != null && subSites.Value.Count > 0) { foreach (var subSite in subSites.Value) { Console.WriteLine($"Processing Sub-Site: {subSite.DisplayName}"); string subSitePath = Path.Combine(path, subSite.DisplayName ?? subSite.Id); Directory.CreateDirectory(subSitePath); // Recursively processing subsites await ProcessSite(graphClient, subSite.Id, subSitePath); } } } catch (Exception ex) { Console.WriteLine($"Error processing site with ID {siteId}: {ex.Message}"); } } static async Task ProcessDrives(GraphServiceClient graphClient, string siteId, string path) { Console.WriteLine($"Processing drives for site with ID: {siteId}"); var drives = await graphClient.Sites[siteId].Drives.GetAsync(); if (drives.Value != null && drives.Value.Count > 0) { foreach (var drive in drives.Value) { Console.WriteLine($"Processing Drive: {drive.Name}"); string drivePath = Path.Combine(path, drive.Name ?? string.Empty); Directory.CreateDirectory(drivePath); await ProcessDriveItems(graphClient, drive.Id, drivePath); } } else { Console.WriteLine("No drives found."); } } static async Task ProcessDriveItems(GraphServiceClient graphClient, string driveId, string path) { try { var rootItems = await graphClient.Drives[driveId].Root.GetAsync(); if (rootItems.Folder != null) { var children = await graphClient.Drives[driveId].Items[rootItems.Id].Children.GetAsync(); await ProcessItems(graphClient, driveId, children.Value, path); } } catch (Exception ex) { Console.WriteLine($"Error processing drive items: {ex.Message}"); } } static async Task ProcessItems(GraphServiceClient graphClient, string driveId, IList<DriveItem> items, string path) { if (items != null) { foreach (var item in items) { var itemPath = Path.Combine(path, item.Name ?? string.Empty); if (item.Folder != null) // It's a folder { Directory.CreateDirectory(itemPath); var folderItems = await graphClient.Drives[driveId].Items[item.Id].Children.GetAsync(); await ProcessItems(graphClient, driveId, folderItems.Value, itemPath); } else if (item.File != null) // It's a file { var fileContent = await graphClient.Drives[driveId].Items[item.Id].Content.GetAsync(); using (var fileStream = new FileStream(itemPath, FileMode.Create, FileAccess.Write)) { await fileContent.CopyToAsync(fileStream); } Console.WriteLine($"Downloaded {item.Name} to {itemPath}"); // Saving meta-information var fileMetaInfo = new { item.Name, item.CreatedDateTime, item.LastModifiedDateTime, CreatedBy = item.CreatedBy?.User?.DisplayName, LastModifiedBy = item.LastModifiedBy?.User?.DisplayName }; var metaInfoPath = $"{itemPath}.meta.json"; await File.WriteAllTextAsync(metaInfoPath, System.Text.Json.JsonSerializer.Serialize(fileMetaInfo)); } } } } }
求助请求
- 分析备份失败的可能原因
- 提供额外的排查步骤或调试技巧
- 指出可能遗漏的SharePoint隐藏配置
内容的提问来源于stack exchange,提问作者IonDOne
相关产品推荐
相关产品推荐

