天天看點

讀取Excel對使用者執行增加/移除角色的控制台程式

我是微軟Dynamics 365 & Power Platform方面的工程師/顧問羅勇,也是2015年7月到2018年6月連續三年Dynamics CRM/Business Solutions方面的微軟最有價值專家(Microsoft MVP),歡迎關注我的微信公衆号 MSFTDynamics365erLuoYong ,回複459或者20211112可友善擷取本文,同時可以在第一間得到我釋出的最新博文資訊,follow me!

這個是個簡單的控制台程式讀取類似如下内容的Excel内容,對使用者執行增加/移除角色操作并生成結果檔案。

讀取Excel對使用者執行增加/移除角色的控制台程式

直接上代碼如下,添加/移除使用者或者團隊角色的方法可以參考我的博文:常​​見的通過Web API執行associate和disassociate消息示例​​​ 和 ​​Dynamics 365中的常用Associate和Disassociate消息彙總​​ 。

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;

namespace ModifyUserRoles
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.GetEncoding("gb2312");
            Console.WriteLine("本程式用于增加/移除使用者角色,開始連接配接Dynamics 365!");
            try
            {
                var sourceFile = ConfigurationManager.AppSettings["sourceFile"];
                var crmClientUrl = ConfigurationManager.AppSettings["CRMClientUrl"];
                int colCount = Convert.ToInt32(ConfigurationManager.AppSettings["colCount"]);
                int rowCount = Convert.ToInt32(ConfigurationManager.AppSettings["rowCount"]);
                CrmServiceClient crmServiceClient = new CrmServiceClient(ConfigurationManager.AppSettings["connectStr"]);
                if (crmServiceClient.IsReady)
                {
                    Console.WriteLine($"連接配接到Dynamics 365環境 ({crmServiceClient.ConnectedOrgFriendlyName}) 成功,若要開始執行程式,請輸入Y并回車确認!");
                    var inputValue = Console.ReadLine();
                    if (inputValue.Equals("Y", StringComparison.OrdinalIgnoreCase))
                    {
                        List<UserModel> lsUsers = new List<UserModel>();
                        Excel.Application xlApp = new Excel.Application();
                        Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(sourceFile);
                        Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
                        Excel.Range xlRange = xlWorksheet.UsedRange;
                        xlRange.Cells[1, colCount + 1] = "狀态";
                        xlRange.Cells[1, colCount + 2] = "處理消息";
                        xlRange.Cells[1, colCount + 3] = "檢視使用者詳情";
                        UserModel user;
                        UserModel tempUserModel;
                        try
                        {
                            for (int rowIndex = 2; rowIndex <= rowCount; rowIndex++)
                            {
                                Console.WriteLine($"讀取第{rowIndex}行記錄!");
                                user = new UserModel();
                                user.errorMessages = new List<string>();
                                user.warnMessages = new List<string>();
                                user.userId = Guid.Empty;
                                for (int colIndex = colCount + 2; colIndex >= 1; colIndex--)
                                {
                                    user.rowIndex = rowIndex;
                                    if (colIndex == colCount + 1)
                                    {
                                        user.status = GetCellValue(xlRange, rowIndex, colIndex);
                                    }
                                    if (user.status != Enums.HandleStatus.Handled_Successfully.ToString().Replace('_', ' '))
                                    {
                                        switch (colIndex)
                                        {
                                            case 1:
                                                user.userName = GetCellValue(xlRange, rowIndex, colIndex);
                                                if (string.IsNullOrEmpty(user.userName))
                                                {
                                                    user.errorMessages.Add("使用者名或者使用者主要郵箱不能為空!");
                                                }
                                                else
                                                {
                                                    tempUserModel = GetUser(crmServiceClient, user.userName);
                                                    if (tempUserModel == null || tempUserModel.userId == Guid.Empty)
                                                    {
                                                        user.errorMessages.Add("找不到有效的使用者!");
                                                    }
                                                    else
                                                    {
                                                        user.businessUnitId = tempUserModel.businessUnitId;
                                                        user.userId = tempUserModel.userId;
                                                    }
                                                }
                                                break;
                                            case 2:
                                                user.toAssociateRoles = GetCellValue(xlRange, rowIndex, colIndex);
                                                break;
                                            case 3:
                                                user.toDisassociateRoles = GetCellValue(xlRange, rowIndex, colIndex);
                                                break;
                                        }
                                    }
                                }
                                lsUsers.Add(user);
                            }
                            Console.WriteLine("開始處理使用者的角色添加/移除!");
                            var lsRoles = GetRoles(crmServiceClient);
                            foreach (var userInstance in lsUsers.Where(t => !t.errorMessages.Any() && t.status != Enums.HandleStatus.Handled_Successfully.ToString().Replace('_', ' ')))
                            {
                                try
                                {
                                    var userRoles = GetDirectUserRoles(crmServiceClient,userInstance.userId);
                                    if (userInstance.toAssociateRoles != null)
                                    {
                                        foreach (var roleName in userInstance.toAssociateRoles.Split(';'))
                                        {
                                            if (!userRoles.Contains(roleName))
                                            {
                                                var lsR = lsRoles.Where(t => t.roleName.Equals(roleName) && t.businessUnitId == userInstance.businessUnitId).ToList();
                                                if (lsR != null && lsR.Any())
                                                {
                                                    crmServiceClient.Associate("systemuser", userInstance.userId, new Relationship("systemuserroles_association"), new EntityReferenceCollection() { new EntityReference("role", lsR.FirstOrDefault().roleId) });
                                                }
                                                else
                                                {
                                                    userInstance.warnMessages.Add($"角色{roleName}不存在,是以未授予!");
                                                }
                                            }
                                        }
                                    }
                                    if (userInstance.toDisassociateRoles != null)
                                    {
                                        foreach (var roleName in userInstance.toDisassociateRoles.Split(';'))
                                        {
                                            if (userRoles.Contains(roleName))
                                            {
                                                var lsR = lsRoles.Where(t => t.roleName.Equals(roleName) && t.businessUnitId == userInstance.businessUnitId).ToList();
                                                if (lsR != null && lsR.Any())
                                                {
                                                    crmServiceClient.Disassociate("systemuser", userInstance.userId, new Relationship("systemuserroles_association"), new EntityReferenceCollection() { new EntityReference("role", lsR.FirstOrDefault().roleId) });
                                                }
                                                else
                                                {
                                                    userInstance.warnMessages.Add($"角色{roleName}不存在,是以未移除!");
                                                }
                                            }
                                            else
                                            {
                                                userInstance.warnMessages.Add($"使用者沒有角色{roleName},是以不需要移除!");
                                            }
                                        }
                                    }
                                    if (userInstance.userId != Guid.Empty)
                                    {
                                        xlWorksheet.Hyperlinks.Add(xlWorksheet.Cells[userInstance.rowIndex, colCount + 3], $"{crmClientUrl}&pagetype=entityrecord&etn=systemuser&id={userInstance.userId}", "", "", "看看使用者詳情");
                                    }
                                }
                                catch (Exception userEx)
                                {
                                    userInstance.errorMessages.Add($"異常錯誤!{userEx.Message}");
                                }
                            }
                            Console.WriteLine("開始将結果寫入Excel檔案!");
                            foreach (var userInstance in lsUsers.Where(t => t.errorMessages.Any() || t.warnMessages.Any()))
                            {
                                var messages = string.Empty;
                                if (userInstance.errorMessages.Any())
                                {
                                    xlRange.Cells[userInstance.rowIndex, colCount + 1] = Enums.HandleStatus.Failed_to_Handle.ToString().Replace('_', ' ');
                                    messages = string.Join(";", userInstance.errorMessages);
                                }
                                else
                                {
                                    xlRange.Cells[userInstance.rowIndex, colCount + 1] = Enums.HandleStatus.Handled_Partially.ToString().Replace('_', ' ');
                                }
                                if (userInstance.warnMessages.Any())
                                {
                                    if (string.IsNullOrEmpty(messages))
                                    {
                                        messages += string.Join(";", userInstance.warnMessages);
                                    }
                                    else
                                    {
                                        messages = $"{messages};{string.Join(";", userInstance.warnMessages)}";
                                    }
                                }
                                xlRange.Cells[userInstance.rowIndex, colCount + 2] = messages;
                                if (userInstance.userId != Guid.Empty)
                                {
                                    xlWorksheet.Hyperlinks.Add(xlWorksheet.Cells[userInstance.rowIndex, colCount + 3], $"{crmClientUrl}&pagetype=entityrecord&etn=systemuser&id={userInstance.userId}", "", "", "看看使用者詳情");
                                }
                            }
                            foreach (var userInstance in lsUsers.Where(t => !t.errorMessages.Any() && !t.warnMessages.Any()))
                            {
                                xlRange.Cells[userInstance.rowIndex, colCount + 1] = Enums.HandleStatus.Handled_Successfully.ToString().Replace('_', ' ');
                            }
                            xlWorkbook.SaveAs(sourceFile.Replace(".xlsx", "_Result.xlsx"));
                        }
                        catch (Exception exelEx)
                        {
                            Console.WriteLine($"處理Excel資料報錯.{exelEx.Message}");
                        }
                        finally
                        {
                            //cleanup
                            GC.Collect();
                            GC.WaitForPendingFinalizers();

                            //release com objects to fully kill excel process from running in the background
                            Marshal.ReleaseComObject(xlRange);
                            Marshal.ReleaseComObject(xlWorksheet);

                            //close and release
                            xlWorkbook.Close();
                            Marshal.ReleaseComObject(xlWorkbook);

                            //quit and release
                            xlApp.Quit();
                            Marshal.ReleaseComObject(xlApp);
                        }
                    }
                    else
                    {
                        Console.WriteLine("你選擇了取消程式運作!");
                    }
                }
                else
                {
                    throw new Exception($"連接配接Dynamics 365報錯.{crmServiceClient.LastCrmError}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"程式運作出錯:{ex.Message};{ex.StackTrace}");
            }
            Console.WriteLine("程式運作結束,按任意鍵退出!");
            Console.ReadKey();
        }

        public static string GetCellValue(Excel.Range xlRange, int rowIndex, int colIndex)
        {
            string returnVal = string.Empty;
            if (xlRange.Cells[rowIndex, colIndex] != null && xlRange.Cells[rowIndex, colIndex].Value2 != null)
            {
                returnVal = Convert.ToString(xlRange.Cells[rowIndex, colIndex].Value2);
                returnVal = returnVal.Trim();
            }
            return returnVal;
        }

        static IEnumerable<string> GetDirectUserRoles(CrmServiceClient crmServiceClient, Guid userId)
        {
            string fetchXml = string.Format(@"<fetch version='1.0' mapping='logical' distinct='true' no-lock='true'>
<entity name='role'>
<attribute name='name' />
<link-entity name='systemuserroles' from='roleid' to='roleid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='ad'>
<filter type='and'>
<condition attribute='systemuserid' operator='eq' value='{0}' />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>", userId);
            return crmServiceClient.RetrieveMultiple(new FetchExpression(fetchXml)).Entities.Select(x => x.GetAttributeValue<string>("name"));
        }

        public static UserModel GetUser(CrmServiceClient crmServiceClient, string userName)
        {
            UserModel returnVal = new UserModel();
            var fetchXml = $@"<fetch mapping='logical' distinct='false' no-lock='true'>
  <entity name='systemuser'>
    <attribute name='fullname' />
    <attribute name='businessunitid' />
    <filter type='and'>
      <filter type='or'>
        <condition attribute='domainname' operator='eq' value='{userName}' />
        <condition attribute='internalemailaddress' operator='eq' value='{userName}' />
      </filter>
      <condition attribute='isdisabled' operator='eq' value='0' />
    </filter>
  </entity>
</fetch>";
            var userEC = crmServiceClient.RetrieveMultiple(new FetchExpression(fetchXml));
            if (userEC.Entities.Any())
            {
                returnVal.userId = userEC.Entities[0].Id;
                returnVal.businessUnitId = userEC.Entities[0].GetAttributeValue<EntityReference>("businessunitid").Id;
            }
            return returnVal;
        }

        public static List<RoleModel> GetRoles(CrmServiceClient crmServiceClient)
        {
            List<RoleModel> returnVal = new List<RoleModel>(); 
            string fetchXml = @"<fetch no-lock='true' mapping='logical' distinct='false'>
  <entity name='role'>
    <attribute name='name' />
    <attribute name='businessunitid' />
    <attribute name='roleid' />
    <order attribute='name' descending='false' />
  </entity>
</fetch>";
            var roleEC = RetrieveAllRecordsByFetchXml(fetchXml, crmServiceClient);
            foreach(var item in roleEC.Entities)
            {
                returnVal.Add(new RoleModel()
                {
                    businessUnitId = item.GetAttributeValue<EntityReference>("businessunitid").Id,
                    roleId = item.Id,
                    roleName = item.GetAttributeValue<string>("name")
                }); ;
            }
            return returnVal;
        }

        public static string CreateXml(string xml, string cookie, int page, int count)
        {
            XDocument doc = XDocument.Parse(xml);
            if (!string.IsNullOrEmpty(cookie))
            {
                doc.Root.Add(new XAttribute("paging-cookie", cookie));
            }
            doc.Root.Add(new XAttribute("page", page));
            doc.Root.Add(new XAttribute("count", count));
            return doc.ToString(SaveOptions.DisableFormatting);
        }
        public static EntityCollection RetrieveAllRecordsByFetchXml(string fetchXml, CrmServiceClient crmServiceClient, int recordsPerPage = 5000)
        {
            EntityCollection EC = new EntityCollection();
            int pageNumber = 1;
            string pagingCookie = null;
            while (true)
            {
                string xml = CreateXml(fetchXml, pagingCookie, pageNumber, recordsPerPage);
                RetrieveMultipleRequest fetchRequest1 = new RetrieveMultipleRequest
                {
                    Query = new FetchExpression(xml)
                };
                EntityCollection returnCollection = ((RetrieveMultipleResponse)crmServiceClient.Execute(fetchRequest1)).EntityCollection;
                if (returnCollection.Entities != null && returnCollection.Entities.Any())
                {
                    EC.Entities.AddRange(returnCollection.Entities);
                }
                if (returnCollection.MoreRecords)
                {
                    pageNumber++;
                    pagingCookie = returnCollection.PagingCookie;
                }
                else
                {
                    break;
                }
            }
            return EC;
        }
    }

    public class UserModel
    {
        public int rowIndex { get; set; }

        public Guid userId { get; set; }

        public Guid businessUnitId { get; set; }

        public string userName { get; set; }

        public string status { get; set; }

        public string toAssociateRoles { get; set; }

        public string toDisassociateRoles { get; set; }

        public List<string> errorMessages { get; set; }

        public List<string> warnMessages { get; set; }

    }

    public class RoleModel
    {
        public Guid roleId { get; set; }

        public Guid businessUnitId { get; set; }

        public string roleName { get; set; }
    }

    public static class Enums
    {
        public enum HandleStatus
        {
            Validation_Failure,
            Handled_Successfully,
            Handled_Partially,
            Failed_to_Handle
        }
    }
}      
<appSettings>
    <add key="sourceFile" value="C:\ModifyUserRoles.xlsx" />
    <add key="rowCount" value="10" />
    <add key="colCount" value="3" />
    <add key="connectStr" value="AuthType=ClientSecret;url=https://thomasluodemo.crm5.dynamics.com/;ClientId=************;ClientSecret=*******" />
    <add key="CRMClientUrl" value="https://thomasluodemo.crm5.dynamics.com/main.aspx?appid=******" />
  </appSettings>      

繼續閱讀