Verwenden von Lösungen
Veröffentlicht: Januar 2017
Gilt für: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online
In diesem Thema werden die Programmieraufgaben in Beispiel: Verwenden von Lösungen und Beispiel: Erkennen von Lösungsabhängigkeiten erläutert.
In diesem Thema
Erstellen eines Herausgebers
Abrufen des Standardherausgebers
Erstellen einer Lösung
Abrufen einer Lösung
Hinzufügen einer neuen Lösungskomponente
Hinzufügen einer vorhandenen Lösungskomponente
Entfernen einer Lösungskomponente
Exportieren oder Packen einer Lösung
Installieren oder Aktualisieren einer Lösung
Löschen einer Lösung
Erkennen von Lösungsabhängigkeiten
Erstellen eines Herausgebers
Jede Lösung erfordert einen Herausgeber, repräsentiert durch die Publisher-Entität. Eine Lösung kann den Herausgeber Microsoft Corporation nicht verwenden sie kann aber den Herausgeber Default für die Organisation oder einen neuen Herausgeber verwenden
Ein Herausgeber erfordert Folgendes:
Ein Anpassungspräfix
Einen eindeutigen Namen
Einen Anzeigenamen
Das folgende Bespiel definiert zunächst einen Herausgeber und prüft dann aufgrund des eindeutigen Namens, ob dieser Herausgeber bereits vorhanden ist. Falls er bereits vorhanden ist, wurde möglicherweise das Anpassungspräfix geändert, dieses Beispiel versucht also, das aktuelle Anpassungspräfix zu erfassen. Die PublisherId wird ebenfalls erfasst, so dass der Herausgeberdatensatz gelöscht werden kann. Wenn der Herausgeber nicht gefunden wird, wird ein neuer Herausgeber mit der IOrganizationService-Methode erstellt.Create Methode
//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
Abrufen des Standardherausgebers
Dieses Beispiel zeigt, wie der Standardherausgeber abgerufen wird. Der Standardherausgeber hat einen konstanten GUID-Wert: 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)
Erstellen einer Lösung
Das folgende Beispiel zeigt, wie Sie eine nicht verwaltete Lösung mithilfe des Microsoft Dynamics 365 SDK Beispielherausgebers erstellen, der in Erstellen eines Herausgebers erstellt wurde.
Eine Lösung erfordert Folgendes:
Einen Herausgeber
Einen Anzeigenamen
Einen eindeutigen Namen
Eine Versionsnummer
Die Variable _crmSdkPublisherId ist ein GUID-Wert, der den publisherid-Wert repräsentiert.
Dieses Beispiel überprüft anhand des eindeutigen Namens, ob die Lösung in der Organisation bereits vorhanden ist. Wenn dies nicht der Fall ist, wird sie erstellt. Der SolutionId-Wert wird erfasst, so dass die Lösung gelöscht werden kann.
// 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
Abrufen einer Lösung
Um eine bestimmte Lösung abzurufen, können Sie den UniqueName der Lösung verwenden. Jede Organisation hat eine Standardlösung mit einem konstanten GUID-Wert: FD140AAF-4DF4-11DD-BD17-0019B9312238.
Dieses Beispiel zeigt, wie Daten für eine Lösung mit dem eindeutigen Namen ”samplesolution” abgerufen werden. Eine Lösung mit diesem Namen wird unter Erstellen einer Lösung erstellt.
// 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)
Hinzufügen einer neuen Lösungskomponente
Dieses Beispiel zeigt, wie eine Lösungskomponente erstellt wird, die mit einer bestimmten Lösung verbunden ist. Wenn Sie die Lösungskomponente nicht mit einer bestimmten Lösung verbinden, wenn sie erstellt wird, wird sie nur der Standardlösung hinzugefügt, und Sie mpüssen sie manuell einer Lösung hinzufügen, wobei Sie den Code verwenden, der in der Hinzufügen einer vorhandenen Lösungskomponente enthalten ist.
Dieser Code erstellt einen neuen globalen Optionssatz und fügt ihn der Lösung mit dem eindeutigen Namen _primarySolutionName hinzu.
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)
Hinzufügen einer vorhandenen Lösungskomponente
Dieses Beispiel zeigt, wie einer Lösungskomponente eine vorhandene Lösung hinzugefügt wird.
Der folgende Code verwendet die AddSolutionComponentRequest zum Hinzufügen der Account-Entität als Lösungskomponente zu einer nicht verwalteten Lösung.
// 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)
Entfernen einer Lösungskomponente
Dieses Beispiel zeigt, wie eine Lösungskomponente von einer nicht verwalteten Lösung entfernt wird. Der folgende Code verwendet die RemoveSolutionComponentRequest zum Entfernen einer Entitätslösungskomponente von einer nicht verwalteten Lösung. Der solution.UniqueName verweist auf die in Erstellen einer Lösung erstellte Lösung.
// 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)
Exportieren oder Packen einer Lösung
Dieses Beispiel zeigt, wie eine nicht verwaltete Lösung exportiert oder eine verwaltete Lösung gepackt wird. Der Code verwendet ExportSolutionRequest, um eine komprimierte Datei zu exportieren, die eine nicht verwalte Lösung repräsentiert. Die Option zur Erstellung einer verwalteten Lösung wird mit der Managed-Eigenschaft festgelegt. In diesem Beispiel wird eine Datei mit dem Namen samplesolution.zip im c:\temp\-Ordner gespeichert.
// 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)
Installieren oder Aktualisieren einer Lösung
Dieses Beispiel veranschaulicht, wie Sie mithilfe der Meldung ImportSolutionRequest eine Lösung installieren oder aktualisieren.
Mit der ImportJob-Entität können Sie Daten zum Erfolg des Imports erfassen.
Das folgende Beispiel zeigt, wie Sie eine Lösung importieren, ohne den Erfolg nachzuverfolgen.
// 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)
Nachverfolgen des Importerfolgs
Wenn Sie eine ImportJobId für die ImportSolutionRequest angegeben haben, können Sie diesen Wert verwenden, um ImportJob nach dem Status des Imports abzufragen.
Die ImportJobId kann auch für den Download einer Importprotokolldatei mit der RetrieveFormattedImportJobResultsRequest-Meldung verwendet werden.
Abrufen von Importauftragsdaten
Das folgende Beispiel zeigt, wie Sie den Datensatz für den Importauftrag und den Inhalt des ImportJob.Data-Attributs abrufen.
// 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
Der Inhalt der Eigenschaft Data eine Zeichenfolge, die eine XML-Datei repräsentiert. Im Folgenden finden Sie ein Beispiel, das mithilfe des Codes in diesem Beispiel erfasst wurde. Diese verwaltete Lösung enthielt einen einzelnen globalen Optionssatz mit dem Namen 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>
Löschen einer Lösung
Dieses Beispiel zeigt, wie Sie eine Lösung löschen. Das folgende Beispiel zeigt, wie Sie eine Lösung mit der Lösung uniquename abrufen und dann die solutionid aus den Ergebnissen extrahieren. Verwenden Sie die solutionid mit der IOrganizationService-Methode.Delete-Methode.
// 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)
Erkennen von Lösungsabhängigkeiten
Dieses Beispiel zeigt, wie Sie einen Bericht erstellen, der die Abhängigkeiten zwischen Lösungskomponenten zeigt.
Dieser Code leistet Folgendes:
Abrufen aller Komponenten für eine Lösung.
Abrufen aller Abhängigkeiten für jede Komponente.
Für jede gefundene Abhängigkeit wird ein bericht angezeigt, der die Abhängigkeit beschreibt.
// 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
Die DependencyReport-Methode befindet sich im folgenden Codebeispiel.
Abhängigkeitsbericht
Die Methode DependencyReport bietet eine benutzerfreundlichere Nachricht, basierend auf den Informationen, die innerhalb der Abhängigkeit gefunden werden.
Hinweis
In diesem Beispiel wird die Methode nur teilweise implementiert. Sie kann Nachrichten nur für Attribut- und Optionssatzlösungskomponenten anzeigen.
/// <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
Erkennen, ob eine Lösungskomponenten gelöscht werden kann
Verwenden Sie die RetrieveDependenciesForDeleteRequest-Meldung, um andere Lösungskomponenten zu identifizieren, die die Löschung einer bestimmten Lösungskomponente verhindern können. Das folgende Codebeispiel sucht nach Attributen, die einen bekannten globalen Optionssatz verwenden. Jedes Attribut, das den globalen Optionssatz verwendet, verhindert das Löschen des globalen Optionssatzes.
// 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
Siehe auch
Packen und Verteilen von Erweiterungen mithilfe von Lösungen
Einführung in Lösungen
Planen einer Lösungsentwicklung
Abhängigkeitsnachverfolgung für Lösungskomponenten
Erstellen, Exportieren oder Importieren einer nicht verwalteten Lösung
Eine verwaltete Lösung erstellen, installieren und aktualisieren
Deinstallieren oder Löschen einer Lösung
Lösungsentitäten
Beispiel: Verwenden von Lösungen
Beispiel: Erkennen von Lösungsabhängigkeiten
Microsoft Dynamics 365
© 2017 Microsoft. Alle Rechte vorbehalten. Copyright