關注本人微信和易信公衆號: 微軟動態CRM專家羅勇 ,回覆240或者20161204可方便獲取本文,同時能夠在第一間獲得我發佈的最新的博文信息,follow me!個人網站是 www.luoyong.me 。安全
爲了便利於用戶及用戶權限審計,須要將系統的用戶及其角色、角色、角色權限等導出到Excel方便查看。我這裏就以這樣一個需求爲例來作一個簡單的控制檯應用程序來導出這些信息到Excel中。爲了方便查看結果,我這裏除了系統管理員,還創建幾個用戶,團隊來展現效果。服務器
這裏說一下如何爲Dynamics 365創建CRM用戶。咱們On-Premise的Dynamics CRM通常(注意是通常,由於你若是了SSO的話,用戶信息也能夠不存儲在CRM服務器所在AD中)須要先在CRM服務器所在的AD中增長用戶。而Dynamics 365則是須要先在 Office 365 門戶的用戶管理部分 增長用戶。打開的界面以下,點擊 管理員 這個磁貼。微信
點擊 添加用戶 連接添加一個用戶,我這裏本身建立密碼,不使用生成的隨機密碼。注意產品許可證要包括Dynamics 365的許可證,我這裏是 Dynamics 365 Plan 1 Enterprise Edition。app
而後咱們就能夠去Dynamics 365中的 設置 > 安全性 >用戶就能夠看到這個新建的用戶了。dom
而後就是設置業務部門,安全角色等,這裏和On-Premise版本的Dynamics CRM同樣,就不贅述了。ide
下面就是咱們的程序了,我建立一個控制檯應用程序,除了要添加對Dynamics 365相關DLL的引用外,還須要添加對Microsoft.Office.Interop.Excel的引用,添加引用的時候選擇 COM, 而後搜索excel就能夠找到。運行後面的程序還須要本機安裝了Excel。測試
Dynamics 365中的 安全角色 沒有導出功能,包括使用高級查找也是如此,因此咱們只有寫程序導出了。字體
全部使用的程序代碼以下:fetch
using Microsoft.Office.Interop.Excel;using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Client;using Microsoft.Xrm.Sdk.Messages;using Microsoft.Xrm.Sdk.Metadata;using Microsoft.Xrm.Sdk.Query;using Microsoft.Xrm.Tooling.Connector;using System;using System.Collections.Generic;using System.Configuration;using System.Drawing;using System.IO;using System.Linq;using System.ServiceModel;using System.ServiceModel.Description;using System.Text;using System.Xml;namespace LuoYongLab { class Program { static void Main(string[] args) { try { var crmSvc = new CrmServiceClient(ConfigurationManager.ConnectionStrings["CRM365"].ConnectionString); if (crmSvc.IsReady) { Console.WriteLine("導出安全角色開始"); var fetchXml = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'> <entity name='role'> <attribute name='name' /> <attribute name='businessunitid' /> <attribute name='roleid' /> <order attribute='name' descending='false' /> <filter type='and'> <condition attribute='parentroleid' operator='null' /> </filter> </entity> </fetch>"); EntityCollection ecRoles = crmSvc.RetrieveMultiple(new FetchExpression(fetchXml)); var excelApp = new Application(); excelApp.Visible = false; Workbook securityWorkbook = excelApp.Workbooks.Add(); Worksheet rolesWorksheet = (Worksheet)excelApp.ActiveSheet; rolesWorksheet.Name = "安全角色"; int row = 1; rolesWorksheet.Cells[1, 1] = "角色名稱"; rolesWorksheet.Cells[1, 2] = "業務部門"; rolesWorksheet.Cells[1, 3] = "角色ID"; //rolesWorksheet.Rows[1].Font.Bold = true;//字體加粗 row++; foreach (var roleEntity in ecRoles.Entities) { rolesWorksheet.Cells[row, 1] = roleEntity.GetAttributeValue<string>("name"); rolesWorksheet.Cells[row, 2] = roleEntity.GetAttributeValue<EntityReference>("businessunitid").Name; rolesWorksheet.Cells[row, 3] = roleEntity.GetAttributeValue<Guid>("roleid").ToString(); row++; } //rolesWorksheet.Columns[1].AutoFit();//自動列寬 rolesWorksheet.Range["A1", "C" + (row - 1)].AutoFormat(XlRangeAutoFormat.xlRangeAutoFormatColor1); Console.WriteLine("導出用戶及其安全角色開始"); fetchXml = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'> <entity name='systemuser'> <attribute name='fullname' /> <attribute name='businessunitid' /> <attribute name='systemuserid' /> <attribute name='domainname' /> <order attribute='fullname' descending='false' /> <filter type='and'> <condition attribute='isdisabled' operator='eq' value='0' /> <condition attribute='accessmode' operator='ne' value='3' /> </filter> </entity> </fetch>"; EntityCollection ecUsers = crmSvc.RetrieveMultiple(new FetchExpression(fetchXml)); Worksheet usersWorksheet = securityWorkbook.Worksheets.Add(); usersWorksheet.Name = "用戶"; row = 1; usersWorksheet.Cells[1, 1] = "用戶姓名"; usersWorksheet.Cells[1, 2] = "業務部門"; usersWorksheet.Cells[1, 3] = "用戶帳戶"; usersWorksheet.Cells[1, 4] = "用戶角色"; usersWorksheet.Cells[1, 5] = "用戶ID"; row++; foreach (var userEntity in ecUsers.Entities) { usersWorksheet.Cells[row, 1] = userEntity.GetAttributeValue<string>("fullname"); usersWorksheet.Cells[row, 2] = userEntity.GetAttributeValue<EntityReference>("businessunitid").Name; usersWorksheet.Cells[row, 3] = userEntity.GetAttributeValue<string>("domainname"); usersWorksheet.Cells[row, 4] = string.Join(",", GetUserRoles(crmSvc.OrganizationServiceProxy, userEntity.GetAttributeValue<Guid>("systemuserid")).Distinct()); usersWorksheet.Cells[row, 5] = userEntity.GetAttributeValue<Guid>("systemuserid").ToString(); row++; } usersWorksheet.Range["A1", "E" + (row - 1)].AutoFormat(XlRangeAutoFormat.xlRangeAutoFormatColor1); securityWorkbook.SaveAs(Filename: "CRMSecurities.xlsx", FileFormat: XlFileFormat.xlWorkbookDefault); securityWorkbook.Close(); excelApp.Quit(); } else { Console.WriteLine("鏈接CRM出錯:" + crmSvc.LastCrmError); } Console.WriteLine("程序運行完成!"); Console.ReadKey(); } catch (FaultException ex) { Console.WriteLine("程序出現異常:ex.Message=" + ex.Message); Console.ReadKey(); } } static IEnumerable<string> GetUserRoles(IOrganizationService service, Guid userId) { //首先獲取用戶直接授予的角色 string fetchXml = string.Format(@"<fetch version='1.0' output-format='xml-platform' 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); var userRolesDirect = service.RetrieveMultiple(new FetchExpression(fetchXml)).Entities.Select(x => x.GetAttributeValue<string>("name")); //找出用戶加入的全部負責人團隊 fetchXml = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'> <entity name='team'> <attribute name='teamid' /> <filter type='and'> <condition attribute='teamtype' operator='eq' value='0' /> </filter> <link-entity name='teammembership' from='teamid' to='teamid' visible='false' intersect='true'> <link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='ah'> <filter type='and'> <condition attribute='systemuserid' operator='eq' value='{0}' /> </filter> </link-entity> </link-entity> </entity> </fetch>", userId); var userTeams = service.RetrieveMultiple(new FetchExpression(fetchXml)).Entities.Select(x => x.GetAttributeValue<Guid>("teamid")); //團隊擁有的角色也是這個團隊全部用戶擁有的角色,因此還要加上這部分角色 var fetchXmlSb = new StringBuilder("<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>"); fetchXmlSb.Append("<entity name='role'>"); fetchXmlSb.Append("<attribute name='name' />"); fetchXmlSb.Append("<order attribute='name' descending='false' />"); fetchXmlSb.Append("<link-entity name='teamroles' from='roleid' to='roleid' visible='false' intersect='true'>"); fetchXmlSb.Append("<link-entity name='team' from='teamid' to='teamid' alias='ak'>"); fetchXmlSb.Append("<filter type='or'>"); foreach (var team in userTeams) { fetchXmlSb.Append(string.Format("<condition attribute='teamid' operator='eq' value='{0}' />", team)); } fetchXmlSb.Append("</filter>"); fetchXmlSb.Append("</link-entity>"); fetchXmlSb.Append("</link-entity>"); fetchXmlSb.Append("</entity>"); fetchXmlSb.Append("</fetch>"); var userRolesInTeam = service.RetrieveMultiple(new FetchExpression(fetchXmlSb.ToString())).Entities.Select(x => x.GetAttributeValue<string>("name")); return userRolesDirect.Concat(userRolesInTeam); } } }
獲得的結果以下,這個Excel有兩個Sheet,我分別截圖,個人測試結果是把用戶直接授予的角色和用戶加入團隊獲取的角色都拿到了。網站