ソリューションの操作

 

公開日: 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)

既存のソリューション コンポーネントの追加

このサンプルは、ソリューションに既存のソリューション コンポーネントを追加する方法を示します。

次のコードでは、AddSolutionComponentRequest を使用して、Account エンティティをアンマネージド ソリューションにソリューション コンポーネントとして追加します。


// 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 エンティティにクエリできます。

ImportJobId を使用すると、RetrieveFormattedImportJobResultsRequest メッセージを使用してインポート ログ ファイルをダウンロードすることもできます。

インポート ジョブ データの取得

以下のサンプルは、インポート ジョブ レコードおよび 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 という名前のグローバル オプション セットが 1 つ含まれていました。

<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 メッセージを使用して、特定のソリューション コンポーネントが削除されるのを防ぐ他のソリューション コンポーネントを識別します。 次のコード サンプルは、既知のグローバル オプションセットを使用して属性を検索します。 グローバル オプションセットを使用する属性は、グローバル オプションセットが削除されることを防ぎます。


// 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. All rights reserved. 著作権