Background:
Before last year, we could upload web resources in batches according to the directory WebResourceUtility. Yesterday, we found that it was useless. It was not very convenient to get the source code of WebResourceUtility and change it. I felt that the official code was too redundant and too long, which was not in line with my simple and rude idea. I just accidentally read a code of uploaded resources, so I just wrote a code by myself to upload w according to the directory Tools for EB resources.
Tools:
LinqPad 5
Microsoft Dynamics SDK 9.0
XrmToolBox
The old rules first show the renderings:
Files contained in directory
After creating web resources in batch, publish
Solution add existing resources
Code
1 //Microsoft Dynamics CRM Batch upload web Resources (Unofficial WebResourceUtility)Replace Icon 2 //Corresponding web Resources in mscrm File type of 3 enum FileTypes 4 { 5 HTML = 1, 6 CSS = 2, 7 JS = 3, 8 XML = 4, 9 PNG = 5, 10 JPG = 6, 11 GIF = 7, 12 XAP = 8, 13 XSL = 9, 14 ICO = 10, 15 SVG = 11, 16 RESX = 12 17 } 18 //Get all files in the directory according to the directory 19 Dictionary<string, int> GetFilesWithDir(string localPath) 20 { 21 Dictionary<string, int> dict = new Dictionary<string, int>(); 22 var typelist = Enum.GetNames(typeof(FileTypes)); 23 var dirs = Directory.GetDirectories(localPath); 24 //dirs.Dump(); 25 foreach (var dir in dirs) 26 { 27 var files = Directory.GetFiles(dir); 28 //files.Dump(); 29 foreach (var file in files) 30 { 31 var index = file.LastIndexOf(".");//.Dump(); 32 if (index == -1) continue; 33 var filetype = file.Substring(index + 1).ToUpper(); 34 if (typelist.Contains(filetype)) 35 { 36 dict.Add(file, 37 Enum.Parse(typeof(FileTypes), filetype).GetHashCode() 38 ); 39 } 40 41 } 42 } 43 return dict; 44 } 45 46 //Create or update web Resources 47 Guid CreateOrUpateFile2WebResoulse(IOrganizationService service, string filePath, FileTypes type, string rootPath, string serverPath = "new_/icons/") 48 { 49 Stopwatch sw = new Stopwatch(); 50 sw.Start(); 51 52 string fileName = filePath.Replace(rootPath, serverPath).Replace("\\", "/"); 53 54 var fileContent = File.ReadAllText(filePath); 55 56 fileName = Regex.Replace(fileName, @"[\u4e00-\u9fa5]", "").Replace("//", "/"); 57 58 //General text file 59 var customTypes = new int[] { 1, 2, 3, 4, 11, 12 }; 60 61 QueryExpression query = new QueryExpression("webresource") 62 { 63 ColumnSet = new ColumnSet(new string[] { "webresourceid" }), 64 Criteria = new FilterExpression(LogicalOperator.And) 65 }; 66 query.Criteria.AddCondition("name", ConditionOperator.Equal, new object[] { fileName }); 67 EntityCollection entitys = service.RetrieveMultiple(query); 68 69 Guid entityId; 70 71 Entity entity = new Entity("webresource"); 72 entity["content"] = customTypes.Contains(type.GetHashCode()) ? Convert.ToBase64String(Encoding.UTF8.GetBytes(fileContent.ToString())) : ImgToBase64String(filePath); 73 74 if (entitys.Entities.Count == 0) 75 { 76 entity["webresourcetype"] = new OptionSetValue(type.GetHashCode()); 77 entity["displayname"] = fileName; 78 entity["name"] = fileName; 79 entity["componentstate"] = new OptionSetValue(0); 80 entityId = service.Create(entity); 81 } 82 else 83 { 84 entity = entitys.Entities[0]; 85 service.Update(entity); 86 entityId = entity.Id; 87 } 88 sw.Stop(); 89 Console.WriteLine($"{fileName} Establish/Update succeeded! Time consuming:{sw.ElapsedMilliseconds} Millisecond."); 90 return entityId; 91 } 92 93 //Release web Resources 94 void publishWebResources(List<Guid> ids,IOrganizationService service) 95 { 96 Stopwatch sw=new Stopwatch(); 97 sw.Start(); 98 99 var sb=new StringBuilder(); 100 101 foreach (var id in ids) 102 { 103 sb.AppendLine($"\r\n<webresource>{id.ToString().ToUpper()}</webresource>\r\n"); 104 } 105 XElement element = XElement.Parse("<importexportxml>\r\n<webresources>"+sb.ToString()+"</webresources>\r\n</importexportxml>"); 106 PublishXmlRequest request = new PublishXmlRequest(); 107 request.ParameterXml = element.ToString(); 108 service.Execute(request); 109 sw.Stop(); 110 Console.WriteLine($"Batch release! Time consuming:{sw.ElapsedMilliseconds} Millisecond."); 111 112 } 113 void Main() 114 { 115 var service = Dynamic365.GetService(Envs.dev); 116 117 var rootPath = @"D:\Desktop\Icon 20191123\Icon 20191123\"; 118 var targetPath = @"new_/dyicon/"; 119 var dict=GetFilesWithDir(rootPath).Dump("Files contained in directory"); 120 121 var ids=new List<Guid>(); 122 123 foreach (var kv in dict) 124 { 125 Guid id; 126 try 127 { 128 id=CreateOrUpateFile2WebResoulse(service, kv.Key, (FileTypes)kv.Value, rootPath, targetPath); 129 130 } 131 catch(Exception ex) 132 { 133 ex.Dump(); 134 135 //Error report and execute again 136 id=CreateOrUpateFile2WebResoulse(service, kv.Key, (FileTypes)kv.Value, rootPath, targetPath); 137 } 138 ids.Add(id); 139 } 140 141 publishWebResources(ids,service); 142 }
Problem extension:
After the batch upload of web resources, you still need to manually select the web resources to replace the entity icon. Here you can find the iconator plug-in in the plug-in market of xrmtoolbox
Final effect drawing of entity modification Icon