问题
Business Process Error
System.ArgumentException: Illegal characters in path. at System.IO.Path.GetFileName(String path) at System.IO.File.InternalWriteAllBytes(String path, Byte[] bytes, Boolean checkHost)at RetrieveAttachments.RetrieveClass.Execute(IServiceProvider serviceProvider)
The code is as follows:
QueryExpression notes = new QueryExpression { EntityName = "annotation", ColumnSet = new ColumnSet("filename", "subject", "annotationid", "documentbody","mimetype") };
notes.Criteria.AddCondition("annotationid", ConditionOperator.Equal, annotationid);
EntityCollection NotesRetrieve = service.RetrieveMultiple(notes);
if (NotesRetrieve != null && NotesRetrieve.Entities.Count > 0)
{
foreach (var note in NotesRetrieve.Entities)
{
string fileName = note.GetAttributeValue<string>("filename");
//string fileType = note.GetAttributeValue<string>("mimetype");
FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.Write, "D:\\note");
string fileLocation = f+ fileName;
byte[] fileContent = Convert.FromBase64String(NotesRetrieve.Entities[0].Attributes["documentbody"].ToString());
System.IO.File.WriteAllBytes(fileLocation, fileContent);
}
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(ex.ToString());
}
回答1:
Santosh,
You can use following code to download attachments from Note entity in Dynamics CRM online.
code for .cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int choice;
CrmServiceClient crmConn = new CrmServiceClient(ConfigurationManager.ConnectionStrings["CRM"].ConnectionString);
IOrganizationService crmService = crmConn.OrganizationServiceProxy;
QueryExpression w_query = new QueryExpression { EntityName = "annotation", ColumnSet = new ColumnSet("filename","documentbody") };
EntityCollection w_account = crmService.RetrieveMultiple(w_query);
string name = "";
foreach (var count in w_account.Entities)
{
name = count.GetAttributeValue<string>("filename");
string doc_content = count.GetAttributeValue<string>("documentbody");
System.IO.FileStream wFile;
byte[] byteData = null;
if (name != null)
{
byte[] doc = Convert.FromBase64String(count.GetAttributeValue<string>("documentbody"));
byteData = doc;
wFile = new FileStream("D:\\attachments\\" + name, FileMode.Append);
wFile.Write(byteData, 0, byteData.Length);
wFile.Close();
}
}
Console.WriteLine("Please find all attachments in your local D: drive");
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
Code for .config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="CRM" connectionString="AuthType=Office365;Url=https://your_organization_url; Username=your_user_name; Password=Your_password" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.22.0.0" newVersion="2.22.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.22.0.0" newVersion="2.22.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
You just need to edit .config file code, this should work for you.
Note:you have to create C# console application and add required assemblies from Nuget.
回答2:
D:\note is a path of my machine where the file is downloaded.
If the above means you are trying to use a CRM plugin to write data to your local machine - as opposed to the CRM server - then this will never work.
The plugin runs on the CRM server so it wont have access to your client machine. E.g. when the plugin runs its looking for D:\note
on the CRM server - not on your personal computer.
If you want to download files to your local machine you are better of creating a console application that runs on your local machine.
In any case there is an example of attachment downloading here. filePath
in your case would be D:\note
(this still won't work in a plugin though).
public void ExportDocuments(IOrganizationService service, String filePath)
{
String fetch = @"<fetch mapping='logical' count='100' version='1.0'>
<entity name='annotation'>
<attribute name='filename' />
<attribute name='documentbody' />
<attribute name='mimetype' />
</entity>
</fetch>";
foreach (Entity e in service.RetrieveMultiple(new FetchExpression(fetch)))
{
if (!String.IsNullOrWhiteSpace(e.Attributes["documentbody"].ToString()))
{
byte[] data = Convert.FromBase64String(e.Attributes["documentbody"].ToString());
File.WriteAllBytes(filePath + e.Attributes["filename"].ToString(), data);
}
}
}
回答3:
This line is part of you culprit:
string fileLocation = f+ fileName;
This line is going to create an invalid file name because FileIOPermission.ToString()
returns an XML fragment.
Here is an example to fix that issue, clean the filename of illegal characters, and use Path.Combine
to build a valid file path.
string fileName = note.GetAttributeValue<string>("filename");
string cleanFileName = string.Empty;
foreach (var chr in fileName.ToCharArray().ToList())
{
if (!Path.GetInvalidFileNameChars().Contains(chr)) cleanFileName = cleanFileName + chr;
}
FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.Write, @"D:\note");
string fileLocation = Path.Combine(@"D:\note", cleanFileName);
byte[] fileContent = Convert.FromBase64String(NotesRetrieve.Entities[0].Attributes["documentbody"].ToString());
System.IO.File.WriteAllBytes(fileLocation, fileContent);
回答4:
CRM Online supports only Sandbox mode that means it isolates the code, You can't access outside environment in Sandbox mode which in your case is you local computer drive.
To achieve your goal you can create a console application as James Wood have said, that will write files into your local machine.
来源:https://stackoverflow.com/questions/39367657/getting-plug-in-path-error-while-downloading-attachments-from-note-entity-and-sa