共用方式為


使用解決方案

 

發行︰ 2017年1月

適用於: Dynamics 365 (online)、Dynamics 365 (on-premises)、Dynamics CRM 2016、Dynamics CRM Online

此主題顯示在 範例:使用解決方案範例:偵測解決方案相依性中的特定程式設計工作。

本主題內容

建立發行者

擷取預設發行者

建立解決方案

擷取解決方案

新增新的解決方案元件

新增現有的解決方案元件

移除解決方案元件

匯出或封裝解決方案

安裝或升級解決方案

刪除解決方案

偵測解決方案相依性

建立發行者

每個解決方案都需要發行者,由 Publisher 實體表示。 解決方案無法使用 Microsoft Corporation 發行者,而是為組織使用 Default 發行者或新發行者

發行者需要下列項目:

  • 自訂首碼

  • 唯一名稱

  • 易記名稱

下列範例先定義發行者,然後根據唯一名稱檢查發行者是否已存在。 如果已存在,自訂首碼可能已變更,所以此範例尋求擷取目前自訂首碼。PublisherId 也會擷取,讓發行者記錄會被刪除。 如果沒有發行者,會建立新發行者,使用 IOrganizationService.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

擷取預設發行者

此範例顯示如何擷取預設發行者。 預設發行者有常數 GUID 值: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)

建立解決方案

下列範例示範如何使用 建立發行者建立的 Microsoft Dynamics 365 SDK 範例發行者,建立未受管理的解決方案。

解決方案需要下列項目:

  • 發行者

  • 易記名稱

  • 唯一名稱

  • 版本號碼

變數 _crmSdkPublisherId 是指 publisherid 的 GUID 值。

根據唯一名稱,此範例檢查解決方案是否已存在於組織。 如果解決方案不存在,則會建立它。 擷取 SolutionId 值,因此解決方案可以刪除。


// 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

擷取解決方案

若要擷取特定解決方案,可以使用解決方案的 UniqueName。 每個組織的預設解決方案有常數 GUID 值:FD140AAF-4DF4-11DD-BD17-0019B9312238。

此範例顯示如何擷取具有唯一名稱 ”samplesolution” 的解決方案的資料。 系統就會在 建立解決方案 中建立此名稱的解決方案。


// 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)

新增新的解決方案元件

這個範例將說明如何建立與特定解決方案相關的解決方案元件。 如果建立時未關聯解決方案元件與特定解決方案,只會新增至預設解決方案,您必須手動新增至解決方案或使用 新增現有的解決方案元件 包含的程式碼。

此程式碼建立新的全域選項組,並將其新增至唯一名稱等於 _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)

新增現有的解決方案元件

此範例顯示如何將現有的解決方案元件新增至解決方案。

下列程式碼使用 AddSolutionComponentRequestAccount 實體新增至未受管理的解決方案中做為解決方案元件。


// 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)

移除解決方案元件

此範例顯示如何從未受管理的解決方案移除解決方案元件。 下列程式碼使用 RemoveSolutionComponentRequest,從未受管理的解決方案移除解決方案元件。solution.UniqueName 參照 建立解決方案 中建立的解決方案。


// 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)

匯出或封裝解決方案

此範例顯示如何匯出未受管理的解決方案或封裝受管理的解決方案。 程式碼使用 ExportSolutionRequest 匯出代表未受管理解決方案的壓縮檔。 使用 Managed 屬性,設定建立受管理解決方案的選項。 此範例儲存名稱為 samplesolution.zip 的檔案至 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)

安裝或升級解決方案

此範例顯示如何使用 ImportSolutionRequest 訊息安裝或升級解決方案。

您可以使用 ImportJob 實體取得關於匯入成功資料。

下列範例顯示如何匯入解決方案,而不追蹤成功。


// 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)

追蹤匯入成功

當您為 ImportSolutionRequest 指定 ImportJobId,您可以使用該值查詢 ImportJob 實體有關匯入的狀態。

使用 RetrieveFormattedImportJobResultsRequest 訊息,ImportJobId 也可用於下載匯入記錄檔。

擷取匯入工作資料

下列範例顯示如何擷取匯入工作記錄與 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

Data 屬性內容是指 XML 檔案的字串。 下列是使用此範例程式碼擷取的範例。 此受管理的解決方案包含單一全域選項組,名稱為 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>

刪除解決方案

此範例顯示如何刪除解決方案。下列範例顯示如何使用解決方案 uniquename 擷取解決方案,然後從結果擷取 solutionid。 使用 solutionidIOrganizationService.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)

偵測解決方案相依性

此範例顯示如何建立顯示解決方案元件相依性之間的報表。

此程式碼會:

  • 擷取解決方案的任何元件。

  • 擷取每個元件的任何相依性。

  • 針對每個相依性,顯示描述相依性的報表。



// 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

DependencyReport 方法是在下列程式碼範例中。

相依性報表

DependencyReport 方法根據相依性中的資訊,提供更好記的訊息。

注意

在此範例中,方法只部分實作。 它只顯示屬性和選項組解決方案元件的訊息。


   /// <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

偵測解決方案元件是否可以刪除

使用 RetrieveDependenciesForDeleteRequest 訊息識別可避免特定解決方案元件刪除的任何其他解決方案元件。 下列程式碼範例尋找所有使用已知全域 optionset 的屬性。 使用全域 optionset 的所有屬性可避免全域 optionset 刪除。


// 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

另請參閱

使用解決方案,封裝與發佈擴充功能
解決方案簡介
解決方案開發計劃
解決方案元件相依性追蹤
建立、匯出或匯入未受管理的解決方案
建立、安裝和更新受管理的解決方案
解除安裝或刪除解決方案
解決方案實體
範例:使用解決方案
範例:偵測解決方案相依性

Microsoft Dynamics 365

© 2017 Microsoft. 著作權所有,並保留一切權利。 著作權