Utiliser des solutions
Date de publication : janvier 2017
S’applique à : Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online
Cette rubrique présente les tâches de programmation spécifiques incluses dans Exemple : utiliser des solutions et Exemple : Rechercher les dépendances de solution.
Contenu de la rubrique
Créer un éditeur
Récupérer l’éditeur par défaut
Créer une solution
Récupérer une solution
Ajouter un nouveau composant de solution
Ajouter un composant de solution existant
Supprimer un composant de solution
Exporter ou empaqueter une solution
Installer ou mettre à niveau une solution
Suppression d'une solution
Détecter les dépendances de solutions
Créer un éditeur
Toutes les solutions requièrent un éditeur, représenté par l’entité Publisher. Une solution ne peut pas utiliser l’éditeur Microsoft Corporation, mais elle peut utiliser l’éditeur Default pour l’organisation ou un nouvel éditeur.
Un éditeur requiert les informations suivantes :
Un préfixe de personnalisation
Un nom unique
Un nom convivial
L’exemple suivant définit tout d’abord un éditeur, puis vérifie si l’éditeur existe déjà en fonction du nom unique. S’il existe déjà, le préfixe de personnalisation a pu être modifié. L’exemple cherche alors à capturer le préfixe de personnalisation actuel.PublisherId est également capturé afin que l’enregistrement d’éditeur puisse être supprimé. Si l’éditeur est introuvable, un nouvel éditeur est créé à l’aide de IOrganizationService. Méthode Create
//Define a new publisher
Publisher _crmSdkPublisher = new Publisher
{
UniqueName = "sdksamples",
FriendlyName = "Microsoft CRM SDK Samples",
SupportingWebsiteUrl = "https://msdn.microsoft.com/en-us/dynamics/crm/default.aspx",
CustomizationPrefix = "sample",
EMailAddress = "someone@microsoft.com",
Description = "This publisher was created with samples from the Microsoft Dynamics CRM SDK"
};
//Does publisher already exist?
QueryExpression querySDKSamplePublisher = new QueryExpression
{
EntityName = Publisher.EntityLogicalName,
ColumnSet = new ColumnSet("publisherid", "customizationprefix"),
Criteria = new FilterExpression()
};
querySDKSamplePublisher.Criteria.AddCondition("uniquename", ConditionOperator.Equal, _crmSdkPublisher.UniqueName);
EntityCollection querySDKSamplePublisherResults = _serviceProxy.RetrieveMultiple(querySDKSamplePublisher);
Publisher SDKSamplePublisherResults = null;
//If it already exists, use it
if (querySDKSamplePublisherResults.Entities.Count > 0)
{
SDKSamplePublisherResults = (Publisher)querySDKSamplePublisherResults.Entities[0];
_crmSdkPublisherId = (Guid)SDKSamplePublisherResults.PublisherId;
_customizationPrefix = SDKSamplePublisherResults.CustomizationPrefix;
}
//If it doesn't exist, create it
if (SDKSamplePublisherResults == null)
{
_crmSdkPublisherId = _serviceProxy.Create(_crmSdkPublisher);
Console.WriteLine(String.Format("Created publisher: {0}.", _crmSdkPublisher.FriendlyName));
_customizationPrefix = _crmSdkPublisher.CustomizationPrefix;
}
'Define a new publisher
Dim _crmSdkPublisher As Publisher =
New Publisher With {
.UniqueName = "sdksamples",
.FriendlyName = "Microsoft CRM SDK Samples",
.SupportingWebsiteUrl = "https://msdn.microsoft.com/en-us/dynamics/crm/default.aspx",
.CustomizationPrefix = "sample",
.EMailAddress = "someone@microsoft.com",
.Description = "This publisher was created with samples from the Microsoft Dynamics CRM SDK"
}
'Does publisher already exist?
Dim querySDKSamplePublisher As QueryExpression =
New QueryExpression With {
.EntityName = Publisher.EntityLogicalName,
.ColumnSet = New ColumnSet("publisherid", "customizationprefix"),
.Criteria = New FilterExpression()
}
querySDKSamplePublisher.Criteria.AddCondition("uniquename",
ConditionOperator.Equal,
_crmSdkPublisher.UniqueName)
Dim querySDKSamplePublisherResults As EntityCollection =
_serviceProxy.RetrieveMultiple(querySDKSamplePublisher)
Dim SDKSamplePublisherResults As Publisher = Nothing
'If it already exists, use it
If querySDKSamplePublisherResults.Entities.Count > 0 Then
SDKSamplePublisherResults = CType(querySDKSamplePublisherResults.Entities(0), Publisher)
_crmSdkPublisherId = CType(SDKSamplePublisherResults.PublisherId, Guid)
_customizationPrefix = SDKSamplePublisherResults.CustomizationPrefix
End If
'If it doesn't exist, create it
If SDKSamplePublisherResults Is Nothing Then
_crmSdkPublisherId = _serviceProxy.Create(_crmSdkPublisher)
Console.WriteLine(String.Format("Created publisher: {0}.", _crmSdkPublisher.FriendlyName))
_customizationPrefix = _crmSdkPublisher.CustomizationPrefix
End If
Récupérer l’éditeur par défaut
Cet exemple montre comment récupérer l’éditeur par défaut. L’éditeur par défaut contient une valeur GUID constante : d21aab71-79e7-11dd-8874-00188b01e34f.
// Retrieve the Default Publisher
//The default publisher has a constant GUID value;
Guid DefaultPublisherId = new Guid("{d21aab71-79e7-11dd-8874-00188b01e34f}");
Publisher DefaultPublisher = (Publisher)_serviceProxy.Retrieve(Publisher.EntityLogicalName, DefaultPublisherId, new ColumnSet(new string[] {"friendlyname" }));
EntityReference DefaultPublisherReference = new EntityReference
{
Id = DefaultPublisher.Id,
LogicalName = Publisher.EntityLogicalName,
Name = DefaultPublisher.FriendlyName
};
Console.WriteLine("Retrieved the {0}.", DefaultPublisherReference.Name);
' Retrieve the Default Publisher
'The default publisher has a constant GUID value;
Dim DefaultPublisherId As New Guid("{d21aab71-79e7-11dd-8874-00188b01e34f}")
Dim DefaultPublisher As Publisher =
CType(_serviceProxy.Retrieve(Publisher.EntityLogicalName,
DefaultPublisherId,
New ColumnSet(New String() {"friendlyname"})),
Publisher)
Dim DefaultPublisherReference As EntityReference = New EntityReference With {
.Id = DefaultPublisher.Id,
.LogicalName = Publisher.EntityLogicalName,
.Name = DefaultPublisher.FriendlyName
}
Console.WriteLine("Retrieved the {0}.", DefaultPublisherReference.Name)
Créer une solution
L’exemple suivant montre comment créer une solution non gérée à l’aide de l’éditeur Exemples du SDK de Microsoft Dynamics 365 créé dans Créer un éditeur.
Une solution requiert les informations suivantes :
Un éditeur
Un nom convivial
Un nom unique
Un numéro de version
La variable _crmSdkPublisherId est une valeur de GUID représentant la valeur publisherid.
Cet exemple vérifie si la solution existe déjà dans l’organisation en fonction du nom unique. Si la solution n’existe pas, elle est créée. La valeur SolutionId est capturée de sorte que la solution puisse être supprimée.
// Create a Solution
//Define a solution
Solution solution = new Solution
{
UniqueName = "samplesolution",
FriendlyName = "Sample Solution",
PublisherId = new EntityReference(Publisher.EntityLogicalName, _crmSdkPublisherId),
Description = "This solution was created by the WorkWithSolutions sample code in the Microsoft Dynamics CRM SDK samples.",
Version = "1.0"
};
//Check whether it already exists
QueryExpression queryCheckForSampleSolution = new QueryExpression
{
EntityName = Solution.EntityLogicalName,
ColumnSet = new ColumnSet(),
Criteria = new FilterExpression()
};
queryCheckForSampleSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, solution.UniqueName);
//Create the solution if it does not already exist.
EntityCollection querySampleSolutionResults = _serviceProxy.RetrieveMultiple(queryCheckForSampleSolution);
Solution SampleSolutionResults = null;
if (querySampleSolutionResults.Entities.Count > 0)
{
SampleSolutionResults = (Solution)querySampleSolutionResults.Entities[0];
_solutionsSampleSolutionId = (Guid)SampleSolutionResults.SolutionId;
}
if (SampleSolutionResults == null)
{
_solutionsSampleSolutionId = _serviceProxy.Create(solution);
}
' Create a Solution
'Define a solution
Dim solution As Solution =
New Solution With {
.UniqueName = "samplesolution",
.FriendlyName = "Sample Solution",
.PublisherId = New EntityReference(Publisher.EntityLogicalName, _crmSdkPublisherId),
.Description = "This solution was created by the WorkWithSolutions sample code in the Microsoft Dynamics CRM SDK samples.",
.Version = "1.0"
}
'Check whether it already exists
Dim queryCheckForSampleSolution As QueryExpression =
New QueryExpression With {
.EntityName = solution.EntityLogicalName,
.ColumnSet = New ColumnSet(),
.Criteria = New FilterExpression()
}
queryCheckForSampleSolution.Criteria.AddCondition("uniquename",
ConditionOperator.Equal,
solution.UniqueName)
'Create the solution if it does not already exist.
Dim querySampleSolutionResults As EntityCollection =
_serviceProxy.RetrieveMultiple(queryCheckForSampleSolution)
Dim SampleSolutionResults As Solution = Nothing
If querySampleSolutionResults.Entities.Count > 0 Then
SampleSolutionResults = CType(querySampleSolutionResults.Entities(0), Solution)
_solutionsSampleSolutionId = CType(SampleSolutionResults.SolutionId, Guid)
End If
If SampleSolutionResults Is Nothing Then
_solutionsSampleSolutionId = _serviceProxy.Create(solution)
End If
Récupérer une solution
Pour récupérer une solution en particulier, vous pouvez utiliser l’attribut UniqueName de la solution. Chaque organisation aura une solution par défaut avec une valeur de GUID constante : FD140AAF-4DF4-11DD-BD17-0019B9312238.
Cet exemple montre comment récupérer les données d’une solution avec le nom unique ”samplesolution”. Une solution portant ce nom est créée dans Créer une solution.
// Retrieve a solution
String solutionUniqueName = "samplesolution";
QueryExpression querySampleSolution = new QueryExpression
{
EntityName = Solution.EntityLogicalName,
ColumnSet = new ColumnSet(new string[] { "publisherid", "installedon", "version", "versionnumber", "friendlyname" }),
Criteria = new FilterExpression()
};
querySampleSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, solutionUniqueName);
Solution SampleSolution = (Solution)_serviceProxy.RetrieveMultiple(querySampleSolution).Entities[0];
' Retrieve a solution
Dim solutionUniqueName As String = "samplesolution"
Dim querySampleSolution As QueryExpression =
New QueryExpression With {
.EntityName = solution.EntityLogicalName,
.ColumnSet = New ColumnSet(New String() {"publisherid",
"installedon",
"version",
"versionnumber",
"friendlyname"}),
.Criteria = New FilterExpression()
}
querySampleSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, solutionUniqueName)
Dim SampleSolution As Solution =
CType(_serviceProxy.RetrieveMultiple(querySampleSolution).Entities(0), Solution)
Ajouter un nouveau composant de solution
Cet exemple montre comment créer un composant de solution associé à une solution spécifique. Si vous n’associez pas le composant de solution à une solution spécifique lors de sa création, il est uniquement ajouté à la solution par défaut et vous devrez l’ajouter à une solution manuellement ou à l’aide du code inclus dans Ajouter un composant de solution existant.
Ce code crée un groupe d’options global et l’ajoute à la solution avec un nom unique égal à _primarySolutionName.
OptionSetMetadata optionSetMetadata = new OptionSetMetadata()
{
Name = _globalOptionSetName,
DisplayName = new Label("Example Option Set", _languageCode),
IsGlobal = true,
OptionSetType = OptionSetType.Picklist,
Options =
{
new OptionMetadata(new Label("Option 1", _languageCode), 1),
new OptionMetadata(new Label("Option 2", _languageCode), 2)
}
};
CreateOptionSetRequest createOptionSetRequest = new CreateOptionSetRequest
{
OptionSet = optionSetMetadata
};
createOptionSetRequest.SolutionUniqueName = _primarySolutionName;
_serviceProxy.Execute(createOptionSetRequest);
Dim optionSetMetadata As New OptionSetMetadata() With {
.Name = _globalOptionSetName,
.DisplayName = New Label("Example Option Set", _languageCode),
.IsGlobal = True,
.OptionSetType = OptionSetType.Picklist
}
optionSetMetadata.Options.AddRange(
{
New OptionMetadata(New Label("Option 1", _languageCode), 1),
New OptionMetadata(New Label("Option 2", _languageCode), 2)
}
)
Dim createOptionSetRequest As CreateOptionSetRequest =
New CreateOptionSetRequest With {
.OptionSet = optionSetMetadata
}
createOptionSetRequest.SolutionUniqueName = _primarySolutionName
_serviceProxy.Execute(createOptionSetRequest)
Ajouter un composant de solution existant
Cet exemple montre comment ajouter un composant de solution existant à une solution.
Le code suivant utilise AddSolutionComponentRequest pour ajouter l’entité Account en tant que composant de solution à une solution non gérée.
// Add an existing Solution Component
//Add the Account entity to the solution
RetrieveEntityRequest retrieveForAddAccountRequest = new RetrieveEntityRequest()
{
LogicalName = Account.EntityLogicalName
};
RetrieveEntityResponse retrieveForAddAccountResponse = (RetrieveEntityResponse)_serviceProxy.Execute(retrieveForAddAccountRequest);
AddSolutionComponentRequest addReq = new AddSolutionComponentRequest()
{
ComponentType = (int)componenttype.Entity,
ComponentId = (Guid)retrieveForAddAccountResponse.EntityMetadata.MetadataId,
SolutionUniqueName = solution.UniqueName
};
_serviceProxy.Execute(addReq);
' Add an existing Solution Component
'Add the Account entity to the solution
Dim retrieveForAddAccountRequest As New RetrieveEntityRequest() With {
.LogicalName = Account.EntityLogicalName
}
Dim retrieveForAddAccountResponse As RetrieveEntityResponse =
CType(_serviceProxy.Execute(retrieveForAddAccountRequest),
RetrieveEntityResponse)
Dim addReq As New AddSolutionComponentRequest() With {
.ComponentType = componenttype.Entity,
.ComponentId = CType(retrieveForAddAccountResponse.EntityMetadata.MetadataId, Guid),
.SolutionUniqueName = solution.UniqueName
}
_serviceProxy.Execute(addReq)
Supprimer un composant de solution
Cet exemple montre comment supprimer un composant de solution d’une solution non gérée. Le code suivant utilise RemoveSolutionComponentRequest pour supprimer un composant de solution d’entité d’une solution non gérée.solution.UniqueName fait référence à la solution créée dans Créer une solution.
// Remove a Solution Component
//Remove the Account entity from the solution
RetrieveEntityRequest retrieveForRemoveAccountRequest = new RetrieveEntityRequest()
{
LogicalName = Account.EntityLogicalName
};
RetrieveEntityResponse retrieveForRemoveAccountResponse = (RetrieveEntityResponse)_serviceProxy.Execute(retrieveForRemoveAccountRequest);
RemoveSolutionComponentRequest removeReq = new RemoveSolutionComponentRequest()
{
ComponentId = (Guid)retrieveForRemoveAccountResponse.EntityMetadata.MetadataId,
ComponentType = (int)componenttype.Entity,
SolutionUniqueName = solution.UniqueName
};
_serviceProxy.Execute(removeReq);
' Remove a Solution Component
'Remove the Account entity from the solution
Dim retrieveForRemoveAccountRequest As New RetrieveEntityRequest() With {
.LogicalName = Account.EntityLogicalName
}
Dim retrieveForRemoveAccountResponse As RetrieveEntityResponse =
CType(_serviceProxy.Execute(retrieveForRemoveAccountRequest), RetrieveEntityResponse)
Dim removeReq As New RemoveSolutionComponentRequest() With {
.ComponentId = CType(retrieveForRemoveAccountResponse.EntityMetadata.MetadataId, Guid),
.ComponentType = componenttype.Entity,
.SolutionUniqueName = solution.UniqueName
}
_serviceProxy.Execute(removeReq)
Exporter ou empaqueter une solution
Cet exemple montre comment exporter une solution non gérée ou empaqueter une solution gérée. Le code utilise ExportSolutionRequest pour exporter un fichier compressé représentant une solution non gérée. La possibilité de créer une solution gérée est définie avec la propriété Managed. Cet exemple enregistre un fichier nommé samplesolution.zip dans le dossier c:\temp\.
// Export or package a solution
//Export an a solution
ExportSolutionRequest exportSolutionRequest = new ExportSolutionRequest();
exportSolutionRequest.Managed = false;
exportSolutionRequest.SolutionName = solution.UniqueName;
ExportSolutionResponse exportSolutionResponse = (ExportSolutionResponse)_serviceProxy.Execute(exportSolutionRequest);
byte[] exportXml = exportSolutionResponse.ExportSolutionFile;
string filename = solution.UniqueName + ".zip";
File.WriteAllBytes(outputDir + filename, exportXml);
Console.WriteLine("Solution exported to {0}.", outputDir + filename);
' Export or package a solution
'Export an a solution
Dim outputDir As String = "C:\temp\"
Dim exportSolutionRequest As New ExportSolutionRequest()
exportSolutionRequest.Managed = False
exportSolutionRequest.SolutionName = solution.UniqueName
Dim exportSolutionResponse As ExportSolutionResponse =
CType(_serviceProxy.Execute(exportSolutionRequest), ExportSolutionResponse)
Dim exportXml() As Byte = exportSolutionResponse.ExportSolutionFile
Dim filename As String = solution.UniqueName & ".zip"
File.WriteAllBytes(outputDir & filename, exportXml)
Console.WriteLine("Solution exported to {0}.", outputDir & filename)
Installer ou mettre à niveau une solution
Cet exemple montre comment installer ou mettre à niveau une solution à l’aide du message ImportSolutionRequest.
Vous pouvez utiliser l’entité ImportJob pour capturer des données sur la réussite de l’importation.
Cet exemple explique comment importer une solution sans suivre la réussite.
// Install or Upgrade a Solution
byte[] fileBytes = File.ReadAllBytes(ManagedSolutionLocation);
ImportSolutionRequest impSolReq = new ImportSolutionRequest()
{
CustomizationFile = fileBytes
};
_serviceProxy.Execute(impSolReq);
Console.WriteLine("Imported Solution from {0}", ManagedSolutionLocation);
' Install or Upgrade a Solution
Dim fileBytes() As Byte = File.ReadAllBytes(ManagedSolutionLocation)
Dim impSolReq As New ImportSolutionRequest() With {
.CustomizationFile = fileBytes
}
_serviceProxy.Execute(impSolReq)
Console.WriteLine("Imported Solution from {0}", ManagedSolutionLocation)
Suivi de la réussite de l’importation
Lorsque vous spécifiez ImportJobId pour ImportSolutionRequest, vous pouvez utiliser la valeur pour interroger l’entité ImportJob à propos du statut de l’importation.
ImportJobId peut également être utilisé pour télécharger un fichier journal à l’aide du message RetrieveFormattedImportJobResultsRequest.
Récupération des données de tâche d’importation
L’exemple suivant explique comment récupérer l’enregistrement de tâche d’importation et le contenu de l’attribut ImportJob.Data.
// Monitor import success
byte[] fileBytesWithMonitoring = File.ReadAllBytes(ManagedSolutionLocation);
ImportSolutionRequest impSolReqWithMonitoring = new ImportSolutionRequest()
{
CustomizationFile = fileBytes,
ImportJobId = Guid.NewGuid()
};
_serviceProxy.Execute(impSolReqWithMonitoring);
Console.WriteLine("Imported Solution with Monitoring from {0}", ManagedSolutionLocation);
ImportJob job = (ImportJob)_serviceProxy.Retrieve(ImportJob.EntityLogicalName, impSolReqWithMonitoring.ImportJobId, new ColumnSet(new System.String[] { "data", "solutionname" }));
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(job.Data);
String ImportedSolutionName = doc.SelectSingleNode("//solutionManifest/UniqueName").InnerText;
String SolutionImportResult = doc.SelectSingleNode("//solutionManifest/result/@result").Value;
Console.WriteLine("Report from the ImportJob data");
Console.WriteLine("Solution Unique name: {0}", ImportedSolutionName);
Console.WriteLine("Solution Import Result: {0}", SolutionImportResult);
Console.WriteLine("");
// This code displays the results for Global Option sets installed as part of a solution.
System.Xml.XmlNodeList optionSets = doc.SelectNodes("//optionSets/optionSet");
foreach (System.Xml.XmlNode node in optionSets)
{
string OptionSetName = node.Attributes["LocalizedName"].Value;
string result = node.FirstChild.Attributes["result"].Value;
if (result == "success")
{
Console.WriteLine("{0} result: {1}",OptionSetName, result);
}
else
{
string errorCode = node.FirstChild.Attributes["errorcode"].Value;
string errorText = node.FirstChild.Attributes["errortext"].Value;
Console.WriteLine("{0} result: {1} Code: {2} Description: {3}",OptionSetName, result, errorCode, errorText);
}
}
' Monitor import success
Dim fileBytesWithMonitoring() As Byte = File.ReadAllBytes(ManagedSolutionLocation)
Dim impSolReqWithMonitoring As New ImportSolutionRequest() With {
.CustomizationFile = fileBytes,
.ImportJobId = Guid.NewGuid()
}
_serviceProxy.Execute(impSolReqWithMonitoring)
Console.WriteLine("Imported Solution with Monitoring from {0}", ManagedSolutionLocation)
Dim job As ImportJob =
CType(_serviceProxy.Retrieve(ImportJob.EntityLogicalName,
impSolReqWithMonitoring.ImportJobId,
New ColumnSet(New String() {"data", "solutionname"})),
ImportJob)
Dim doc As New System.Xml.XmlDocument()
doc.LoadXml(job.Data)
Dim ImportedSolutionName As String = doc.SelectSingleNode("//solutionManifest/UniqueName").InnerText
Dim SolutionImportResult As String = doc.SelectSingleNode("//solutionManifest/result/@result").Value
Console.WriteLine("Report from the ImportJob data")
Console.WriteLine("Solution Unique name: {0}", ImportedSolutionName)
Console.WriteLine("Solution Import Result: {0}", SolutionImportResult)
Console.WriteLine("")
'This code displays the results for Global Option sets installed as part of a solution.
Dim optionSets As System.Xml.XmlNodeList = doc.SelectNodes("//optionSets/optionSet")
For Each node As System.Xml.XmlNode In optionSets
Dim OptionSetName As String = node.Attributes("LocalizedName").Value
Dim result As String = node.FirstChild.Attributes("result").Value
If result = "success" Then
Console.WriteLine("{0} result: {1}", OptionSetName, result)
Else
Dim errorCode As String = node.FirstChild.Attributes("errorcode").Value
Dim errorText As String = node.FirstChild.Attributes("errortext").Value
Console.WriteLine("{0} result: {1} Code: {2} Description: {3}", OptionSetName, result, errorCode, errorText)
End If
Next node
Le contenu de la propriété Data correspond à une chaîne représentant un fichier XML. L’exemple suivant a été capturé avec le code de cet exemple. Cette solution gérée contenait un groupe d’options global unique appelé sample_tempsampleglobaloptionsetname.
<importexportxml start="634224017519682730"
stop="634224017609764033"
progress="80"
processed="true">
<solutionManifests>
<solutionManifest languagecode="1033"
id="samplesolutionforImport"
LocalizedName="Sample Solution for Import"
processed="true">
<UniqueName>samplesolutionforImport</UniqueName>
<LocalizedNames>
<LocalizedName description="Sample Solution for Import"
languagecode="1033" />
</LocalizedNames>
<Descriptions>
<Description description="This solution was created by the WorkWithSolutions sample code in the Microsoft CRM SDK samples."
languagecode="1033" />
</Descriptions>
<Version>1.0</Version>
<Managed>1</Managed>
<Publisher>
<UniqueName>sdksamples</UniqueName>
<LocalizedNames>
<LocalizedName description="Microsoft CRM SDK Samples"
languagecode="1033" />
</LocalizedNames>
<Descriptions>
<Description description="This publisher was created with samples from the Microsoft CRM SDK"
languagecode="1033" />
</Descriptions>
<EMailAddress>someone@microsoft.com</EMailAddress>
<SupportingWebsiteUrl>https://msdn.microsoft.com/en-us/dynamics/crm/default.aspx</SupportingWebsiteUrl>
<Addresses>
<Address>
<City />
<Country />
<Line1 />
<Line2 />
<PostalCode />
<StateOrProvince />
<Telephone1 />
</Address>
</Addresses>
</Publisher>
<results />
<result result="success"
errorcode="0"
errortext=""
datetime="20:49:12.08"
datetimeticks="634224269520845122" />
</solutionManifest>
</solutionManifests>
<upgradeSolutionPackageInformation>
<upgradeRequired>0</upgradeRequired>
<upgradeValid>1</upgradeValid>
<fileVersion>5.0.9669.0</fileVersion>
<currentVersion>5.0.9669.0</currentVersion>
<fileSku>OnPremise</fileSku>
<currentSku>OnPremise</currentSku>
</upgradeSolutionPackageInformation>
<entities />
<nodes />
<settings />
<dashboards />
<securityroles />
<workflows />
<templates />
<optionSets>
<optionSet id="sample_tempsampleglobaloptionsetname"
LocalizedName="Example Option Set"
Description=""
processed="true">
<result result="success"
errorcode="0"
errortext=""
datetime="20:49:16.10"
datetimeticks="634224269561025400" />
</optionSet>
</optionSets>
<ConnectionRoles />
<SolutionPluginAssemblies />
<SdkMessageProcessingSteps />
<ServiceEndpoints />
<webResources />
<reports />
<FieldSecurityProfiles />
<languages>
<language>
<result result="success"
errorcode="0"
errortext=""
datetime="20:49:12.00"
datetimeticks="634224269520092986" />
</language>
</languages>
<entitySubhandlers />
<publishes>
<publish processed="false" />
</publishes>
<rootComponents>
<rootComponent processed="true">
<result result="success"
errorcode="0"
errortext=""
datetime="20:49:20.83"
datetimeticks="634224269608387238" />
</rootComponent>
</rootComponents>
<dependencies>
<dependency processed="true">
<result result="success"
errorcode="0"
errortext=""
datetime="20:49:20.97"
datetimeticks="634224269609715208" />
</dependency>
</dependencies>
</importexportxml>
Suppression d'une solution
Cet exemple montre comment supprimer une solution. Cet exemple explique comment récupérer une solution à l’aide de l’attribut uniquename de la solution, puis récupérer l’attribut solutionid dans les résultats. Utilisez solutionid avec IOrganizationService. Méthode Delete.
// Delete a solution
QueryExpression queryImportedSolution = new QueryExpression
{
EntityName = Solution.EntityLogicalName,
ColumnSet = new ColumnSet(new string[] { "solutionid", "friendlyname" }),
Criteria = new FilterExpression()
};
queryImportedSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, ImportedSolutionName);
Solution ImportedSolution = (Solution)_serviceProxy.RetrieveMultiple(queryImportedSolution).Entities[0];
_serviceProxy.Delete(Solution.EntityLogicalName, (Guid)ImportedSolution.SolutionId);
Console.WriteLine("Deleted the {0} solution.", ImportedSolution.FriendlyName);
' Delete a solution
Dim queryImportedSolution As QueryExpression =
New QueryExpression With {
.EntityName = solution.EntityLogicalName,
.ColumnSet = New ColumnSet(New String() {"solutionid", "friendlyname"}),
.Criteria = New FilterExpression()
}
queryImportedSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, ImportedSolutionName)
Dim ImportedSolution As Solution =
CType(_serviceProxy.RetrieveMultiple(queryImportedSolution).Entities(0), Solution)
_serviceProxy.Delete(solution.EntityLogicalName, CType(ImportedSolution.SolutionId, Guid))
Console.WriteLine("Deleted the {0} solution.", ImportedSolution.FriendlyName)
Détecter les dépendances de solutions
Cet exemple montre comment créer un rapport montrant les dépendances entre les composants de solution.
Ce code :
récupère tous les composants d’une solution ;
récupère toutes les dépendances de chaque composant ;
affiche un rapport décrivant la dépendance, pour chaque dépendance détectée.
// Grab all Solution Components for a solution.
QueryByAttribute componentQuery = new QueryByAttribute
{
EntityName = SolutionComponent.EntityLogicalName,
ColumnSet = new ColumnSet("componenttype", "objectid", "solutioncomponentid", "solutionid"),
Attributes = { "solutionid" },
// In your code, this value would probably come from another query.
Values = { _primarySolutionId }
};
IEnumerable<SolutionComponent> allComponents =
_serviceProxy.RetrieveMultiple(componentQuery).Entities.Cast<SolutionComponent>();
foreach (SolutionComponent component in allComponents)
{
// For each solution component, retrieve all dependencies for the component.
RetrieveDependentComponentsRequest dependentComponentsRequest =
new RetrieveDependentComponentsRequest
{
ComponentType = component.ComponentType.Value,
ObjectId = component.ObjectId.Value
};
RetrieveDependentComponentsResponse dependentComponentsResponse =
(RetrieveDependentComponentsResponse)_serviceProxy.Execute(dependentComponentsRequest);
// If there are no dependent components, we can ignore this component.
if (dependentComponentsResponse.EntityCollection.Entities.Any() == false)
continue;
// If there are dependencies upon this solution component, and the solution
// itself is managed, then you will be unable to delete the solution.
Console.WriteLine("Found {0} dependencies for Component {1} of type {2}",
dependentComponentsResponse.EntityCollection.Entities.Count,
component.ObjectId.Value,
component.ComponentType.Value
);
//A more complete report requires more code
foreach (Dependency d in dependentComponentsResponse.EntityCollection.Entities)
{
DependencyReport(d);
}
}
' Grab all Solution Components for a solution.
Dim componentQuery As QueryByAttribute =
New QueryByAttribute With {
.EntityName = SolutionComponent.EntityLogicalName,
.ColumnSet = New ColumnSet("componenttype", "objectid",
"solutioncomponentid", "solutionid")
}
componentQuery.Attributes.Add("solutionid")
componentQuery.Values.Add(_primarySolutionId)
' In your code, this value would probably come from another query.
Dim allComponents As IEnumerable(Of SolutionComponent) =
_serviceProxy.RetrieveMultiple(componentQuery).Entities.Cast(Of SolutionComponent)()
For Each component As SolutionComponent In allComponents
' For each solution component, retrieve all dependencies for the component.
Dim dependentComponentsRequest As RetrieveDependentComponentsRequest =
New RetrieveDependentComponentsRequest With {
.ComponentType = component.ComponentType.Value,
.ObjectId = component.ObjectId.Value
}
Dim dependentComponentsResponse As RetrieveDependentComponentsResponse =
CType(_serviceProxy.Execute(dependentComponentsRequest),
RetrieveDependentComponentsResponse)
' If there are no dependent components, we can ignore this component.
If dependentComponentsResponse.EntityCollection.Entities.Any() = False Then
Continue For
End If
' If there are dependencies upon this solution component, and the solution
' itself is managed, then you will be unable to delete the solution.
Console.WriteLine("Found {0} dependencies for Component {1} of type {2}",
dependentComponentsResponse.EntityCollection.Entities.Count,
component.ObjectId.Value,
component.ComponentType.Value)
'A more complete report requires more code
For Each d As Dependency In dependentComponentsResponse.EntityCollection.Entities
DependencyReport(d)
Next d
Next component
La méthode DependencyReport est utilisée dans l’exemple de code suivant.
Rapport de dépendance
La méthode DependencyReport fournit un message plus convivial à partir des informations disponibles dans la dépendance.
Notes
Dans cet exemple, la méthode est uniquement partiellement mise en œuvre. Elle affiche des messages uniquement pour les composants de solution d’attributs et de groupes d’options.
/// <summary>
/// Shows how to get a more friendly message based on information within the dependency
/// <param name="dependency">A Dependency returned from the RetrieveDependentComponents message</param>
/// </summary>
public void DependencyReport(Dependency dependency)
{
//These strings represent parameters for the message.
String dependentComponentName = "";
String dependentComponentTypeName = "";
String dependentComponentSolutionName = "";
String requiredComponentName = "";
String requiredComponentTypeName = "";
String requiredComponentSolutionName = "";
//The ComponentType global Option Set contains options for each possible component.
RetrieveOptionSetRequest componentTypeRequest = new RetrieveOptionSetRequest
{
Name = "componenttype"
};
RetrieveOptionSetResponse componentTypeResponse = (RetrieveOptionSetResponse)_serviceProxy.Execute(componentTypeRequest);
OptionSetMetadata componentTypeOptionSet = (OptionSetMetadata)componentTypeResponse.OptionSetMetadata;
// Match the Component type with the option value and get the label value of the option.
foreach (OptionMetadata opt in componentTypeOptionSet.Options)
{
if (dependency.DependentComponentType.Value == opt.Value)
{
dependentComponentTypeName = opt.Label.UserLocalizedLabel.Label;
}
if (dependency.RequiredComponentType.Value == opt.Value)
{
requiredComponentTypeName = opt.Label.UserLocalizedLabel.Label;
}
}
//The name or display name of the compoent is retrieved in different ways depending on the component type
dependentComponentName = getComponentName(dependency.DependentComponentType.Value, (Guid)dependency.DependentComponentObjectId);
requiredComponentName = getComponentName(dependency.RequiredComponentType.Value, (Guid)dependency.RequiredComponentObjectId);
// Retrieve the friendly name for the dependent solution.
Solution dependentSolution = (Solution)_serviceProxy.Retrieve
(
Solution.EntityLogicalName,
(Guid)dependency.DependentComponentBaseSolutionId,
new ColumnSet("friendlyname")
);
dependentComponentSolutionName = dependentSolution.FriendlyName;
// Retrieve the friendly name for the required solution.
Solution requiredSolution = (Solution)_serviceProxy.Retrieve
(
Solution.EntityLogicalName,
(Guid)dependency.RequiredComponentBaseSolutionId,
new ColumnSet("friendlyname")
);
requiredComponentSolutionName = requiredSolution.FriendlyName;
//Display the message
Console.WriteLine("The {0} {1} in the {2} depends on the {3} {4} in the {5} solution.",
dependentComponentName,
dependentComponentTypeName,
dependentComponentSolutionName,
requiredComponentName,
requiredComponentTypeName,
requiredComponentSolutionName);
}
''' <summary>
''' Shows how to get a more friendly message based on information within the dependency
''' <param name="dependency">A Dependency returned from the RetrieveDependentComponents message</param>
''' </summary>
Public Sub DependencyReport(ByVal dependency As Dependency)
'These strings represent parameters for the message.
Dim dependentComponentName As String = ""
Dim dependentComponentTypeName As String = ""
Dim dependentComponentSolutionName As String = ""
Dim requiredComponentName As String = ""
Dim requiredComponentTypeName As String = ""
Dim requiredComponentSolutionName As String = ""
'The ComponentType global Option Set contains options for each possible component.
Dim componentTypeRequest As RetrieveOptionSetRequest =
New RetrieveOptionSetRequest With {
.Name = "componenttype"
}
Dim componentTypeResponse As RetrieveOptionSetResponse =
CType(_serviceProxy.Execute(componentTypeRequest), RetrieveOptionSetResponse)
Dim componentTypeOptionSet As OptionSetMetadata =
CType(componentTypeResponse.OptionSetMetadata, OptionSetMetadata)
' Match the Component type with the option value and get the label value of the option.
For Each opt As OptionMetadata In componentTypeOptionSet.Options
If dependency.DependentComponentType.Value = opt.Value Then
dependentComponentTypeName = opt.Label.UserLocalizedLabel.Label
End If
If dependency.RequiredComponentType.Value = opt.Value Then
requiredComponentTypeName = opt.Label.UserLocalizedLabel.Label
End If
Next opt
'The name or display name of the compoent is retrieved in different ways depending on the component type
dependentComponentName = getComponentName(dependency.DependentComponentType.Value,
CType(dependency.DependentComponentObjectId,
Guid))
requiredComponentName = getComponentName(dependency.RequiredComponentType.Value,
CType(dependency.RequiredComponentObjectId,
Guid))
' Retrieve the friendly name for the dependent solution.
Dim dependentSolution As Solution =
CType(_serviceProxy.Retrieve(Solution.EntityLogicalName,
CType(dependency.DependentComponentBaseSolutionId, Guid),
New ColumnSet("friendlyname")),
Solution)
dependentComponentSolutionName = dependentSolution.FriendlyName
' Retrieve the friendly name for the required solution.
Dim requiredSolution As Solution =
CType(_serviceProxy.Retrieve(Solution.EntityLogicalName,
CType(dependency.RequiredComponentBaseSolutionId,
Guid),
New ColumnSet("friendlyname")),
Solution)
requiredComponentSolutionName = requiredSolution.FriendlyName
'Display the message
Console.WriteLine("The {0} {1} in the {2} depends on the {3} {4} in the {5} solution.",
dependentComponentName,
dependentComponentTypeName,
dependentComponentSolutionName,
requiredComponentName,
requiredComponentTypeName,
requiredComponentSolutionName)
End Sub
Détecter si un composant de solution peut être supprimé
Utilisez le message RetrieveDependenciesForDeleteRequest pour identifier les autres composants de solution qui pourraient empêcher un composant de solution donné d’être supprimé. L’exemple de code suivant recherche tous les attributs utilisant un groupe d’options global connu. Tout attribut utilisant le groupe d’options global empêcherait le groupe d’options défini d’être supprimé.
// Use the RetrieveOptionSetRequest message to retrieve
// a global option set by it's name.
RetrieveOptionSetRequest retrieveOptionSetRequest =
new RetrieveOptionSetRequest
{
Name = _globalOptionSetName
};
// Execute the request.
RetrieveOptionSetResponse retrieveOptionSetResponse =
(RetrieveOptionSetResponse)_serviceProxy.Execute(
retrieveOptionSetRequest);
_globalOptionSetId = retrieveOptionSetResponse.OptionSetMetadata.MetadataId;
if (_globalOptionSetId != null)
{
//Use the global OptionSet MetadataId with the appropriate componenttype
// to call RetrieveDependenciesForDeleteRequest
RetrieveDependenciesForDeleteRequest retrieveDependenciesForDeleteRequest = new RetrieveDependenciesForDeleteRequest
{
ComponentType = (int)componenttype.OptionSet,
ObjectId = (Guid)_globalOptionSetId
};
RetrieveDependenciesForDeleteResponse retrieveDependenciesForDeleteResponse =
(RetrieveDependenciesForDeleteResponse)_serviceProxy.Execute(retrieveDependenciesForDeleteRequest);
Console.WriteLine("");
foreach (Dependency d in retrieveDependenciesForDeleteResponse.EntityCollection.Entities)
{
if (d.DependentComponentType.Value == 2)//Just testing for Attributes
{
String attributeLabel = "";
RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest
{
MetadataId = (Guid)d.DependentComponentObjectId
};
RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)_serviceProxy.Execute(retrieveAttributeRequest);
AttributeMetadata attmet = retrieveAttributeResponse.AttributeMetadata;
attributeLabel = attmet.DisplayName.UserLocalizedLabel.Label;
Console.WriteLine("An {0} named {1} will prevent deleting the {2} global option set.",
(componenttype)d.DependentComponentType.Value,
attributeLabel,
_globalOptionSetName);
}
}
}
' Use the RetrieveOptionSetRequest message to retrieve
' a global option set by it's name.
Dim retrieveOptionSetRequest_Renamed As RetrieveOptionSetRequest =
New RetrieveOptionSetRequest With {.Name = _globalOptionSetName}
' Execute the request.
Dim retrieveOptionSetResponse_Renamed As RetrieveOptionSetResponse =
CType(_serviceProxy.Execute(retrieveOptionSetRequest_Renamed), RetrieveOptionSetResponse)
_globalOptionSetId = retrieveOptionSetResponse_Renamed.OptionSetMetadata.MetadataId
If _globalOptionSetId IsNot Nothing Then
'Use the global OptionSet MetadataId with the appropriate componenttype
' to call RetrieveDependenciesForDeleteRequest
Dim retrieveDependenciesForDeleteRequest_Renamed As RetrieveDependenciesForDeleteRequest =
New RetrieveDependenciesForDeleteRequest With
{
.ComponentType = CInt(Fix(componenttype.OptionSet)),
.ObjectId = CType(_globalOptionSetId, Guid)
}
Dim retrieveDependenciesForDeleteResponse_Renamed As RetrieveDependenciesForDeleteResponse =
CType(_serviceProxy.Execute(retrieveDependenciesForDeleteRequest_Renamed),
RetrieveDependenciesForDeleteResponse)
Console.WriteLine("")
For Each d As Dependency In retrieveDependenciesForDeleteResponse_Renamed _
.EntityCollection.Entities
If d.DependentComponentType.Value = 2 Then 'Just testing for Attributes
Dim attributeLabel As String = ""
Dim retrieveAttributeRequest_Renamed As RetrieveAttributeRequest =
New RetrieveAttributeRequest With
{
.MetadataId = CType(d.DependentComponentObjectId, Guid)
}
Dim retrieveAttributeResponse_Renamed As RetrieveAttributeResponse =
CType(_serviceProxy.Execute(retrieveAttributeRequest_Renamed),
RetrieveAttributeResponse)
Dim attmet As AttributeMetadata = retrieveAttributeResponse_Renamed.AttributeMetadata
attributeLabel = attmet.DisplayName.UserLocalizedLabel.Label
Console.WriteLine("An {0} named {1} will prevent deleting the {2} global option set.",
CType(d.DependentComponentType.Value, componenttype),
attributeLabel, _globalOptionSetName)
End If
Next d
End If
Voir aussi
Empaqueter et distribuer les extensions à l’aide des solutions
Présentation des solutions
Plan de développement de solutions
Suivi de dépendance pour les composants de solution
Créer, exporter ou importer une solution non gérée
Créer, installer et mettre à jour une solution gérée
Désinstaller ou supprimer une solution
Entités de solution
Exemple : utiliser des solutions
Exemple : Rechercher les dépendances de solution
Microsoft Dynamics 365
© 2017 Microsoft. Tous droits réservés. Copyright