Trabajar con soluciones
Publicado: enero de 2017
Se aplica a: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online
Este tema muestra las tareas de programación específicas incluidas en Ejemplo: trabajar con soluciones y Ejemplo: detectar las dependencias de solución.
En este tema
Crear un editor
Recuperar el editor predeterminado.
Crear una solución
Recuperar una solución
Agregar un nuevo componente de la solución
Agregar un componente de la solución existente
Quitar un componente de la solución
Exportar o empaquetar una solución
Instalar o actualizar una solución
Eliminar una solución
Detectar dependencias de soluciones
Crear un editor
Cada solución necesita un editor, representado por la entidad Publisher. Una solución no puede usar el editor de Microsoft Corporation pero puede usar el editor Default de la organización o un nuevo editor
Un editor requiere lo siguiente:
Un prefijo de personalización
Un nombre único
Un nombre descriptivo
El siguiente ejemplo primero define un editor y después se asegura de que el editor exista según el nombre único. Si ya existe, puede que el prefijo de personalización haya cambiado, por lo que este ejemplo busca capturar el prefijo actual de personalización. El PublisherId también se captura para poder eliminar el registro del editor. Si no encuentra el editor, se creará un nuevo editor mediante el método IOrganizationService. Método de 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
Recuperar el editor predeterminado.
Este ejemplo muestra cómo recuperar el editor predeterminado. El editor predeterminado tiene un valor de 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)
Crear una solución
El siguiente ejemplo muestra cómo crear una solución no administrada mediante los SDK de Microsoft Dynamics 365 Ejemplos creados en el editor Crear un editor.
Una solución requiere lo siguiente:
Un editor
Un nombre descriptivo
Un nombre único
Un número de versión
La variable _crmSdkPublisherId es un valor GUID que representa el valor de publisherid.
Este ejemplo comprueba si la solución ya existe en la organización en función del nombre único. Si la solución no existe, se crea. El valor de SolutionId se captura para que la solución se pueda eliminar.
// 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
Recuperar una solución
Para recuperar una solución específica puede usar el UniqueName de la solución. Cada organización tendrá una solución predeterminada con un valor de GUID constante: FD140AAF-4DF4-11DD-BD17-0019B9312238.
Este ejemplo muestra cómo recuperar los datos para una solución con el nombre único ”samplesolution”. Se creará una solución con este nombre en Crear una solución.
// 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)
Agregar un nuevo componente de la solución
Este ejemplo muestra cómo crear un componente de la solución que está asociado con una solución específica. Si no asocia el componente de la solución a una solución específica cuando se crea solo se agregará a la solución predeterminada y necesitará agregarlo a una solución manualmente o mediante el código incluido en Agregar un componente de la solución existente.
Este código crea un nuevo conjunto de opciones globales y lo agrega a la solución con un nombre único igual a _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)
Agregar un componente de la solución existente
Este ejemplo muestra cómo agregar un componente de la solución existente a una solución.
El siguiente código usa AddSolutionComponentRequest para agregar la entidad Account como componente de la solución a una solución no administrada.
// 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)
Quitar un componente de la solución
Este ejemplo muestra cómo quitar un componente de la solución de una solución no administrada. El siguiente código usa RemoveSolutionComponentRequest para quitar un componente de la solución de entidad de una solución no administrada. El solution.UniqueName hace referencia a la solución creada en Crear una solución.
// 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)
Exportar o empaquetar una solución
Este ejemplo muestra cómo exportar una solución no administrada o empaquetar una solución administrada. El código usa ExportSolutionRequest para exportar un archivo comprimido que representa una solución no administrada. La opción para crear una solución administrada se configura mediante la propiedad de Managed. Este ejemplo guarda un archivo llamado samplesolution.zip en la carpeta 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)
Instalar o actualizar una solución
Este ejemplo muestra cómo instalar o actualizar una solución con el mensaje de ImportSolutionRequest.
Puede usar la entidad ImportJob para capturar datos acerca del éxito de la importación.
El siguiente ejemplo muestra cómo importar una solución sin hacer seguimiento del éxito.
// 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)
Seguir el éxito de la importación
Cuando especifica un ImportJobId para ImportSolutionRequest, puede usar ese valor para consultar la entidad ImportJob sobre el estado de la importación.
ImportJobId también puede usarse para descargar un archivo de registro de importación mediante el mensaje de RetrieveFormattedImportJobResultsRequest.
Recuperar datos del trabajo de importación
El siguiente ejemplo muestra cómo recuperar el registro del trabajo de importación y el contenido del atributo de 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
El contenido de la propiedad de Data es una cadena que representa un archivo XML. Lo siguiente es un ejemplo capturado mediante el código en este ejemplo. Esta solución administrada contenía un único conjunto de opciones globales llamado 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>
Eliminar una solución
Este ejemplo muestra cómo eliminar una solución. El siguiente ejemplo muestra cómo recuperar una solución con el uniquename de la solución y después extraer el solutionid de los resultados. Use el solutionid con el método IOrganizationService.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)
Detectar dependencias de soluciones
Este ejemplo muestra cómo crear un informe que muestre las dependencias entre los componentes de la solución.
Este código:
Recuperará todos los componentes de una solución.
Recuperará todas las dependencias para cada componente.
Para cada dependencia encontrada mostrará un informe describiendo la dependencia.
// 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
El método DependencyReport se encuentra en el siguiente ejemplo de código.
Informe de dependencia
El método de DependencyReport proporciona un mensaje más fácil de usar basándose en la información encontrada en la dependencia.
Nota
En este ejemplo el método se implementa solo parcialmente. Puede enviar mensajes solo para los componentes de la solución de atributo y de conjunto de opciones.
/// <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
Detectar si un componente de la solución se puede eliminar
Use el mensaje de RetrieveDependenciesForDeleteRequest para identificar cualquier otro componente de la solución que pueda evitar que un determinado componente de la solución se elimine. El siguiente ejemplo de código busca atributos que utilicen un conjunto de opciones global conocido. Cualquier atributo que utilice el conjunto de opciones global evitará que el conjunto de opciones global se elimine.
// 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
Ver también
Empaquetar y distribuir las extensiones con soluciones
Introducción a soluciones
Planear el desarrollo de la solución
Seguimiento de las dependencias de los componentes de la solución
Crear, exportar o importar una solución no administrada
Crear, instalar y actualizar una solución administrada
Desinstalar o eliminar una solución
Entidades de solución
Ejemplo: trabajar con soluciones
Ejemplo: detectar las dependencias de solución
Microsoft Dynamics 365
© 2017 Microsoft. Todos los derechos reservados. Copyright