

のバージョン 4 (V4) AWS SDK for .NET がリリースされました。

重要な変更とアプリケーションの移行については、[「移行トピック](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html)」を参照してください。

 [https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html)

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# のガイド付きコード例 AWS SDK for .NET
<a name="tutorials-examples"></a>

以下のセクションにはコード例が含まれ、その例に関するガイダンスを提供します。これらは、 を使用して AWS サービス AWS SDK for .NET を操作する方法を学ぶのに役立ちます。その他のコード例については、「[コードの例](csharp_code_examples.md)」を参照してください。

**注記**  
の V3 に固有のコード例 AWS SDK for .NET も利用できます。それらを見つけるには、 AWS SDK for .NET 「(V3) デベロッパーガイド」の[「ガイダンスを含むコード例](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/tutorials-examples.html)」と[「コード例](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/csharp_code_examples.html)」を参照してください。ただし、SDK (最新バージョン) の V3-specificコード例を使用する場合は、 の情報に従って調整する必要がある場合があります[バージョン 4 への移行](net-dg-v4.md)。 V4 

を初めて使用する場合は AWS SDK for .NET、まず[シンプルなアプリケーションの作成](quick-start.md)トピックを確認してください。SDK についてわかりやすく説明しています。

開始する前に、[環境をセットアップ](net-dg-config.md)し、[プロジェクトを設定した](configuring-the-sdk.md)ことを確認してください。また、「[SDK の使用](net-dg-sdk-features.md)」の情報を確認してください。

**Topics**
+ [CloudFormation](cloudformation-apis-intro.md)
+ [Amazon Cognito](cognito-apis-intro.md)
+ [DynamoDB](dynamodb-intro.md)
+ [Amazon EC2](ec2-apis-intro.md)
+ [IAM](iam-apis-intro.md)
+ [Amazon S3](s3-apis-intro.md)
+ [Amazon SNS](sns-apis-intro.md)
+ [Amazon SQS](sqs-apis-intro.md)

# CloudFormation を使用した へのアクセス AWS SDK for .NET
<a name="cloudformation-apis-intro"></a>

は[AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/)、 AWS インフラストラクチャのデプロイを予測どおりに繰り返し作成およびプロビジョニングする AWS SDK for .NET をサポートします。

## API
<a name="w2aac19c15c15b5"></a>

 AWS SDK for .NET はAPIs を提供します。 CloudFormation APIs を使用すると、テンプレートやスタックなどの CloudFormation 機能を操作できます。このセクションでは、これらの API を操作する際に活用できるパターンを示すいくつかの例を紹介します。API の完全なセットを確認するには、[AWS SDK for .NET API リファレンス](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)を参照してください(「Amazon.CloudFormation」までスクロールします)。

 AWS CloudFormation APIs は [AWSSDK.CloudFormation ](https://www.nuget.org/packages/AWSSDK.CloudFormation/)パッケージによって提供されます。

## 前提条件
<a name="w2aac19c15c15b7"></a>

開始する前に、[環境をセットアップ](net-dg-config.md)し、[プロジェクトを設定した](configuring-the-sdk.md)ことを確認してください。また、「[SDK の使用](net-dg-sdk-features.md)」の情報を確認してください。

## トピック
<a name="w2aac19c15c15b9"></a>

**Topics**
+ [API](#w2aac19c15c15b5)
+ [前提条件](#w2aac19c15c15b7)
+ [トピック](#w2aac19c15c15b9)
+ [AWS リソースの一覧表示](cfn-list-resources.md)

# を使用した AWS リソースの一覧表示 AWS CloudFormation
<a name="cfn-list-resources"></a>

この例では、 AWS SDK for .NET を使用して CloudFormation スタック内のリソースを一覧表示する方法を示します。この例では、低レベル API を使用します。アプリケーションは引数を取らず、ユーザーの認証情報にアクセスできるすべてのスタックの情報を単に収集して、それらのスタックに関する情報を表示します。

## SDK リファレンス
<a name="w2aac19c15c15c13b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.CloudFormation](https://www.nuget.org/packages/AWSSDK.CloudFormation/)

プログラミング要素:
+ 名前空間 [Amazon.CloudFormation](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/NCloudFormation.html)

  クラス [AmazonCloudFormationClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TCloudFormationClient.html)
+ 名前空間 [Amazon.CloudFormation.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/NCloudFormationModel.html)

  クラス [ICloudFormationPaginatorFactory.DescribeStacks](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/MICloudFormationPaginatorFactoryDescribeStacksDescribeStacksRequest.html)

  クラス [DescribeStackResourcesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TDescribeStackResourcesRequest.html)

  クラス [DescribeStackResourcesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TDescribeStackResourcesResponse.html)

  クラス [Stack](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TStack.html)

  クラス [StackResource](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TStackResource.html)

  クラス [Tag](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TTag.html)

```
using Amazon.CloudFormation;
using Amazon.CloudFormation.Model;
using Amazon.Runtime;

namespace CloudFormationActions;

public static class HelloCloudFormation
{
    public static IAmazonCloudFormation _amazonCloudFormation;

    static async Task Main(string[] args)
    {
        // Create the CloudFormation client
        _amazonCloudFormation = new AmazonCloudFormationClient();
        Console.WriteLine($"\nIn Region: {_amazonCloudFormation.Config.RegionEndpoint}");

        // List the resources for each stack
        await ListResources();
    }

    /// <summary>
    /// Method to list stack resources and other information.
    /// </summary>
    /// <returns>True if successful.</returns>
    public static async Task<bool> ListResources()
    {
        try
        {
            Console.WriteLine("Getting CloudFormation stack information...");

            // Get all stacks using the stack paginator.
            var paginatorForDescribeStacks =
                _amazonCloudFormation.Paginators.DescribeStacks(
                    new DescribeStacksRequest());
            await foreach (Stack stack in paginatorForDescribeStacks.Stacks)
            {
                // Basic information for each stack
                Console.WriteLine("\n------------------------------------------------");
                Console.WriteLine($"\nStack: {stack.StackName}");
                Console.WriteLine($"  Status: {stack.StackStatus.Value}");
                Console.WriteLine($"  Created: {stack.CreationTime}");

                // The tags of each stack (etc.)
                if (stack.Tags.Count > 0)
                {
                    Console.WriteLine("  Tags:");
                    foreach (Tag tag in stack.Tags)
                        Console.WriteLine($"    {tag.Key}, {tag.Value}");
                }

                // The resources of each stack
                DescribeStackResourcesResponse responseDescribeResources =
                    await _amazonCloudFormation.DescribeStackResourcesAsync(
                        new DescribeStackResourcesRequest
                        {
                            StackName = stack.StackName
                        });
                if (responseDescribeResources.StackResources.Count > 0)
                {
                    Console.WriteLine("  Resources:");
                    foreach (StackResource resource in responseDescribeResources
                                 .StackResources)
                        Console.WriteLine(
                            $"    {resource.LogicalResourceId}: {resource.ResourceStatus}");
                }
            }

            Console.WriteLine("\n------------------------------------------------");
            return true;
        }
        catch (AmazonCloudFormationException ex)
        {
            Console.WriteLine("Unable to get stack information:\n" + ex.Message);
            return false;
        }
        catch (AmazonServiceException ex)
        {
            if (ex.Message.Contains("Unable to get IAM security credentials"))
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("If you are usnig SSO, be sure to install" +
                                  " the AWSSDK.SSO and AWSSDK.SSOOIDC packages.");
            }
            else
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            return false;
        }
        catch (ArgumentNullException ex)
        {
            if (ex.Message.Contains("Options property cannot be empty: ClientName"))
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("If you are using SSO, have you logged in?");
            }
            else
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            return false;
        }
    }
```

# Amazon Cognito を使用したユーザー認証
<a name="cognito-apis-intro"></a>

**注記**  
このトピックの情報は、.NET Framework および AWS SDK for .NET バージョン 3.3 以前のプロジェクトに固有のものです。

Amazon Cognito Identity を使用すると、ユーザーの一意の ID を作成し、Amazon S3 や Amazon DynamoDB などの AWS リソースへの安全なアクセスのために認証できます。Amazon Cognito ID では、公開 ID プロバイダー (Amazon、Facebook、Twitter/Digits、Google、あるいは OpenID Connect と互換性のあるプロバイダーなど) および未認証 ID がサポートされています。また Cognito では、[デベロッパーが認証した ID](https://aws.amazon.com/blogs/mobile/amazon-cognito-announcing-developer-authenticated-identities/) もサポートされており、Amazon Cognito Sync を使用したユーザーデータの同期と AWS リソースへのアクセスを活用しながら、独自のバックエンド認証プロセスを通じてユーザー登録や認証ができます。

[Amazon Cognito](https://aws.amazon.com/cognito/) の詳細については、[Amazon Cognito デベロッパーガイド](https://docs.aws.amazon.com/cognito/latest/developerguide/) を参照してください。

以下のコード例では、Amazon Cognito ID を簡単に使用する方法を示しています。[認証情報プロバイダー](cognito-creds-provider.md) の例では、ユーザー ID を作成して認証する方法を示しています。[CognitoAuthentication 拡張ライブラリ](cognito-authentication-extension.md) の例では、CognitoAuthentication 拡張ライブラリを使用して Amazon Cognito ユーザープールの認証を行う方法を示しています。

**Topics**
+ [認証情報プロバイダー](cognito-creds-provider.md)
+ [CognitoAuthentication 拡張ライブラリ](cognito-authentication-extension.md)

# Amazon Cognito 認証情報プロバイダー
<a name="cognito-creds-provider"></a>

**注記**  
このトピックの情報は、.NET Framework および AWS SDK for .NET バージョン 3.3 以前のプロジェクトに固有のものです。

 `Amazon.CognitoIdentity.CognitoAWSCredentials`[AWSSDK.CognitoIdentity](https://www.nuget.org/packages/AWSSDK.CognitoIdentity/) NuGet パッケージにある は、Amazon Cognito と AWS Security Token Service (AWS STS) を使用して AWS 呼び出しを行う認証情報を取得する認証情報オブジェクトです。

`CognitoAWSCredentials` の設定での最初のステップは「ID プール」を作成することです。(アイデンティティプールとは、お客様のアカウントに固有のユーザー ID 情報のストアです。) 情報はクライアントプラットフォーム、デバイス、およびオペレーティングシステム間で取得可能です。これにより、ユーザーが電話でアプリの使用を開始して、後でタブレットに切り替えた場合でも、保持されたアプリ情報はそのユーザーに対して引き続き利用可能になります。Amazon Cognito コンソールから新しい ID プールを作成できます。コンソールを使用している場合は、必要なその他の情報も提供します。
+ アカウント番号 - 123456789012 などの、アカウントに一意な 12 桁の数字。
+ 認証されていないロール ARN - 認証されていないユーザーが引き受けるロール。たとえば、このロールは、データへの読み取り専用アクセス許可を提供できます。
+ 認証されたロール ARN - 認証されたユーザーが引き受けるロール。このロールは、データへのより広範なアクセス許可を提供できます。

## CognitoAWSCredentials をセットアップする
<a name="set-up-cognitoawscredentials"></a>

次のコード例では、認証されていないユーザーとして Amazon S3 を呼び出すことを可能にする `CognitoAWSCredentials` のセットアップ方法を示しています。これにより、ユーザーを認証するのに必要な最小量のデータだけで呼び出すことができます。ユーザーアクセス許可はロールによって制御されるため、必要に応じてアクセスを設定することもできます。

```
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    accountId,        // Account number
    identityPoolId,   // Identity pool ID
    unAuthRoleArn,    // Role for unauthenticated users
    null,             // Role for authenticated users, not set
    region);
using (var s3Client = new AmazonS3Client(credentials))
{
    s3Client.ListBuckets();
}
```

## 認証されていないユーザー AWS として を使用する
<a name="use-aws-as-an-unauthenticated-user"></a>

次のコード例は、認証されていないユーザー AWS として の使用を開始し、Facebook を介して認証し、Facebook 認証情報を使用するように認証情報を更新する方法を示しています。この方法を使用すると、認証されたロールを通じて、認証されたユーザーにさまざまな機能を付与できるようになります。たとえば、ユーザーが匿名でコンテンツを表示することを許可するものの、1 つ以上の設定済みプロバイダーでログオンしている場合に投稿を許可する電話アプリケーションがあります。

```
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    accountId, identityPoolId,
    unAuthRoleArn,    // Role for unauthenticated users
    authRoleArn,      // Role for authenticated users
    region);
using (var s3Client = new AmazonS3Client(credentials))
{
    // Initial use will be unauthenticated
    s3Client.ListBuckets();

    // Authenticate user through Facebook
    string facebookToken = GetFacebookAuthToken();

    // Add Facebook login to credentials. This clears the current AWS credentials
    // and retrieves new AWS credentials using the authenticated role.
    credentials.AddLogin("graph.facebook.com", facebookAccessToken);

    // This call is performed with the authenticated role and credentials
    s3Client.ListBuckets();
}
```

`CognitoAWSCredentials` オブジェクトは、 AWS SDK for .NETの一部である `AmazonCognitoSyncClient` で使用した場合、さらに多くの機能を提供します。`AmazonCognitoSyncClient` と `CognitoAWSCredentials` の両方を使用している場合は、`AmazonCognitoSyncClient` を使用して呼び出しを行うときに `IdentityPoolId` と `IdentityId` のプロパティを指定する必要はありません。これらのプロパティは `CognitoAWSCredentials` から自動的に入力されます。次のコード例では、これとともに、`IdentityId` の `CognitoAWSCredentials` が変更されるたびに通知するイベントを示します。`IdentityId` は、たとえば、認証されていないユーザーから認証されたユーザーに変更する際など、場合によって変更されます。

```
CognitoAWSCredentials credentials = GetCognitoAWSCredentials();

// Log identity changes
credentials.IdentityChangedEvent += (sender, args) =>
{
    Console.WriteLine("Identity changed: [{0}] => [{1}]", args.OldIdentityId, args.NewIdentityId);
};

using (var syncClient = new AmazonCognitoSyncClient(credentials))
{
    var result = syncClient.ListRecords(new ListRecordsRequest
    {
        DatasetName = datasetName
        // No need to specify these properties
        //IdentityId = "...",
        //IdentityPoolId = "..."        
    });
}
```

# Amazon CognitoAuthentication 拡張ライブラリの例
<a name="cognito-authentication-extension"></a>

**注記**  
このトピックの情報は、.NET Framework および AWS SDK for .NET バージョン 3.3 以前のプロジェクトに固有のものです。

CognitoAuthentication 拡張ライブラリは、.NET Core および Xamarin デベロッパーによる Amazon Cognito ユーザープールの認証プロセスを簡素化するもので、[Amazon.Extensions.CognitoAuthentication](https://www.nuget.org/packages/Amazon.Extensions.CognitoAuthentication/) NuGet パッケージで提供されています。このライブラリは、Amazon Cognito ID プロバイダー API に基づいて構築されており、ユーザー認証 API コールを作成して送信します。

## CognitoAuthentication 拡張ライブラリの使用
<a name="using-the-cognitoauthentication-extension-library"></a>

Amazon Cognito には、Secure Remote Password (SRP) を通じてユーザー名とパスワードを検証する標準的な認証フローのための、組み込みの `AuthFlow` 値と `ChallengeName` 値がいくつかあります。認証フローの詳細については、「[Amazon Cognito ユーザープール認証フロー](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html)」を参照してください。

以下の例では、これらの `using` ステートメントが必要になります。

```
// Required for all examples
using System;
using Amazon;
using Amazon.CognitoIdentity;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;
using Amazon.Runtime;
// Required for the GetS3BucketsAsync example
using Amazon.S3;
using Amazon.S3.Model;
```

### 基本的な認証の使用
<a name="use-basic-authentication"></a>

[AnonymousAWSCredentials](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Runtime/TAnonymousAWSCredentials.html) を使用して、署名付きリクエストを必要としない [AmazonCognitoIdentityProviderClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CognitoIdentityProvider/TCognitoIdentityProviderClient.html) を作成します。リージョンを指定する必要はありませんが、基盤となるコードはリージョンが提供されない場合 `FallbackRegionFactory.GetRegionEndpoint()` を呼び出します。`CognitoUserPool` および `CognitoUser` オブジェクトを作成します。ユーザーパスワードを含む `StartWithSrpAuthAsync` で `InitiateSrpAuthRequest` メソッドを呼び出します。

```
public static async void GetCredsAsync()
{
    AmazonCognitoIdentityProviderClient provider =
        new AmazonCognitoIdentityProviderClient(new Amazon.Runtime.AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);
    InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest()
    {
        Password = "userPassword"
    };

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);
    accessToken = authResponse.AuthenticationResult.AccessToken;

}
```

### チャレンジを使用した認証
<a name="authenticate-with-challenges"></a>

NewPasswordRequired や多要素認証 (MFA) などのチャレンジを使用して認証フローを継続することも、より簡単な方法です。唯一の要件は、CognitoAuthentication オブジェクト、SRP 用のユーザーパスワード、およびユーザーが入力することにより取得される、次のチャレンジに必要な情報です。次のコードは、チャレンジタイプを確認し、認証フロー中の MFA および NewPasswordRequired チャレンジに対する適切な応答を取得する方法の 1 つを示しています。

前と同じように、基本的な認証リクエストと `await` および `AuthFlowResponse` を実行します。レスポンスを受信すると、返された `AuthenticationResult` オブジェクトをループします。`ChallengeName` タイプが `NEW_PASSWORD_REQUIRED` の場合は、`RespondToNewPasswordRequiredAsync` メソッドを呼び出します。

```
public static async void GetCredsChallengesAsync()
{
    AmazonCognitoIdentityProviderClient provider = 
        new AmazonCognitoIdentityProviderClient(new Amazon.Runtime.AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);
    InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest(){
        Password = "userPassword"
    };

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);

    while (authResponse.AuthenticationResult == null)
    {
        if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
        {
            Console.WriteLine("Enter your desired new password:");
            string newPassword = Console.ReadLine();

            authResponse = await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest()
            {
                SessionID = authResponse.SessionID,
                NewPassword = newPassword
            });
            accessToken = authResponse.AuthenticationResult.AccessToken;
        }
        else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
        {
            Console.WriteLine("Enter the MFA Code sent to your device:");
            string mfaCode = Console.ReadLine();

            AuthFlowResponse mfaResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest()
            {
                SessionID = authResponse.SessionID,
                MfaCode = mfaCode

            }).ConfigureAwait(false);
            accessToken = authResponse.AuthenticationResult.AccessToken;
        }
        else
        {
            Console.WriteLine("Unrecognized authentication challenge.");
            accessToken = "";
            break;
        }
    }

    if (authResponse.AuthenticationResult != null)
    {
        Console.WriteLine("User successfully authenticated.");
    }
    else
    {
        Console.WriteLine("Error in authentication process.");
    }
 
}
```

### 認証後に AWS リソースを使用する
<a name="use-aws-resources-after-authentication"></a>

CognitoAuthentication ライブラリを使用してユーザーが認証されたら、次のステップは、ユーザーに適切な AWS リソースへのアクセスを許可することです。そのためには、Amazon Cognito フェデレーテッド ID コンソールを通じて ID プールを作成する必要があります。プロバイダーとして作成した Amazon Cognito ユーザープールを、その poolID および clientID を使用して指定することにより、Amazon Cognito ユーザープールのユーザーがアカウントに接続された AWS リソースにアクセスすることを許可できます。異なるロールを指定して、認証されていないユーザーと認証されたユーザーの両方が異なるリソースにアクセスするようにもできます。IAM コンソールでこれらのルールを変更できます。ロールのアタッチされたポリシーの [**アクション**] フィールドで、アクセス許可を追加または削除できます。次に、適切な ID プール、ユーザープール、Amazon Cognito ユーザー情報を使用して、さまざまな AWS リソースを呼び出すことができます。次の例は、SRP で認証されたユーザーが、関連付けられた ID プールのロールによって許可された異なる Amazon S3 バケットにアクセスする方法を示しています。

```
public async void GetS3BucketsAsync()
{
    var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);

    string password = "userPassword";

    AuthFlowResponse context = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
    {
        Password = password
    }).ConfigureAwait(false);

    CognitoAWSCredentials credentials =
        user.GetCognitoAWSCredentials("identityPoolID", RegionEndpoint.< YourIdentityPoolRegion >);

    using (var client = new AmazonS3Client(credentials))
    {
        ListBucketsResponse response =
            await client.ListBucketsAsync(new ListBucketsRequest()).ConfigureAwait(false);

        foreach (S3Bucket bucket in response.Buckets)
        {
            Console.WriteLine(bucket.BucketName);
        }
    }
}
```

## その他の認証オプション
<a name="more-authentication-options"></a>

SRP に加えて、NewPasswordRequired、MFA、CognitoAuthentication 拡張ライブラリは、以下の簡単な認証フローを提供しています。
+ Custom - `StartWithCustomAuthAsync(InitiateCustomAuthRequest customRequest)` を呼び出すことで開始する 
+ RefreshToken - `StartWithRefreshTokenAuthAsync(InitiateRefreshTokenAuthRequest refreshTokenRequest)` を呼び出すことで開始する 
+ RefreshTokenSRP - `StartWithRefreshTokenAuthAsync(InitiateRefreshTokenAuthRequest refreshTokenRequest)` を呼び出すことで開始する 
+ AdminNoSRP - `StartWithAdminNoSrpAuthAsync(InitiateAdminNoSrpAuthRequest adminAuthRequest)` を呼び出すことで開始する 

フローに応じて適切なメソッドを呼び出します。その後、各メソッド呼び出しの `AuthFlowResponse` オブジェクトで示されるように、ユーザーにチャレンジを表示し続けます。また、MFA チャレンジには `RespondToSmsMfaAuthAsync`、カスタムチャレンジには `RespondToCustomAuthAsync` など、適切なレスポンスメソッドを呼び出します。

# Amazon DynamoDB NoSQL データベースの使用
<a name="dynamodb-intro"></a>

**注記**  
これらのトピックのプログラミングモデルは.NET Framework と.NET (Core) の両方に存在しますが、呼び出し規則は同期か非同期かで異なります。

は、 が提供する高速 NoSQL データベースサービスである Amazon DynamoDB AWS SDK for .NET をサポートしています AWS。SDK では、DynamoDB との通信用に 3 つのプログラムモデルが提供されています。*低レベル*モデル、*ドキュメント*モデル、*オブジェクト永続性*モデルです。

以下では、これらのモデルとその API について紹介し、それぞれの使用方法と用途の例を示します。また、 AWS SDK for .NETでの追加の DynamoDB プログラミングリソースへのリンクも提供します。

## 低レベルモデル
<a name="dynamodb-intro-apis-low-level"></a>

低レベルプログラミングモデルは、DynamoDB サービスの直接呼び出しをラップします。このモデルには、[Amazon.DynamoDBv2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/NDynamoDBv2.html) 名前空間からアクセスします。

低レベルモデルは、3 つのモデルの中で最も多くのコードを記述する必要があります。例えば、.NET データ型を DynamoDB の同等の型に変換する必要があります。ただし、このモデルを使用するとほとんどの機能にアクセスできます。

以下の例では、低レベルモデルを使用して DynamoDB でのテーブルの作成、テーブルの変更、テーブルへの項目の挿入を行う方法を示します。

### テーブルの作成
<a name="dynamodb-intro-apis-low-level-create-table"></a>

次の例では、`CreateTable` クラスの `AmazonDynamoDBClient` メソッドを使用してテーブルを作成します。`CreateTable` メソッドでは、必要な項目属性名、プライマリキーの定義、スループット容量などの特性を含む `CreateTableRequest` クラスのインスタンスを使用します。`CreateTable` メソッドは、`CreateTableResponse` クラスのインスタンスを返します。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();

Console.WriteLine("Getting list of tables");
List<string> currentTables = client.ListTables().TableNames;
Console.WriteLine("Number of tables: " + currentTables.Count);
if (!currentTables.Contains("AnimalsInventory"))
{
    var request = new CreateTableRequest
    {
        TableName = "AnimalsInventory",
        AttributeDefinitions = new List<AttributeDefinition>
      {
        new AttributeDefinition
        {
          AttributeName = "Id",
          // "S" = string, "N" = number, and so on.
          AttributeType = "N"
        },
        new AttributeDefinition
        {
          AttributeName = "Type",
          AttributeType = "S"
        }
      },
        KeySchema = new List<KeySchemaElement>
      {
        new KeySchemaElement
        {
          AttributeName = "Id",
          // "HASH" = hash key, "RANGE" = range key.
          KeyType = "HASH"
        },
        new KeySchemaElement
        {
          AttributeName = "Type",
          KeyType = "RANGE"
        },
      },
        ProvisionedThroughput = new ProvisionedThroughput
        {
            ReadCapacityUnits = 10,
            WriteCapacityUnits = 5
        },
    };

    var response = client.CreateTable(request);

    Console.WriteLine("Table created with request ID: " +
      response.ResponseMetadata.RequestId);
}
```

### テーブルを変更する準備が整っていることの確認
<a name="dynamodb-intro-apis-low-level-verify-table"></a>

テーブルを変更または修正する前に、テーブルを変更する準備が整っていることを確認する必要があります。次の例では、低レベルモデルを使用して DynamoDB のテーブルの準備が整っていることを確認する方法を示します。この例では、チェック対象のテーブルは `DescribeTable` クラスの `AmazonDynamoDBClient` メソッドを使用して参照されています。5 秒ごとに、コードはテーブルの `TableStatus` プロパティの値を調べます。ステータスが `ACTIVE` に設定されると、テーブルは変更できる状態です。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();      
var status = "";

do
{
  // Wait 5 seconds before checking (again).
  System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
        
  try
  {
    var response = client.DescribeTable(new DescribeTableRequest
    {
      TableName = "AnimalsInventory"
    });

    Console.WriteLine("Table = {0}, Status = {1}",
      response.Table.TableName,
      response.Table.TableStatus);

    status = response.Table.TableStatus;
  }
  catch (ResourceNotFoundException)
  {
    // DescribeTable is eventually consistent. So you might
    //   get resource not found. 
  }

} while (status != TableStatus.ACTIVE);
```

### テーブルへの項目の挿入
<a name="dynamodb-intro-apis-low-level-insert-item"></a>

次の例では、低レベルモデルを使用して DynamoDB のテーブルに 2 つの項目を挿入します。各項目は、`PutItem` クラスのインスタンスを使用して、`AmazonDynamoDBClient` クラスの `PutItemRequest` メソッドによって挿入されます。`PutItemRequest` クラスの 2 つのインスタンスはそれぞれ、項目を挿入するテーブルの名前と一連の項目属性値を取得します。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();

var request1 = new PutItemRequest
{
  TableName = "AnimalsInventory",
  Item = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "1" }},
    { "Type", new AttributeValue { S = "Dog" }},
    { "Name", new AttributeValue { S = "Fido" }}
  }
};

var request2 = new PutItemRequest
{
  TableName = "AnimalsInventory",
  Item = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "2" }},
    { "Type", new AttributeValue { S = "Cat" }},
    { "Name", new AttributeValue { S = "Patches" }}
  }
};
        
client.PutItem(request1);
client.PutItem(request2);
```

## ドキュメントモデル
<a name="dynamodb-intro-apis-document"></a>

ドキュメントプログラミングモデルは、DynamoDB のデータを操作する簡単な手段を提供します。このモデルは、特にテーブルおよびテーブル内の項目にアクセスすることを目的に作られています。このモデルには、[Amazon.DynamoDBv2.DocumentModel](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/NDynamoDBv2DocumentModel.html) 名前空間からアクセスします。

低レベルプログラミングモデルと比べると、ドキュメントモデルの方が DynamoDB データに対するコーディングが容易です。例えば、多くの .NET データ型を DynamoDB の同等のデータ型に変換する必要はありません。ただし、このモデルでは、低レベルプログラミングモデルほど多くの機能にはアクセスできません。例えば、このモデルを使用して、テーブルの項目を作成、取得、更新、削除することはできます。しかし、テーブルを作成するには、低レベルモデルを使用する必要があります。オブジェクト永続性モデルと比較すると、このモデルの方が .NET オブジェクトを保存、ロード、クエリするために多くのコードを作成する必要があります。

DynamoDB ドキュメントプログラミングモデルの詳細については、[Amazon DynamoDB デベロッパーガイド](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/)の「[.NET: ドキュメントモデル](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html)」を参照してください。

以下のセクションでは、目的の DynamoDB テーブルの表現を作成する方法と、ドキュメントモデルを使用してテーブルに項目を挿入し、テーブルから項目を取得する方法の例を示します。

### 表の表現の作成
<a name="dynamodb-intro-apis-document-table"></a>

ドキュメントモデルを使用してデータオペレーションを実行するには、最初に メソッドを呼び出して、特定のテーブルを表す `Table`クラスのインスタンスを作成します。これには、主に 2 つの方法があります。

**LoadTable (メソッド)**

1 つ目のメカニズムは、次の例のように、[https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTable.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTable.html)クラスの静的`LoadTable`メソッドの 1 つを使用することです。

```
var client = new AmazonDynamoDBClient();
Table table = Table.LoadTable(client, "Reply");
```

**注記**  
このメカニズムは機能しますが、特定の条件下では、コールドスタートやスレッドプールの動作が原因で、レイテンシーが増えたり、デッドロックが発生したりすることがあります。これらの動作の詳細については、ブログ記事「[AWS SDK for .NETのDynamoDB 初期化パターンの改善](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/)」を参照してください。

**テーブルビルダー**

代替メカニズムである[https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html)クラスは、[AWSSDK.DynamoDBV2 NuGet パッケージのバージョン 3.7.203](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203) で導入されました。このメカニズムでは、特定の暗黙的なメソッド呼び出し (具体的には`DescribeTable`メソッド) を削除することで、上記の動作に対処できます。このメカニズムは、次の例のような方法で使用されます。

```
var client = new AmazonDynamoDBClient();
var table = new TableBuilder(client, "Reply")
    .AddHashKey("Id", DynamoDBEntryType.String)
    .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String)
    .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String, "Message", DynamoDBEntryType.String)
    .Build();
```

この代替メカニズムの詳細については、ブログ記事「 AWS SDK for .NETの [DynamoDB 初期化パターンの改善](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/)」をもう一度参照してください。

### テーブルへの項目の挿入
<a name="dynamodb-intro-apis-document-insert-item"></a>

次の例では、`PutItemAsync` クラスの `Table` メソッドを使用してテーブルにリプライを挿入しています。`PutItemAsync` メソッドは、`Document` クラスのインスタンスを受け取ります。`Document` クラスは、初期化された属性の単純なコレクションです。

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

// Create a representation of the "Reply" table
//  by using one of the mechanisms described previously.

// Then, add a reply to the table.
var newReply = new Document();
newReply["Id"] = Guid.NewGuid().ToString();
newReply["ReplyDateTime"] = DateTime.UtcNow;
newReply["PostedBy"] = "Author1";
newReply["Message"] = "Thank you!";

await table.PutItemAsync(newReply);
```

### テーブルからの項目の取得
<a name="dynamodb-intro-apis-document-get-item"></a>

次の例では、`GetItemAsync` クラスの `Table` メソッドを使用してリプライを取得しています。取得するリプライを特定するために、`GetItemAsync` メソッドでは対象リプライのハッシュおよび範囲プライマリキーを使用しています。

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

// Create a representation of the "Reply" table
//  by using one of the mechanisms described previously.

// Then, get a reply from the table
//  where "guid" is the hash key and "datetime" is the range key.
var reply = await table.GetItemAsync(guid, datetime);
Console.WriteLine("Id = " + reply["Id"]);
Console.WriteLine("ReplyDateTime = " + reply["ReplyDateTime"]);
Console.WriteLine("PostedBy = " + reply["PostedBy"]);
Console.WriteLine("Message = " + reply["Message"]);
```

前述の例では、テーブル値を `WriteLine` メソッドの文字列に暗黙的に変換しています。`DynamoDBEntry`クラスのさまざまな 「As[type]」 メソッドを使用すると、明示的に変換できます。たとえば、`AsGuid()` メソッドを使用して、`Id` の値を `Primitive` データ型から GUID に明示的に変換できます。

```
var guid = reply["Id"].AsGuid();
```

## オブジェクト永続性モデル
<a name="dynamodb-intro-apis-object-persistence"></a>

オブジェクト永続性プログラミングは、特に DynamoDB での .NET オブジェクトの保存、ロード、クエリを目的として作られています。このモデルには、[Amazon.DynamoDBv2.DataModel](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/NDynamoDBv2DataModel.html) 名前空間からアクセスします。

3 つのモデルの中で、オブジェクト永続性モデルは、DynamoDB データの保存、ロード、クエリに関してはコーディングが最も簡単です。例えば、DynamoDB のデータ型を直接操作できます。ただし、このモデルでアクセスできるのは、DynamoDB に .NET オブジェクトを保存、ロード、クエリする操作だけです。例えば、このモデルを使用して、テーブルの項目を作成、取得、更新、削除することはできます。ただし、最初に低レベルモデルを使用してテーブルを作成してから、このモデルを使用して .NET クラスをテーブルにマッピングする必要があります。

DynamoDB オブジェクト永続性プログラミングモデルの詳細については、「[Amazon DynamoDB デベロッパーガイド](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/)」の「[.NET: オブジェクト永続性モデル](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKHighLevel.html)」を参照してください。

次の例は、DynamoDB 項目を表す .NET クラスを定義する方法、.NET クラスのインスタンスを使用して項目を DynamoDB テーブルに挿入する方法、.NET クラスのインスタンスを使用してテーブルから項目を取得する方法を示しています。

### テーブルで項目を表す .NET クラスの定義
<a name="dynamodb-intro-apis-object-persistence-net-class-item"></a>

次のクラス定義の例では、`DynamoDBTable` 属性はテーブル名を指定し、`DynamoDBHashKey` 属性と `DynamoDBRangeKey` 属性はテーブルのハッシュと範囲のプライマリキーをモデル化します。`DynamoDBGlobalSecondaryIndexHashKey`属性は、特定の作成者による返信のクエリを作成できるように定義されています。

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

[DynamoDBTable("Reply")]
public class Reply
{
    [DynamoDBHashKey]
    public string Id { get; set; }

    [DynamoDBRangeKey(StoreAsEpoch = false)]
    public DateTime ReplyDateTime { get; set; }

    [DynamoDBGlobalSecondaryIndexHashKey("PostedBy-Message-Index",
        AttributeName ="PostedBy")]
    public string Author { get; set; }

    [DynamoDBGlobalSecondaryIndexRangeKey("PostedBy-Message-Index")]
    public string Message { get; set; }
}
```

### オブジェクト永続性モデルのコンテキストを作成します。
<a name="dynamodb-intro-apis-object-persistence-context"></a>

DynamoDB のオブジェクト永続プログラミングモデルを使用するには、コンテキストを作成する必要があります。このクラスから DynamoDB に接続して、テーブルにアクセスし、各種のオペレーションとクエリを実行することができます。

**基本コンテキスト**

次の例は、最も基本的なコンテキストを作成する方法を示しています。

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
```

**DisableFetchingTableMetadata プロパティによるコンテキスト**

次の例は、`DescribeTable`メソッドが暗黙的に呼び出されないように、`DynamoDBContextConfig`クラスの`DisableFetchingTableMetadata`プロパティを追加で設定する方法を示しています。

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client, new DynamoDBContextConfig
{
    DisableFetchingTableMetadata = true
});
```

最初の例のように`DisableFetchingTableMetadata`プロパティが `false` (デフォルト) に設定されている場合は、テーブル項目のキーとインデックスの構造を記述する属性を`Reply`クラスから省略できます。代わりに、これらの属性は`DescribeTable`メソッドを暗黙的に呼び出すことで推測されます。2 番目の例に示すように、 `DisableFetchingTableMetadata` が `true` に設定されている場合、`SaveAsync` や `QueryAsync` などのオブジェクト永続モデルのメソッドは、`Reply` クラスで定義された属性に完全に依存します。この場合、`DescribeTable`メソッドの呼び出しは行われません。

**注記**  
特定の条件下では、コールドスタートやスレッドプールの動作が原因で、`DescribeTable`メソッドを呼び出すとレイテンシーが増えたり、デッドロックが発生したりすることがあります。このため、そのメソッドの呼び出しは避けたほうが有利な場合があります。  
これらの動作の詳細については、ブログ記事「 AWS SDK for .NETの[DynamoDB 初期化パターンの改善](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/)」を参照してください。

### .NET クラスのインスタンスの使用によるテーブルへの項目の挿入
<a name="dynamodb-intro-apis-object-persistence-net-insert-item"></a>

上の例では、項目は `DynamoDBContext` クラスの `SaveAsync` メソッドによって挿入されます。このメソッドは、項目を表す .NET クラスの初期化されたインスタンスを受け取ります

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

// Create an appropriate context for the object persistence programming model,
//  examples of which have been described earlier.

// Create an object that represents the new item.
var reply = new Reply()
{
    Id = Guid.NewGuid().ToString(),
    ReplyDateTime = DateTime.UtcNow,
    Author = "Author1",
    Message = "Thank you!"
};

// Insert the item into the table.
await context.SaveAsync<Reply>(reply, new DynamoDBOperationConfig
{
    IndexName = "PostedBy-Message-index"
});
```

### .NET クラスのインスタンスを使用してテーブルから項目を取得する
<a name="dynamodb-intro-apis-object-persistence-net-get-item"></a>

この例では、`DynamoDBContext`クラスの`QueryAsync`メソッドを使用して「Author1」のすべてのレコードを検索するクエリを作成します。次に、クエリの`GetNextSetAsync`メソッドを使用して項目が取得されます。

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

// Create an appropriate context for the object persistence programming model,
//  examples of which have been described earlier.

// Construct a query that finds all replies by a specific author.
var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig
{
    IndexName = "PostedBy-Message-index"
});

// Display the result.
var set = await query.GetNextSetAsync();
foreach (var item in set)
{
    Console.WriteLine("Id = " + item.Id);
    Console.WriteLine("ReplyDateTime = " + item.ReplyDateTime);
    Console.WriteLine("PostedBy = " + item.Author);
    Console.WriteLine("Message = " + item.Message);
}
```

### オブジェクト永続モデルに関する追加情報
<a name="dynamodb-intro-apis-object-persistence-more-into"></a>

上記の例と説明には、`DisableFetchingTableMetadata`という`DynamoDBContext`クラスのプロパティが含まれている場合があります。[awsSDK.DynamoDBV2 NuGet パッケージのバージョン 3.7.203](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203) で導入されたこのプロパティを使用すると、コールドスタートやスレッドプールの動作が原因で、追加のレイテンシーやデッドロックが発生する可能性のある特定の条件を回避できます。詳細については、ブログ記事「 AWS SDK for .NETの[DynamoDB 初期化パターンの改善](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/)」を参照してください。

このプロパティに関する追加情報は次のとおりです。
+ .NET Framework を使用している場合は、このプロパティを`app.config`または`web.config`ファイルにグローバルに設定できます。
+ このプロパティは、次の例に示すように、[https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/TAWSConfigsDynamoDB.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/TAWSConfigsDynamoDB.html)クラスを使用してグローバルに設定できます。

  ```
  // Set the DisableFetchingTableMetadata property globally
  // before constructing any context objects.
  AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true;
  
  var client = new AmazonDynamoDBClient();
  var context = new DynamoDBContext(client);
  ```
+ クラスが依存関係で定義されている場合など、DynamoDB 属性を.NET クラスに追加できない場合があります。このような場合でも、`DisableFetchingTableMetadata`プロパティを利用することは可能です。そのためには、`DisableFetchingTableMetadata`プロパティに加えて[https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html)クラスも使用します。`TableBuilder`クラスは、[AWSSDK.DynamoDBV2 NuGet パッケージのバージョン 3.7.203](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203) でも導入されました。

  ```
  // Set the DisableFetchingTableMetadata property globally
  // before constructing any context objects.
  AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true;
  
  var client = new AmazonDynamoDBClient();
  var context = new DynamoDBContext(client);
  
  var table = new TableBuilder(client, "Reply")
      .AddHashKey("Id", DynamoDBEntryType.String)
      .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String)
      .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String,
          "Message", DynamoDBEntryType.String)
      .Build();
  
  // This registers the "Reply" table we constructed via the builder.
  context.RegisterTableDefinition(table);
  
  // Now operations like this will work,
  // even if the Reply class was not annotated with this index.
  var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig()
  {
      IndexName = "PostedBy-Message-index"
  });
  ```

## 詳細情報
<a name="dynamodb-intro-more-info"></a>

 ** AWS SDK for .NET を使用して DynamoDB をプログラムする、情報と例**
+  [DynamoDB API](http://blogs.aws.amazon.com/net/post/Tx17SQHVEMW8MXC/DynamoDB-APIs) 
+  [DynamoDB Series Kickoff](http://blogs.aws.amazon.com/net/post/Tx2XQOCY08QMTKO/DynamoDB-Series-Kickoff) 
+  [DynamoDB Series - Document Model](http://blogs.aws.amazon.com/net/post/Tx2R0WG46GQI1JI/DynamoDB-Series-Document-Model) 
+  [DynamoDB Series - Conversion Schemas](http://blogs.aws.amazon.com/net/post/Tx2TCOGWG7ARUH5/DynamoDB-Series-Conversion-Schemas) 
+  [DynamoDB Series - Object Persistence Model](http://blogs.aws.amazon.com/net/post/Tx20L86FLMBW51P/DynamoDB-Series-Object-Persistence-Model) 
+  [DynamoDB Series - Expressions](http://blogs.aws.amazon.com/net/post/TxZQM7VA9AUZ9L/DynamoDB-Series-Expressions) 
+  [Amazon DynamoDB と での式の使用 AWS SDK for .NET](dynamodb-expressions.md) 
+  [Amazon DynamoDB での JSON のサポート](dynamodb-json.md) 

 **低レベルモデル、情報および例** 
+  [AWS SDK for .NET 低レベル API を使用したテーブルの操作](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetWorkingWithTables.html) 
+  [AWS SDK for .NET 低レベル API を使用したアイテムの操作](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html) 
+  [AWS SDK for .NET 低レベル API を使用したテーブルのクエリ](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetQuerying.html) 
+  [AWS SDK for .NET 低レベル API を使用したテーブルのスキャン](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html) 
+  [AWS SDK for .NET 低レベル API を使用したローカルセカンダリインデックスの操作](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSILowLevelDotNet.html) 
+  [AWS SDK for .NET 低レベル API を使用したグローバルセカンダリインデックスの使用](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSILowLevelDotNet.html) 

 **ドキュメントモデル、情報および例** 
+  [DynamoDB データ型](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html#DataModel.DataTypes) 
+  [DynamoDBEntry](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TDynamoDBv2DocumentModelDynamoDBEntry.html) 
+  [.NET ドキュメントモデル](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html) 

 **オブジェクト永続性モデル、情報および例** 
+  [.NET: オブジェクト永続性モデル](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKHighLevel.html) 

 **その他の有用な情報** 
+ .NET Aspire を通じた Amazon DynamoDB Local での開発については、「[.NET Aspire AWS との統合](aspire-integrations.md)」を参照してください。

**Topics**
+ [低レベルモデル](#dynamodb-intro-apis-low-level)
+ [ドキュメントモデル](#dynamodb-intro-apis-document)
+ [オブジェクト永続性モデル](#dynamodb-intro-apis-object-persistence)
+ [詳細情報](#dynamodb-intro-more-info)
+ [式の使用](dynamodb-expressions.md)
+ [JSON サポート](dynamodb-json.md)

# Amazon DynamoDB と での式の使用 AWS SDK for .NET
<a name="dynamodb-expressions"></a>

**注記**  
このトピックの情報は、.NET Framework および AWS SDK for .NET バージョン 3.3 以前のプロジェクトに固有のものです。

次のコード例は、 を使用して式で DynamoDB AWS SDK for .NET をプログラムする方法を示しています。*式*は、DynamoDB テーブルの項目から読み取る属性を示します。また、項目を書き込むときも式を使用して、満たす必要がある条件 (*条件付き更新*とも呼ばれます) と、属性を更新する方法を示します。更新の例として、属性を新しい値で置き換えたり、新しいデータをリストやマップに追加したりします。詳細については、「[式を使用した項目の読み取りと書き込み](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html)」を参照してください。

**Topics**
+ [サンプルデータ](#dynamodb-expressions-sample-data)
+ [式と項目のプライマリキーを使用して単一の項目を取得する](#dynamodb-expressions-get-item)
+ [式およびテーブルのプライマリキーを使用して複数の項目を取得する](#dynamodb-expressions-query)
+ [式および他の項目属性を使って複数の項目を取得する](#dynamodb-expressions-scan)
+ [項目の出力](#dynamodb-expressions-print-item)
+ [式を使用して項目を作成または置換する](#dynamodb-expressions-put-item)
+ [式を使用して項目を更新する](#dynamodb-expressions-update-item)
+ [式を使用して項目を削除する](#dynamodb-expressions-delete-item)
+ [詳細情報](#dynamodb-expressions-resources)

## サンプルデータ
<a name="dynamodb-expressions-sample-data"></a>

このトピックのコード例では、`ProductCatalog` という名前の DynamoDB テーブルに存在する以下の 2 つの項目を例として使用します。これらの項目は、架空の自転車店のカタログの製品エントリに関する情報を示します。これらの項目は、「[導入事例: ProductCatalog 項目](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.CaseStudy.html)」で提供されている例に基づきます。`BOOL`、`L`、`M`、`N`、`NS`、`S`、`SS` などのデータ型記述子は、[JSON データ形式](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataFormat.html)でのデータ型に対応します。

```
{
  "Id": {
    "N": "205"
  },
  "Title": {
    "S": "20-Bicycle 205"
  },
  "Description": {
    "S": "205 description"
  },
  "BicycleType": {
    "S": "Hybrid"
  },
  "Brand": {
    "S": "Brand-Company C"
  },
  "Price": {
    "N": "500"
  },
  "Gender": {
    "S": "B"
  },
  "Color": {
    "SS": [
      "Red",
      "Black"
    ]
  },
  "ProductCategory": {
    "S": "Bike"
  },
  "InStock": {
    "BOOL": true
  },
  "QuantityOnHand": {
    "N": "1"
  },
  "RelatedItems": {
    "NS": [
      "341",
      "472",
      "649"
    ]
  },
  "Pictures": {
    "L": [
      {
        "M": {
          "FrontView": {
            "S": "http://example/products/205_front.jpg"
          }
        }
      },
      {
        "M": {
          "RearView": {
            "S": "http://example/products/205_rear.jpg"
          }
        }
      },
      {
        "M": {
          "SideView": {
            "S": "http://example/products/205_left_side.jpg"
          }
        }
      }
    ]
  },
  "ProductReviews": {
    "M": {
      "FiveStar": {
        "SS": [
          "Excellent! Can't recommend it highly enough! Buy it!",
          "Do yourself a favor and buy this."
        ]
      },
      "OneStar": {
        "SS": [
          "Terrible product! Do not buy this."
        ]
      }
    }
  }
},
{
  "Id": {
    "N": "301"
  },
  "Title": {
    "S": "18-Bicycle 301"
  },
  "Description": {
    "S": "301 description"
  },
  "BicycleType": {
    "S": "Road"
  },
  "Brand": {
    "S": "Brand-Company C"
  },
  "Price": {
    "N": "185"
  },
  "Gender": {
    "S": "F"
  },
  "Color": {
    "SS": [
      "Blue",
      "Silver"
    ]
  },
  "ProductCategory": {
    "S": "Bike"
  },
  "InStock": {
    "BOOL": true
  },
  "QuantityOnHand": {
    "N": "3"
  },
  "RelatedItems": {
    "NS": [
      "801",
      "822",
      "979"
    ]
  },
  "Pictures": {
    "L": [
      {
        "M": {
          "FrontView": {
            "S": "http://example/products/301_front.jpg"
          }
        }
      },
      {
        "M": {
          "RearView": {
            "S": "http://example/products/301_rear.jpg"
          }
        }
      },
      {
        "M": {
          "SideView": {
            "S": "http://example/products/301_left_side.jpg"
          }
        }
      }
    ]
  },
  "ProductReviews": {
    "M": {
      "FiveStar": {
        "SS": [
          "My daughter really enjoyed this bike!"
        ]
      },
      "ThreeStar": {
        "SS": [
          "This bike was okay, but I would have preferred it in my color.",
	      "Fun to ride."
        ]
      }
    }
  }
}
```

## 式と項目のプライマリキーを使用して単一の項目を取得する
<a name="dynamodb-expressions-get-item"></a>

次の例では、`Amazon.DynamoDBv2.AmazonDynamoDBClient.GetItem` メソッドと一連の式を使用して、`Id` が `205` である項目を取得して出力します。項目の属性のうち返されるものは、`Id`、`Title`、`Description`、`Color`、`RelatedItems`、`Pictures`、`ProductReviews` だけです。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new GetItemRequest
{
  TableName = "ProductCatalog",
  ProjectionExpression = "Id, Title, Description, Color, #ri, Pictures, #pr",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#ri", "RelatedItems" }
  },
  Key = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "205" } }
  },
};
var response = client.GetItem(request);

// PrintItem() is a custom function.
PrintItem(response.Item);
```

前の例で、`ProjectionExpression` プロパティは返される属性を指定しています。`ExpressionAttributeNames` プロパティで、プレースホルダー `#pr` は `ProductReviews` 属性を表し、プレースホルダー `#ri` は `RelatedItems` 属性を表します。`PrintItem` の呼び出しは、「[項目の出力](#dynamodb-expressions-print-item)」で説明されているようにカスタム関数を参照します。

## 式およびテーブルのプライマリキーを使用して複数の項目を取得する
<a name="dynamodb-expressions-query"></a>

次の例では、`Amazon.DynamoDBv2.AmazonDynamoDBClient.Query` メソッドと一連の式を使用して、`Id` が `301` で `Price` の値が `150` より大きい項目を取得して出力します。返される項目の属性は、`Id`、`Title`、および `ThreeStar` のすべての `ProductReviews` 属性だけです。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new QueryRequest
{
  TableName = "ProductCatalog",
  KeyConditions = new Dictionary<string,Condition>
  {
    { "Id", new Condition()
      {
        ComparisonOperator = ComparisonOperator.EQ,
        AttributeValueList = new List<AttributeValue>
        {
          new AttributeValue { N = "301" }
        }
      }
    }
  },
  ProjectionExpression = "Id, Title, #pr.ThreeStar",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#p", "Price" }
  },
  ExpressionAttributeValues = new Dictionary<string,AttributeValue>
  {
    { ":val", new AttributeValue { N = "150" } }
  },
  FilterExpression = "#p > :val"
};
var response = client.Query(request);

foreach (var item in response.Items)
{
  // Write out the first page of an item's attribute keys and values.
  // PrintItem() is a custom function.
  PrintItem(item);
  Console.WriteLine("=====");
}
```

前の例で、`ProjectionExpression` プロパティは返される属性を指定しています。`ExpressionAttributeNames` プロパティで、プレースホルダー `#pr` は `ProductReviews` 属性を表し、プレースホルダー `#p` は `Price` 属性を表します。`#pr.ThreeStar` は、`ThreeStar` 属性だけを返すように指定します。`ExpressionAttributeValues` プロパティは、プレースホルダー `:val` が値 `150` を表すことを指定します。`FilterExpression` プロパティは、`#p`（`Price`）が `:val`（`150`）より大きくなければならないことを指定します。`PrintItem` の呼び出しは、「[項目の出力](#dynamodb-expressions-print-item)」で説明されているようにカスタム関数を参照します。

## 式および他の項目属性を使って複数の項目を取得する
<a name="dynamodb-expressions-scan"></a>

次の例では、`Amazon.DynamoDBv2.AmazonDynamoDBClient.Scan` メソッドと一連の式を使用して、`ProductCategory` が `Bike` であるすべての項目を取得して出力します。返される項目の属性は、`Id`、`Title`、および `ProductReviews` のすべての属性だけです。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new ScanRequest
{
  TableName = "ProductCatalog",
  ProjectionExpression = "Id, Title, #pr",
  ExpressionAttributeValues = new Dictionary<string,AttributeValue>
  {
    { ":catg", new AttributeValue { S = "Bike" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#pc", "ProductCategory" }
  },
  FilterExpression = "#pc = :catg",  
};
var response = client.Scan(request);

foreach (var item in response.Items)
{
  // Write out the first page/scan of an item's attribute keys and values.
  // PrintItem() is a custom function.
  PrintItem(item);
  Console.WriteLine("=====");
}
```

前の例で、`ProjectionExpression` プロパティは返される属性を指定しています。`ExpressionAttributeNames` プロパティで、プレースホルダー `#pr` は `ProductReviews` 属性を表し、プレースホルダー `#pc` は `ProductCategory` 属性を表します。`ExpressionAttributeValues` プロパティは、プレースホルダー `:catg` が値 `Bike` を表すことを指定します。`FilterExpression` プロパティは、`#pc`（`ProductCategory`）が `:catg`（`Bike`）と等しくなければならないことを示します。`PrintItem` の呼び出しは、「[項目の出力](#dynamodb-expressions-print-item)」で説明されているようにカスタム関数を参照します。

## 項目の出力
<a name="dynamodb-expressions-print-item"></a>

次の例では、項目の属性と値を出力する方法を示します。この例は、「[式と項目のプライマリキーを使用して単一の項目を取得する](#dynamodb-expressions-get-item)」、「[式およびテーブルのプライマリキーを使用して複数の項目を取得する](#dynamodb-expressions-query)」、「[式および他の項目属性を使って複数の項目を取得する](#dynamodb-expressions-scan)」の各方法に関する前述の例で使用されています。

```
// using Amazon.DynamoDBv2.Model;

// Writes out an item's attribute keys and values.
public static void PrintItem(Dictionary<string, AttributeValue> attrs)
{
  foreach (KeyValuePair<string, AttributeValue> kvp in attrs)
  {
    Console.Write(kvp.Key + " = ");
    PrintValue(kvp.Value);
  }
}

// Writes out just an attribute's value.
public static void PrintValue(AttributeValue value)
{
  // Binary attribute value.
  if (value.B != null)
  {
    Console.Write("Binary data");
  }
  // Binary set attribute value.
  else if (value.BS.Count > 0)
  {
    foreach (var bValue in value.BS)
    {
      Console.Write("\n  Binary data");
    }
  }
  // List attribute value.
  else if (value.L.Count > 0)
  {
    foreach (AttributeValue attr in value.L)
    {
      PrintValue(attr);
    }
  }
  // Map attribute value.
  else if (value.M.Count > 0)
  {
    Console.Write("\n");
    PrintItem(value.M);
  }
  // Number attribute value.
  else if (value.N != null)
  {
    Console.Write(value.N);
  }
  // Number set attribute value.
  else if (value.NS.Count > 0)
  {
    Console.Write("{0}", string.Join("\n", value.NS.ToArray()));
  }
  // Null attribute value.
  else if (value.NULL)
  {
    Console.Write("Null");
  }
  // String attribute value.
  else if (value.S != null)
  {
    Console.Write(value.S);
  }
  // String set attribute value.
  else if (value.SS.Count > 0)
  {
    Console.Write("{0}", string.Join("\n", value.SS.ToArray()));
  }
  // Otherwise, boolean value.
  else
  {
    Console.Write(value.BOOL);
  }
 
  Console.Write("\n");
}
```

前の例では、各属性値に含まれる複数のデータ型固有のプロパティを評価して、属性を出力する正しい形式を決定しています。このようなプロパティとしては `B`、`BOOL`、`BS`、`L`、`M`、`N`、`NS`、`NULL`、`S`、`SS` などがあり、これらは [JSON データ形式](DataFormat.html)に対応しています。`B`、`N`、`NULL`、`S` などのプロパティでは、対応するプロパティが `null` ではない場合、属性は対応する `null` ではないデータ型になります。`BS`、`L`、`M`、`NS`、`SS` などのプロパティでは、`Count` がゼロより大きい場合、属性は対応するゼロ値ではないデータ型になります。属性のすべてのデータ型固有プロパティが `null` であるか、または `Count` がゼロに等しい場合、属性は `BOOL` データ型に対応します。

## 式を使用して項目を作成または置換する
<a name="dynamodb-expressions-put-item"></a>

次の例では、`Amazon.DynamoDBv2.AmazonDynamoDBClient.PutItem` メソッドと一連の式を使用して、`Title` が `18-Bicycle 301` である項目を更新します。項目が存在しない場合、新しい項目が追加されます。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new PutItemRequest
{
  TableName = "ProductCatalog",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":product", new AttributeValue { S = "18-Bicycle 301" } }
  },
  ConditionExpression = "#title = :product", 
  // CreateItemData() is a custom function.
  Item = CreateItemData()
};
client.PutItem(request);
```

前の例で、`ExpressionAttributeNames` プロパティは、プレースホルダー `#title` が `Title` 属性を表すことを指定します。`ExpressionAttributeValues` プロパティは、プレースホルダー `:product` が値 `18-Bicycle 301` を表すことを指定します。`ConditionExpression` プロパティは、`#title`（`Title`）が `:product`（`18-Bicycle 301`）と等しくなければならないことを示します。`CreateItemData` の呼び出しは、次のカスタム関数を参照します。

```
// using Amazon.DynamoDBv2.Model;

// Provides a sample item that can be added to a table.
public static Dictionary<string, AttributeValue> CreateItemData()
{
  var itemData = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "301" } },
    { "Title", new AttributeValue { S = "18\" Girl's Bike" } },
    { "BicycleType", new AttributeValue { S = "Road" } },
    { "Brand" , new AttributeValue { S = "Brand-Company C" } },
    { "Color", new AttributeValue { SS = new List<string>{ "Blue", "Silver" } } },
    { "Description", new AttributeValue { S = "301 description" } },
    { "Gender", new AttributeValue { S = "F" } },
    { "InStock", new AttributeValue { BOOL = true } },
    { "Pictures", new AttributeValue { L = new List<AttributeValue>{ 
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "FrontView", new AttributeValue { S = "http://example/products/301_front.jpg" } } } } },
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "RearView", new AttributeValue {S = "http://example/products/301_rear.jpg" } } } } },
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "SideView", new AttributeValue { S = "http://example/products/301_left_side.jpg" } } } } }
    } } },
    { "Price", new AttributeValue { N = "185" } },
    { "ProductCategory", new AttributeValue { S = "Bike" } },
    { "ProductReviews", new AttributeValue { M = new Dictionary<string,AttributeValue>{
      { "FiveStar", new AttributeValue { SS = new List<string>{
        "My daughter really enjoyed this bike!" } } },
      { "OneStar", new AttributeValue { SS = new List<string>{
        "Fun to ride.",
        "This bike was okay, but I would have preferred it in my color." } } }
    } } },
    { "QuantityOnHand", new AttributeValue { N = "3" } },
    { "RelatedItems", new AttributeValue { NS = new List<string>{ "979", "822", "801" } } }
  };

  return itemData;
}
```

前の例では、サンプルデータを含む項目の例が呼び出し元に返されます。一連の属性と対応する値は、`BOOL`、`L`、`M`、`N`、`NS`、`S`、`SS` のようなデータ型を使用して構成されます。これらは [JSON データ形式](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataFormat.html)内のものと対応しています。

## 式を使用して項目を更新する
<a name="dynamodb-expressions-update-item"></a>

次の例では、`Amazon.DynamoDBv2.AmazonDynamoDBClient.UpdateItem` メソッドと一連の式を使用して、`Title` が `18" Girl's Bike` である項目の `Id` を `301` に変更します。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new UpdateItemRequest
{
  TableName = "ProductCatalog",
  Key = new Dictionary<string,AttributeValue>
  {
     { "Id", new AttributeValue { N = "301" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":newproduct", new AttributeValue { S = "18\" Girl's Bike" } }
  },
  UpdateExpression = "SET #title = :newproduct"
};
client.UpdateItem(request);
```

前の例で、`ExpressionAttributeNames` プロパティは、プレースホルダー `#title` が `Title` 属性を表すことを指定します。`ExpressionAttributeValues` プロパティは、プレースホルダー `:newproduct` が値 `18" Girl's Bike` を表すことを指定します。`UpdateExpression` プロパティは、`#title`（`Title`）を `:newproduct`（`18" Girl's Bike`）に変更することを指定します。

## 式を使用して項目を削除する
<a name="dynamodb-expressions-delete-item"></a>

次の例では、`Amazon.DynamoDBv2.AmazonDynamoDBClient.DeleteItem` メソッドと一連の式を使用して、`Id` が `301` で `Title` が `18-Bicycle 301` である項目を削除します。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new DeleteItemRequest
{
  TableName = "ProductCatalog",
  Key = new Dictionary<string,AttributeValue>
  {
     { "Id", new AttributeValue { N = "301" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":product", new AttributeValue { S = "18-Bicycle 301" } }
  },
  ConditionExpression = "#title = :product"
};
client.DeleteItem(request);
```

前の例で、`ExpressionAttributeNames` プロパティは、プレースホルダー `#title` が `Title` 属性を表すことを指定します。`ExpressionAttributeValues` プロパティは、プレースホルダー `:product` が値 `18-Bicycle 301` を表すことを指定します。`ConditionExpression` プロパティは、`#title`（`Title`）が `:product`（`18-Bicycle 301`）と等しくなければならないことを示します。

## 詳細情報
<a name="dynamodb-expressions-resources"></a>

詳細な説明とコード例については、以下を参照してください。
+  [DynamoDB Series - Expressions](http://blogs.aws.amazon.com/net/post/TxZQM7VA9AUZ9L/DynamoDB-Series-Expressions) 
+  [プロジェクト式を使用した項目属性へのアクセス](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) 
+  [属性の名前および値でのプレースホルダーの使用](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html) 
+  [条件式を使用した条件の指定](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) 
+  [更新式を使用した項目および属性の変更](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Modifying.html) 
+  [AWS SDK for .NET 低レベル API を使用したアイテムの操作](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html) 
+  [AWS SDK for .NET 低レベル API を使用したテーブルのクエリ](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetQuerying.html) 
+  [AWS SDK for .NET 低レベル API を使用したテーブルのスキャン](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html) 
+  [AWS SDK for .NET 低レベル API を使用したローカルセカンダリインデックスの操作](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSILowLevelDotNet.html) 
+  [AWS SDK for .NET 低レベル API を使用したグローバルセカンダリインデックスの使用](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSILowLevelDotNet.html) 

# Amazon DynamoDB での JSON のサポート
<a name="dynamodb-json"></a>

**注記**  
このトピックの情報は、.NET Framework および AWS SDK for .NET バージョン 3.3 以前のプロジェクトに固有のものです。

は、Amazon DynamoDB を使用する際に JSON データ AWS SDK for .NET をサポートします。そのため、DynamoDB テーブルから JSON 形式のデータを取得したり、テーブルに JSON ドキュメントを挿入したりする操作を簡単に行えます。

**Topics**
+ [DynamoDB テーブルから JSON 形式のデータを取得する](#dynamodb-json-get-table-data)
+ [DynamoDB テーブルに JSON 形式のデータを挿入する](#dynamodb-json-insert-table-data)
+ [DynamoDB データ型の JSON への変換](#dynamodb-json-datatypes)
+ [詳細情報](#dynamodb-json-more-info)

## DynamoDB テーブルから JSON 形式のデータを取得する
<a name="dynamodb-json-get-table-data"></a>

次の例では、DynamoDB テーブルから JSON 形式のデータを取得する方法を示します。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.DocumentModel;

var client = new AmazonDynamoDBClient();
var table = Table.LoadTable(client, "AnimalsInventory");
var item = table.GetItem(3, "Horse");

var jsonText = item.ToJson();
Console.Write(jsonText);
      
// Output:
//   {"Name":"Shadow","Type":"Horse","Id":3}

var jsonPrettyText = item.ToJsonPretty();
Console.WriteLine(jsonPrettyText);
      
// Output:
//   {
//     "Name" : "Shadow",
//     "Type" : "Horse",
//     "Id"   : 3
//   }
```

この例では、`Document` クラスの `ToJson` メソッドを使用してテーブルの項目を JSON 形式の文字列に変換しています。項目を取得するには、`Table` クラスの `GetItem` メソッドを使用します。取得する項目を特定するには、この例では、対象項目のハッシュおよび範囲プライマリキーを `GetItem` メソッドで使用しています。項目を取得するテーブルを特定するために、`Table` クラスの `LoadTable` メソッドで `AmazonDynamoDBClient` クラスのインスタンスと DynamoDB の対象テーブルの名前を使用しています。

## DynamoDB テーブルに JSON 形式のデータを挿入する
<a name="dynamodb-json-insert-table-data"></a>

次の例では、JSON 形式を使用して DynamoDB テーブルに項目を挿入する方法を示します。

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.DocumentModel;

var client = new AmazonDynamoDBClient();
var table = Table.LoadTable(client, "AnimalsInventory");
var jsonText = "{\"Id\":6,\"Type\":\"Bird\",\"Name\":\"Tweety\"}";
var item = Document.FromJson(jsonText);

table.PutItem(item);
```

この例では、`Document` クラスの `FromJson` メソッドを使用して JSON 形式の文字列を項目に変換しています。項目は、`PutItem` クラスの `Table` メソッドによってテーブルに挿入されます。このメソッドは、項目を含む `Document` クラスのインスタンスを使用します。項目を挿入するテーブルを特定するために、`Table` クラスの `LoadTable` メソッドが呼び出され、`AmazonDynamoDBClient` クラスのインスタンスと DynamoDB の対象テーブルの名前を指定しています。

## DynamoDB データ型の JSON への変換
<a name="dynamodb-json-datatypes"></a>

`Document` クラスの `ToJson` メソッドを呼び出す場合、および結果の JSON データで `FromJson` メソッドを呼び出して JSON データを `Document` クラスのインスタンスに変換する場合、一部の DynamoDB データ型は意図したとおりには変換されません。具体的には次のとおりです。
+ DynamoDB のセット (`SS`、`NS`、`BS` 型) は、JSON の配列に変換されます。
+ DynamoDB のバイナリスカラーおよびセット (`B`、`BS` 型) は、base64 でエンコードされた JSON 文字列または文字列のリストに変換されます。

  この場合は、`Document` クラスの `DecodeBase64Attributes` メソッドを呼び出して、base64 でエンコードされた JSON データを正しいバイナリ表現に置き換える必要があります。次の例では、`Document` クラスのインスタンスの `Picture` という名前の base64 でエンコードされたバイナリスカラー項目属性を、正しいバイナリ表現で置き換えています。また、この例では、`Document` クラスの同じインスタンスの `RelatedPictures` という名前の base64 でエンコードされたバイナリセット項目属性に対しても同じことを行っています。

  ```
  item.DecodeBase64Attributes("Picture", "RelatedPictures");
  ```

## 詳細情報
<a name="dynamodb-json-more-info"></a>

を使用して DynamoDB で JSON をプログラミングする詳細と例については AWS SDK for .NET、以下を参照してください。
+  [DynamoDB JSON Support](https://aws.amazon.com/blogs/developer/dynamodb-json-support/) 
+  [Amazon DynamoDB Update - JSON, Expanded Free Tier, Flexible Scaling, Larger Items](https://aws.amazon.com/blogs/aws/dynamodb-update-json-and-more/) 

# Amazon EC2 の使用
<a name="ec2-apis-intro"></a>

は、サイズ変更可能なコンピューティング容量を提供するウェブサービスである [Amazon EC2](https://docs.aws.amazon.com/ec2/) AWS SDK for .NET をサポートしています。このコンピューティング性能を使用して、ソフトウェアシステムの構築とホストを行います。

## API
<a name="w2aac19c15c21b5"></a>

 AWS SDK for .NET はAPIs を提供します。 Amazon EC2 API を通じて、セキュリティグループやキーペアなどの EC2 の機能を使用できます。API により、Amazon EC2 インスタンスを制御することもできます。このセクションでは、これらの API を操作する際に活用できるパターンを示すいくつかの例を紹介します。API の完全なセットを確認するには、[AWS SDK for .NET API リファレンス](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)を参照してください (「Amazon.EC2」までスクロールします)。

Amazon EC2 API は、[AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2) NuGet パッケージによって提供されます。

## 前提条件
<a name="w2aac19c15c21b7"></a>

開始する前に、[環境をセットアップ](net-dg-config.md)し、[プロジェクトを設定した](configuring-the-sdk.md)ことを確認してください。また、「[SDK の使用](net-dg-sdk-features.md)」の情報を確認してください。

## の例について
<a name="ec2-apis-intro-about"></a>

このセクションの例では、Amazon EC2 クライアントの使用方法と、Amazon EC2 インスタンスを管理する方法について説明します。

[EC2 スポットインスタンスのチュートリアル](how-to-spot-instances.md)では、Amazon EC2 スポットインスタンスをリクエストする方法について説明します。スポットインスタンスを使用すると、未使用の EC2 性能にオンデマンド料金よりも低価格でアクセスできます。

**Topics**
+ [API](#w2aac19c15c21b5)
+ [前提条件](#w2aac19c15c21b7)
+ [の例について](#ec2-apis-intro-about)
+ [セキュリティグループ](security-groups.md)
+ [キーペア](key-pairs.md)
+ [リージョンとアベイラビリティーゾーン](using-regions-and-availability-zones.md)
+ [EC2 インスタンス](how-to-ec2.md)
+ [スポットインスタンスのチュートリアル](how-to-spot-instances.md)

# Amazon EC2 でのセキュリティグループの使用
<a name="security-groups"></a>

Amazon EC2 では、*セキュリティグループ*は 1 つ以上の EC2 インスタンスのネットワークトラフィックを制御する仮想ファイアウォールとして機能します。デフォルトでは EC2 は、インバウンドトラフィックを許可しないセキュリティグループにインスタンスを関連付けます。EC2 インスタンスが特定のトラフィックを受け付けるようにするセキュリティグループを作成できます。例えば、EC2 Windows インスタンスに接続する必要がある場合は、RDP トラフィックを許可するようにセキュリティグループを設定する必要があります。

セキュリティグループの詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon EC2 セキュリティグループ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)」を参照してください。

**警告**  
EC2-Classic は 2022 年 8 月 15 日に廃止されました。EC2-Classic は、VPC への移行をお勧めします。詳細については、ブログ記事「[EC2-Classic Networking is Retiring - Here's How to Prepare](https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/)」を参照してください。

API の詳細と前提条件については、親セクション ([Amazon EC2 の使用](ec2-apis-intro.md)) を参照してください。

**Topics**
+ [セキュリティグループの列挙](enumerate-security-groups.md)
+ [セキュリティグループの作成](creating-security-group.md)
+ [セキュリティグループの更新](authorize-ingress.md)

# セキュリティグループの列挙
<a name="enumerate-security-groups"></a>

この例では、 を使用してセキュリティグループ AWS SDK for .NET を列挙する方法を示します。[Amazon Virtual Private Cloud](https://docs.aws.amazon.com/vpc/latest/userguide/) ID を指定した場合、アプリケーションは指定された VPC のセキュリティグループを列挙します。指定しなかった場合、アプリケーションは単に使用可能なすべてのセキュリティグループを一覧表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#enum-sec-groups-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [セキュリティグループの列挙](#enum-sec-groups-enum)
+ [コード全文](#enum-sec-groups-complete-code)
+ [その他の考慮事項](#enum-sec-groups-additional)

## セキュリティグループの列挙
<a name="enum-sec-groups-enum"></a>

次のスニペットでは、セキュリティグループを列挙します。すべてのグループ、または特定の VPC が指定されている場合にはその VPC のグループを列挙します。

[このトピックの最後](#enum-sec-groups-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to enumerate the security groups
    private static async Task EnumerateGroups(IAmazonEC2 ec2Client, string vpcID)
    {
      // A request object, in case we need it.
      var request = new DescribeSecurityGroupsRequest();

      // Put together the properties, if needed
      if(!string.IsNullOrEmpty(vpcID))
      {
        // We have a VPC ID. Find the security groups for just that VPC.
        Console.WriteLine($"\nGetting security groups for VPC {vpcID}...\n");
        request.Filters.Add(new Filter
        {
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });
      }

      // Get the list of security groups
      DescribeSecurityGroupsResponse response =
        await ec2Client.DescribeSecurityGroupsAsync(request);

      // Display the list of security groups.
      foreach (SecurityGroup item in response.SecurityGroups)
      {
        Console.WriteLine("Security group: " + item.GroupId);
        Console.WriteLine("\tGroupId: " + item.GroupId);
        Console.WriteLine("\tGroupName: " + item.GroupName);
        Console.WriteLine("\tVpcId: " + item.VpcId);
        Console.WriteLine();
      }
    }
```

## コード全文
<a name="enum-sec-groups-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c21c13c13c15b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [DescribeSecurityGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsRequest.html)

  クラス [DescribeSecurityGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsResponse.html)

  クラス [Filter](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TFilter.html)

  クラス [SecurityGroup](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSecurityGroup.html)

### コード
<a name="w2aac19c15c21c13c13c15b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2EnumerateSecGroups
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line
       string vpcID = string.Empty;
      if(args.Length == 0)
      {
        Console.WriteLine("\nEC2EnumerateSecGroups [vpc_id]");
        Console.WriteLine("  vpc_id - The ID of the VPC for which you want to see security groups.");
        Console.WriteLine("\nSince you specified no arguments, showing all available security groups.");
      }
      else
      {
        vpcID = args[0];
      }

      if(vpcID.StartsWith("vpc-") || string.IsNullOrEmpty(vpcID))
      {
        // Create an EC2 client object
        var ec2Client = new AmazonEC2Client();

        // Enumerate the security groups
        await EnumerateGroups(ec2Client, vpcID);
      }
      else
      {
        Console.WriteLine("Could not find a valid VPC ID in the command-line arguments:");
        Console.WriteLine($"{args[0]}");
      }
    }


    //
    // Method to enumerate the security groups
    private static async Task EnumerateGroups(IAmazonEC2 ec2Client, string vpcID)
    {
      // A request object, in case we need it.
      var request = new DescribeSecurityGroupsRequest();

      // Put together the properties, if needed
      if(!string.IsNullOrEmpty(vpcID))
      {
        // We have a VPC ID. Find the security groups for just that VPC.
        Console.WriteLine($"\nGetting security groups for VPC {vpcID}...\n");
        request.Filters.Add(new Filter
        {
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });
      }

      // Get the list of security groups
      DescribeSecurityGroupsResponse response =
        await ec2Client.DescribeSecurityGroupsAsync(request);

      // Display the list of security groups.
      foreach (SecurityGroup item in response.SecurityGroups)
      {
        Console.WriteLine("Security group: " + item.GroupId);
        Console.WriteLine("\tGroupId: " + item.GroupId);
        Console.WriteLine("\tGroupName: " + item.GroupName);
        Console.WriteLine("\tVpcId: " + item.VpcId);
        Console.WriteLine();
      }
    }
  }
}
```

## その他の考慮事項
<a name="enum-sec-groups-additional"></a>
+ VPC の場合、フィルターの名前と値のペアの `Name` の部分が「vpc-id」に設定されている点に注目してください。この名前は、[DescribeSecurityGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsRequest.html) クラスの `Filters` プロパティの記述に由来しています。
+ セキュリティグループの完全なリストを取得するには、[DescribeSecurityGroupsAsync をパラメータなしで](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/MEC2DescribeSecurityGroupsAsyncCancellationToken.html)使用することもできます。
+ [Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/v2/home#SecurityGroups)でセキュリティグループのリストを確認することにより、結果を検証できます。

# セキュリティグループの作成
<a name="creating-security-group"></a>

この例では、 AWS SDK for .NET を使用してセキュリティグループを作成する方法を示します。既存の VPC の ID を指定して、VPC 内の EC2 用のセキュリティグループを作成できます。このような ID を指定しない場合、 AWS アカウントがこれをサポートしている場合、新しいセキュリティグループは EC2-Classic 用になります。

VPC ID を指定せず、 AWS アカウントが EC2-Classic をサポートしていない場合、新しいセキュリティグループはアカウントのデフォルト VPC に属します。

**警告**  
EC2-Classic は 2022 年 8 月 15 日に廃止されました。EC2-Classic は、VPC への移行をお勧めします。詳細については、ブログ記事「[EC2-Classic Networking is Retiring - Here's How to Prepare](https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/)」を参照してください。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#create-sec-groups-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [既存のセキュリティグループを検索する](#create-sec-groups-find)
+ [セキュリティグループを作成する](#create-sec-groups-enum)
+ [コード全文](#create-sec-groups-complete-code)

## 既存のセキュリティグループを検索する
<a name="create-sec-groups-find"></a>

次のスニペットでは、指定された名前を持つ既存のセキュリティグループを指定された VPC 内で検索します。

[このトピックの最後](#create-sec-groups-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to determine if a security group with the specified name
    // already exists in the VPC
    private static async Task<List<SecurityGroup>> FindSecurityGroups(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      var request = new DescribeSecurityGroupsRequest();
      request.Filters.Add(new Filter{
        Name = "group-name",
        Values = new List<string>() { groupName }
      });
      if(!string.IsNullOrEmpty(vpcID))
        request.Filters.Add(new Filter{
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });

      var response = await ec2Client.DescribeSecurityGroupsAsync(request);
      return response.SecurityGroups;
    }
```

## セキュリティグループを作成する
<a name="create-sec-groups-enum"></a>

次のスニペットでは、指定された名前のグループが指定された VPC に存在しない場合に、新しいセキュリティグループを作成します。VPC が指定されず、指定された名前のグループが 1 つ以上存在する場合、スニペットは単にグループのリストを返します。

[このトピックの最後](#create-sec-groups-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to create a new security group (either EC2-Classic or EC2-VPC)
    // If vpcID is empty, the security group will be for EC2-Classic
    private static async Task<List<SecurityGroup>> CreateSecurityGroup(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      // See if one or more security groups with that name
      // already exist in the given VPC. If so, return the list of them.
      var securityGroups = await FindSecurityGroups(ec2Client, groupName, vpcID);
      if (securityGroups.Count > 0)
      {
        Console.WriteLine(
          $"\nOne or more security groups with name {groupName} already exist.\n");
        return securityGroups;
      }

      // If the security group doesn't already exists, create it.
      var createRequest = new CreateSecurityGroupRequest{
        GroupName = groupName
      };
      if(string.IsNullOrEmpty(vpcID))
      {
        createRequest.Description = "My .NET example security group for EC2-Classic";
      }
      else
      {
        createRequest.VpcId = vpcID;
        createRequest.Description = "My .NET example security group for EC2-VPC";
      }
      CreateSecurityGroupResponse createResponse =
        await ec2Client.CreateSecurityGroupAsync(createRequest);

      // Return the new security group
      DescribeSecurityGroupsResponse describeResponse =
        await ec2Client.DescribeSecurityGroupsAsync(new DescribeSecurityGroupsRequest{
          GroupIds = new List<string>() { createResponse.GroupId }
        });
      return describeResponse.SecurityGroups;
    }
```

## コード全文
<a name="create-sec-groups-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c21c13c15c23b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [CreateSecurityGroupRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateSecurityGroupRequest.html)

  クラス [CreateSecurityGroupResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateSecurityGroupResponse.html)

  クラス [DescribeSecurityGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsRequest.html)

  クラス [DescribeSecurityGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsResponse.html)

  クラス [Filter ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TFilter.html)

  クラス [SecurityGroup](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSecurityGroup.html)

### コード
<a name="w2aac19c15c21c13c15c23b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2CreateSecGroup
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create a security group
  class Program
  {
    private const int MaxArgs = 2;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }
      if(parsedArgs.Count > MaxArgs)
        CommandLine.ErrorExit("\nThe number of command-line arguments is incorrect." +
          "\nRun the command with no arguments to see help.");

      // Get the application arguments from the parsed list
      var groupName = CommandLine.GetArgument(parsedArgs, null, "-g", "--group-name");
      var vpcID = CommandLine.GetArgument(parsedArgs, null, "-v", "--vpc-id");
      if(string.IsNullOrEmpty(groupName))
        CommandLine.ErrorExit("\nYou must supply a name for the new group." +
          "\nRun the command with no arguments to see help.");
      if(!string.IsNullOrEmpty(vpcID) && !vpcID.StartsWith("vpc-"))
        CommandLine.ErrorExit($"\nNot a valid VPC ID: {vpcID}");

      // groupName has a value and vpcID either has a value or is null (which is fine)
      // Create the new security group and display information about it
      var securityGroups =
        await CreateSecurityGroup(new AmazonEC2Client(), groupName, vpcID);
      Console.WriteLine("Information about the security group(s):");
      foreach(var group in securityGroups)
      {
        Console.WriteLine($"\nGroupName: {group.GroupName}");
        Console.WriteLine($"GroupId: {group.GroupId}");
        Console.WriteLine($"Description: {group.Description}");
        Console.WriteLine($"VpcId (if any): {group.VpcId}");
      }
    }


    //
    // Method to create a new security group (either EC2-Classic or EC2-VPC)
    // If vpcID is empty, the security group will be for EC2-Classic
    private static async Task<List<SecurityGroup>> CreateSecurityGroup(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      // See if one or more security groups with that name
      // already exist in the given VPC. If so, return the list of them.
      var securityGroups = await FindSecurityGroups(ec2Client, groupName, vpcID);
      if (securityGroups.Count > 0)
      {
        Console.WriteLine(
          $"\nOne or more security groups with name {groupName} already exist.\n");
        return securityGroups;
      }

      // If the security group doesn't already exists, create it.
      var createRequest = new CreateSecurityGroupRequest{
        GroupName = groupName
      };
      if(string.IsNullOrEmpty(vpcID))
      {
        createRequest.Description = "Security group for .NET code example (no VPC specified)";
      }
      else
      {
        createRequest.VpcId = vpcID;
        createRequest.Description = "Security group for .NET code example (VPC: " + vpcID + ")";
      }
      CreateSecurityGroupResponse createResponse =
        await ec2Client.CreateSecurityGroupAsync(createRequest);

      // Return the new security group
      DescribeSecurityGroupsResponse describeResponse =
        await ec2Client.DescribeSecurityGroupsAsync(new DescribeSecurityGroupsRequest{
          GroupIds = new List<string>() { createResponse.GroupId }
        });
      return describeResponse.SecurityGroups;
    }


    //
    // Method to determine if a security group with the specified name
    // already exists in the VPC
    private static async Task<List<SecurityGroup>> FindSecurityGroups(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      var request = new DescribeSecurityGroupsRequest();
      request.Filters.Add(new Filter{
        Name = "group-name",
        Values = new List<string>() { groupName }
      });
      if(!string.IsNullOrEmpty(vpcID))
        request.Filters.Add(new Filter{
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });

      var response = await ec2Client.DescribeSecurityGroupsAsync(request);
      return response.SecurityGroups;
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2CreateSecGroup -g <group-name> [-v <vpc-id>]" +
        "\n  -g, --group-name: The name you would like the new security group to have." +
        "\n  -v, --vpc-id: The ID of a VPC to which the new security group will belong." +
        "\n     If vpc-id isn't present, the security group will be" +
        "\n     for EC2-Classic (if your AWS account supports this)" +
        "\n     or will use the default VCP for EC2-VPC.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

# セキュリティグループの更新
<a name="authorize-ingress"></a>

この例では、 AWS SDK for .NET を使用してセキュリティグループにルールを追加する方法を示します。特にこの例では、特定の TCP ポートでインバウンドトラフィックを許可するルールを追加します。これは、EC2 インスタンスへのリモート接続などに使用できます。アプリケーションは、既存のセキュリティグループの ID、CIDR 形式の IP アドレス (またはアドレス範囲)、およびオプションで TCP ポート番号を取得します。アプリケーションは次に、指定されたセキュリティグループにインバウンドルールを追加します。

**注記**  
この例を使用するには、CIDR 形式の IP アドレス (またはアドレス範囲) が必要です。お使いのローカルコンピュータの IP アドレスを取得する方法については、このトピックの最後にある**追加の考慮事項**を参照してください。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#authorize-ingress-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [インバウンドルールの追加](#authorize-ingress-add-rule)
+ [コード全文](#authorize-ingress-complete-code)
+ [その他の考慮事項](#authorize-ingress-additional)

## インバウンドルールの追加
<a name="authorize-ingress-add-rule"></a>

次のスニペットでは、セキュリティグループに特定の IP アドレス (または範囲) および TCP ポートのインバウンドルールを追加します。

[このトピックの最後](#authorize-ingress-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method that adds a TCP ingress rule to a security group
    private static async Task AddIngressRule(
      IAmazonEC2 eC2Client, string groupID, string ipAddress, int port)
    {
      // Create an object to hold the request information for the rule.
      // It uses an IpPermission object to hold the IP information for the rule.
      var ingressRequest = new AuthorizeSecurityGroupIngressRequest{
        GroupId = groupID};
      ingressRequest.IpPermissions.Add(new IpPermission{
        IpProtocol = "tcp",
        FromPort = port,
        ToPort = port,
        Ipv4Ranges = new List<IpRange>() { new IpRange { CidrIp = ipAddress } }
      });

      // Create the inbound rule for the security group
      AuthorizeSecurityGroupIngressResponse responseIngress =
        await eC2Client.AuthorizeSecurityGroupIngressAsync(ingressRequest);
      Console.WriteLine($"\nNew RDP rule was written in {groupID} for {ipAddress}.");
      Console.WriteLine($"Result: {responseIngress.HttpStatusCode}");
    }
```

## コード全文
<a name="authorize-ingress-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c21c13c17c17b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [AuthorizeSecurityGroupIngressRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TAuthorizeSecurityGroupIngressRequest.html)

  クラス [AuthorizeSecurityGroupIngressResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TAuthorizeSecurityGroupIngressResponse.html)

  クラス [IpPermission](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIpPermission.html)

  クラス [IpRange](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIpRange.html)

### コード
<a name="w2aac19c15c21c13c17c17b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2AddRuleForRDP
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to add a rule that allows inbound traffic on TCP a port
  class Program
  {
    private const int DefaultPort = 3389;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      var groupID = CommandLine.GetArgument(parsedArgs, null, "-g", "--group-id");
      var ipAddress = CommandLine.GetArgument(parsedArgs, null, "-i", "--ip-address");
      var portStr = CommandLine.GetArgument(parsedArgs, DefaultPort.ToString(), "-p", "--port");
      if(string.IsNullOrEmpty(ipAddress))
        CommandLine.ErrorExit("\nYou must supply an IP address in CIDR format.");
      if(string.IsNullOrEmpty(groupID) || !groupID.StartsWith("sg-"))
        CommandLine.ErrorExit("\nThe ID for a security group is missing or incorrect.");
      if(int.Parse(portStr) == 0)
        CommandLine.ErrorExit($"\nThe given TCP port number, {portStr}, isn't allowed.");

      // Add a rule to the given security group that allows
      // inbound traffic on a TCP port
      await AddIngressRule(
        new AmazonEC2Client(), groupID, ipAddress, int.Parse(portStr));
    }


    //
    // Method that adds a TCP ingress rule to a security group
    private static async Task AddIngressRule(
      IAmazonEC2 eC2Client, string groupID, string ipAddress, int port)
    {
      // Create an object to hold the request information for the rule.
      // It uses an IpPermission object to hold the IP information for the rule.
      var ingressRequest = new AuthorizeSecurityGroupIngressRequest{
        GroupId = groupID};
      ingressRequest.IpPermissions.Add(new IpPermission{
        IpProtocol = "tcp",
        FromPort = port,
        ToPort = port,
        Ipv4Ranges = new List<IpRange>() { new IpRange { CidrIp = ipAddress } }
      });

      // Create the inbound rule for the security group
      AuthorizeSecurityGroupIngressResponse responseIngress =
        await eC2Client.AuthorizeSecurityGroupIngressAsync(ingressRequest);
      Console.WriteLine($"\nNew RDP rule was written in {groupID} for {ipAddress}.");
      Console.WriteLine($"Result: {responseIngress.HttpStatusCode}");
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2AddRuleForRDP -g <group-id> -i <ip-address> [-p <port>]" +
        "\n  -g, --group-id: The ID of the security group to which you want to add the inbound rule." +
        "\n  -i, --ip-address: An IP address or address range in CIDR format." +
        "\n  -p, --port: The TCP port number. Defaults to 3389.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="authorize-ingress-additional"></a>
+ ポート番号を指定しない場合、アプリケーションはデフォルトでポート 3389 を使用します。これは Windows RDP 用のポートで、Windows が動作している EC2 インスタンスに接続できるようになります。Linux が動作している EC2 インスタンスを起動する場合は、代わりに TCP ポート 22 (SSH) を使用できます。
+ 例では `IpProtocol` が「tcp」にセットされている点に注目してください。`IpProtocol` の値は、[IpPermission](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIpPermission.html) クラスの `IpProtocol` プロパティに記述されています。
+ この例を使用する際に、お使いのローカルコンピュータの IP アドレスを確認する必要があるかもしれません。アドレスを取得する方法を以下にいくつか示します。
  + EC2 インスタンスに接続するローカルコンピュータが静的パブリック IP アドレスを持っている場合は、サービスを使用してそのアドレスを取得できます。サービスの一例としては [http://checkip.amazonaws.com/](http://checkip.amazonaws.com/) があります。インバウンドトラフィックの承認の詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[セキュリティグループにルールを追加する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/working-with-security-groups.html#adding-security-group-rule)」と「[さまざまなユースケースのセキュリティグループルール](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html)」を参照してください。
  + ローカルコンピュータの IP アドレスを取得する別の方法として、[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/v2/home#SecurityGroups)を使用できます。

    いずれかのセキュリティグループを選択し、[**Inbound rules**] (インバウンドルール) タブをクリックして [**Edit inbound rules**] (インバウンドのルールの編集) を選択します。インバウンドルールで [**Source**] (送信元) 列にあるドロップダウンメニューを開き、[**My IP**] (マイ IP) を選択して、ローカルコンピュータの IP アドレスを CIDR 形式で表示します。必ず操作を [**Cancel**] (キャンセル) するようにしてください。
+ [Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/v2/home#SecurityGroups)でセキュリティグループのリストを確認することにより、この例の結果を検証できます。

# Amazon EC2 のキーペアの使用
<a name="key-pairs"></a>

Amazon EC2 は公開キー暗号化を使用し、ログイン情報の暗号化と復号を行います。パブリックキー暗号ではパブリックキーを使用してデータを暗号化し、受信者はプライベートキーを使用してデータを復号します。パブリックキーとプライベートキーは、キーペアと呼ばれます。EC2 インスタンスにログインする場合、インスタンスの起動時にキーペアを指定し、接続時にキーペアのプライベートキーを指定する必要があります。

EC2 インスタンスを起動する際、キーペアを作成することもできますし、他のインスタンスの起動時に既に使用済みのキーペアを使用することもできます。Amazon EC2 キーペアについては、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon EC2 キーペアの操作](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)」を参照してください。

API の詳細と前提条件については、親セクション ([Amazon EC2 の使用](ec2-apis-intro.md)) を参照してください。

**Topics**
+ [キーペアの作成と表示](create-save-key-pair.md)
+ [キーペアの削除](delete-key-pairs.md)

# キーペアの作成と表示
<a name="create-save-key-pair"></a>

この例では、 AWS SDK for .NET を使用してキーペアを作成する方法を示します。アプリケーションは、新しいキーペア名と PEM ファイル名 (拡張子は「.pem」) を受け取ります。そしてキーペアを作成し、プライベートキーを PEM ファイルに書き込み、使用可能なすべてのキーペアを表示します。コマンドライン引数を指定しない場合、アプリケーションは単に使用可能なすべてのキーペアを表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#create-save-key-pair-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [キーペアを作成する](#create-save-key-pair-create)
+ [使用可能なキーペアの表示](#create-save-key-pair-display)
+ [コード全文](#create-save-key-pair-complete-code)
+ [その他の考慮事項](#create-save-key-pair-additional)

## キーペアを作成する
<a name="create-save-key-pair-create"></a>

次のスニペットではキーペアが作成され、指定された PEM ファイルにプライベートキーが保存されます。

[このトピックの最後](#create-save-key-pair-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to create a key pair and save the key material in a PEM file
    private static async Task CreateKeyPair(
      IAmazonEC2 ec2Client, string keyPairName, string pemFileName)
    {
      // Create the key pair
      CreateKeyPairResponse response =
        await ec2Client.CreateKeyPairAsync(new CreateKeyPairRequest{
          KeyName = keyPairName
        });
      Console.WriteLine($"\nCreated new key pair: {response.KeyPair.KeyName}");

      // Save the private key in a PEM file
      using (var s = new FileStream(pemFileName, FileMode.Create))
      using (var writer = new StreamWriter(s))
      {
        writer.WriteLine(response.KeyPair.KeyMaterial);
      }
    }
```

## 使用可能なキーペアの表示
<a name="create-save-key-pair-display"></a>

次のスニペットでは、利用可能なキーペアのリストが表示されます。

[このトピックの最後](#create-save-key-pair-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }
```

## コード全文
<a name="create-save-key-pair-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c21c15c11c19b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [CreateKeyPairRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateKeyPairRequest.html)

  クラス [CreateKeyPairResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateKeyPairResponse.html)

  クラス [DescribeKeyPairsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeKeyPairsResponse.html)

  クラス [KeyPairInfo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TKeyPairInfo.html)

### コード
<a name="w2aac19c15c21c15c11c19b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.IO;
using Amazon.EC2;
using Amazon.EC2.Model;
using System.Collections.Generic;

namespace EC2CreateKeyPair
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create and store a key pair
  class Program
  {
    static async Task Main(string[] args)
    {
      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        // In the case of no command-line arguments,
        // just show help and the existing key pairs
        PrintHelp();
        Console.WriteLine("\nNo arguments specified.");
        Console.Write(
          "Do you want to see a list of the existing key pairs? ((y) or n): ");
        string response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await EnumerateKeyPairs(ec2Client);
        return;
      }

      // Get the application arguments from the parsed list
      string keyPairName =
        CommandLine.GetArgument(parsedArgs, null, "-k", "--keypair-name");
      string pemFileName =
        CommandLine.GetArgument(parsedArgs, null, "-p", "--pem-filename");
      if(string.IsNullOrEmpty(keyPairName))
        CommandLine.ErrorExit("\nNo key pair name specified." +
          "\nRun the command with no arguments to see help.");
      if(string.IsNullOrEmpty(pemFileName) || !pemFileName.EndsWith(".pem"))
        CommandLine.ErrorExit("\nThe PEM filename is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create the key pair
      await CreateKeyPair(ec2Client, keyPairName, pemFileName);
      await EnumerateKeyPairs(ec2Client);
    }


    //
    // Method to create a key pair and save the key material in a PEM file
    private static async Task CreateKeyPair(
      IAmazonEC2 ec2Client, string keyPairName, string pemFileName)
    {
      // Create the key pair
      CreateKeyPairResponse response =
        await ec2Client.CreateKeyPairAsync(new CreateKeyPairRequest{
          KeyName = keyPairName
        });
      Console.WriteLine($"\nCreated new key pair: {response.KeyPair.KeyName}");

      // Save the private key in a PEM file
      using (var s = new FileStream(pemFileName, FileMode.Create))
      using (var writer = new StreamWriter(s))
      {
        writer.WriteLine(response.KeyPair.KeyMaterial);
      }
    }


    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2CreateKeyPair -k <keypair-name> -p <pem-filename>" +
        "\n  -k, --keypair-name: The name you want to assign to the key pair." +
        "\n  -p, --pem-filename: The name of the PEM file to create, with a \".pem\" extension.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="create-save-key-pair-additional"></a>
+ この例を実行した後、[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/#KeyPairs)で新しいキーペアを確認できます。
+ キーペアの作成時に、返されたプライベートキーを必ず保存する必要があります。後でプライベートキーを取得することはできないためです。

# キーペアの削除
<a name="delete-key-pairs"></a>

この例では、 AWS SDK for .NET を使用してキーペアを削除する方法を示します。アプリケーションはキーペア名を受け取ります。そのキーペアが削除された後に、使用可能なすべてのキーペアが表示されます。コマンドライン引数を指定しない場合、アプリケーションは単に使用可能なすべてのキーペアを表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#delete-key-pairs-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [キーペアの削除](#delete-key-pairs-create)
+ [使用可能なキーペアの表示](#delete-key-pairs-display)
+ [コード全文](#delete-key-pairs-complete-code)

## キーペアの削除
<a name="delete-key-pairs-create"></a>

次のスニペットでは、キーペアが削除されます。

[このトピックの最後](#delete-key-pairs-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to delete a key pair
    private static async Task DeleteKeyPair(IAmazonEC2 ec2Client, string keyName)
    {
      await ec2Client.DeleteKeyPairAsync(new DeleteKeyPairRequest{
        KeyName = keyName});
      Console.WriteLine($"\nKey pair {keyName} has been deleted (if it existed).");
    }
```

## 使用可能なキーペアの表示
<a name="delete-key-pairs-display"></a>

次のスニペットでは、利用可能なキーペアのリストが表示されます。

[このトピックの最後](#delete-key-pairs-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }
```

## コード全文
<a name="delete-key-pairs-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c21c15c13c19b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [https://docs.aws.amazon.com/sdkfornet/v4/apidocs/](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)

  クラス [DescribeKeyPairsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeKeyPairsResponse.html)

  クラス [KeyPairInfo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TKeyPairInfo.html)

### コード
<a name="w2aac19c15c21c15c13c19b7b1"></a>

```
using System;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2DeleteKeyPair
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      if(args.Length == 1)
      {
        // Delete a key pair (if it exists)
        await DeleteKeyPair(ec2Client, args[0]);

        // Display the key pairs that are left
        await EnumerateKeyPairs(ec2Client);
      }
      else
      {
        Console.WriteLine("\nUsage: EC2DeleteKeyPair keypair-name");
        Console.WriteLine("  keypair-name - The name of the key pair you want to delete.");
        Console.WriteLine("\nNo arguments specified.");
        Console.Write(
          "Do you want to see a list of the existing key pairs? ((y) or n): ");
        string response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await EnumerateKeyPairs(ec2Client);
      }
    }


    //
    // Method to delete a key pair
    private static async Task DeleteKeyPair(IAmazonEC2 ec2Client, string keyName)
    {
      await ec2Client.DeleteKeyPairAsync(new DeleteKeyPairRequest{
        KeyName = keyName});
      Console.WriteLine($"\nKey pair {keyName} has been deleted (if it existed).");
    }


    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }
  }
}
```

# Amazon EC2 のリージョンとアベイラビリティーゾーンの確認
<a name="using-regions-and-availability-zones"></a>

Amazon EC2 は、世界中の複数のロケーションでホスティングされています。これらの場所は、 リージョンとアベイラビリティーゾーンで構成されています。それぞれのリージョンは地理別に区別された地域であり、アベイラビリティーゾーンと呼ばれる複数の独立したロケーションを持っています。

リージョンとアベイラビリティーゾーンの詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[リージョンとゾーン](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)」を参照してください。

この例では、 を使用して EC2 クライアントに関連するリージョンとアベイラビリティーゾーンの詳細 AWS SDK for .NET を取得する方法を示します。アプリケーションは、EC2 クライアントで使用可能なリージョンとアベイラビリティーゾーンのリストを表示します。

## SDK リファレンス
<a name="w2aac19c15c21c17b9b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [DescribeAvailabilityZonesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeAvailabilityZonesResponse.html)

  クラス [DescribeRegionsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeRegionsResponse.html)

  クラス [AvailabilityZone](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TAvailabilityZone.html)

  クラス [Region](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRegion.html)

```
using System;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2RegionsAndZones
{
  class Program
  {
    static async Task Main(string[] args)
    {
      Console.WriteLine(
        "Finding the Regions and Availability Zones available to an EC2 client...");

      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      // Display the Regions and Availability Zones
      await DescribeRegions(ec2Client);
      await DescribeAvailabilityZones(ec2Client);
    }


    //
    // Method to display Regions
    private static async Task DescribeRegions(IAmazonEC2 ec2Client)
    {
      Console.WriteLine("\nRegions that are enabled for the EC2 client:");
      DescribeRegionsResponse response = await ec2Client.DescribeRegionsAsync();
      foreach (Region region in response.Regions)
        Console.WriteLine(region.RegionName);
    }


    //
    // Method to display Availability Zones
    private static async Task DescribeAvailabilityZones(IAmazonEC2 ec2Client)
    {
      Console.WriteLine("\nAvailability Zones for the EC2 client's region:");
      DescribeAvailabilityZonesResponse response =
        await ec2Client.DescribeAvailabilityZonesAsync();
      foreach (AvailabilityZone az in response.AvailabilityZones)
        Console.WriteLine(az.ZoneName);
    }
  }
}
```

# Amazon EC2 インスタンスの使用
<a name="how-to-ec2"></a>

を使用して AWS SDK for .NET 、作成、開始、終了などのオペレーションで Amazon EC2 インスタンスを制御できます。このセクションのトピックでは、その方法についての例をいくつか示します。EC2 インスタンスの詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon EC2 インスタンス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Instances.html)」を参照してください。

API の詳細と前提条件については、親セクション ([Amazon EC2 の使用](ec2-apis-intro.md)) を参照してください。

**Topics**
+ [EC2 インスタンスの起動](run-instance.md)
+ [EC2 インスタンスの終了](terminate-instance.md)

# Amazon EC2 インスタンスの起動
<a name="run-instance"></a>

この例では、 を使用して AWS SDK for .NET 、同じ Amazon マシンイメージ (AMI) から 1 つ以上の同一の設定の Amazon EC2 インスタンスを起動する方法を示します。アプリケーションは指定された[複数の入力](#run-instance-gather)を使用して EC2 インスタンスを起動し、インスタンスが「Pending」状態でなくなるまでインスタンスを監視します。

EC2 インスタンスが実行中の場合、「[(オプション) インスタンスへの接続](#connect-to-instance)」の説明に従ってインスタンスにリモートで接続できます。

**警告**  
EC2-Classic は 2022 年 8 月 15 日に廃止されました。EC2-Classic は、VPC への移行をお勧めします。詳細については、ブログ記事「[EC2-Classic Networking is Retiring - Here's How to Prepare](https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/)」を参照してください。

以下のセクションでは、この例のスニペットとその他の情報を確認できます。スニペットの下には、[この例のコードの全文](#run-instance-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [必要な要素を集める](#run-instance-gather)
+ [インスタンスの起動](#run-instance-launch)
+ [インスタンスのモニタリング](#run-instance-monitor)
+ [コード全文](#run-instance-complete-code)
+ [その他の考慮事項](#run-instance-additional)
+ [(オプション) インスタンスへの接続](#connect-to-instance)
+ [クリーンアップ](#run-instance-cleanup)

## 必要な要素を集める
<a name="run-instance-gather"></a>

EC2 インスタンスを起動するには、いくつかの要素が必要です。
+ インスタンスを起動する場所である [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/)。Windows インスタンスに RDP 経由で接続する場合、VPC にはインターネットゲートウェイが添付され、そのルートテーブル内にインターネットゲートウェイへのエントリを持つ必要があるのが普通です。詳細については、*Amazon VPC ユーザーガイド*の「[インターネットゲートウェイ](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html)」を参照してください。
+ インスタンスを起動する VPC 内の既存サブネットの ID。これを簡単に検索または作成するには、[Amazon VPC コンソール](https://console.aws.amazon.com/vpc/home#subnets)にサインインします。または、[CreateSubnetAsync](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/MEC2CreateSubnetAsyncCreateSubnetRequestCancellationToken.html)および[DescribeSubnetsAsync](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/MEC2DescribeSubnetsAsyncDescribeSubnetsRequestCancellationToken.html)メソッドを使用してプログラムで取得することもできます。
**注記**  
このパラメータを指定しなかった場合、アカウントのデフォルト VPC で新しいインスタンスが起動されます。
+ インスタンスを起動する VPC に属する既存のセキュリティグループの ID。詳細については、「[Amazon EC2 でのセキュリティグループの使用](security-groups.md)」を参照してください。
+ 新しいインスタンスに接続する場合は、前述のセキュリティグループにポート 22 で SSH トラフィックを許可する (Linux インスタンス) か、またはポート 3389 で RDP トラフィックを許可する (Windows インスタンス) 適切なインバウンドルールが設定されている必要があります。設定の方法については、「[セキュリティグループの更新](authorize-ingress.md)」を参照してください (トピックの最後近くにある「[その他の考慮事項](authorize-ingress.md#authorize-ingress-additional)」を含む)。
+ インスタンスの作成に使用する Amazon マシンイメージ (AMI)。AMI の詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon マシンイメージ (AMI)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)」を参照してください。特に、「[AMI の検索](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html)」と「[共有 AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharing-amis.html)」を参照してください。
+ 既存の EC2 キーペア名。これは新しいインスタンスへの接続に使用されます。詳細については、「[Amazon EC2 のキーペアの使用](key-pairs.md)」を参照してください。
+ 前述の EC2 キーペアのプライベートキーを含む PEM ファイルの名前。PEM ファイルは、インスタンスに[リモートで接続する](#connect-to-instance)場合に使用されます。

## インスタンスの起動
<a name="run-instance-launch"></a>

次のスニペットでは、EC2 インスタンスが起動します。

[このトピックの最後付近](#run-instance-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to launch the instances
    // Returns a list with the launched instance IDs
    private static async Task<List<string>> LaunchInstances(
      IAmazonEC2 ec2Client, RunInstancesRequest requestLaunch)
    {
      var instanceIds = new List<string>();
      RunInstancesResponse responseLaunch =
        await ec2Client.RunInstancesAsync(requestLaunch);

      Console.WriteLine("\nNew instances have been created.");
      foreach (Instance item in responseLaunch.Reservation.Instances)
      {
        instanceIds.Add(item.InstanceId);
        Console.WriteLine($"  New instance: {item.InstanceId}");
      }

      return instanceIds;
    }
```

## インスタンスのモニタリング
<a name="run-instance-monitor"></a>

次のスニペットでは、インスタンスが「Pending」状態でなくなるまでインスタンスを監視します。

[このトピックの最後あたり](#run-instance-complete-code)で、スニペットが実際に使用されている例を確認できます。

`Instance.State.Code` プロパティの有効な値については、[InstanceState](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceState.html) クラスを参照してください。

```
    //
    // Method to wait until the instances are running (or at least not pending)
    private static async Task CheckState(IAmazonEC2 ec2Client, List<string> instanceIds)
    {
      Console.WriteLine(
        "\nWaiting for the instances to start." +
        "\nPress any key to stop waiting. (Response might be slightly delayed.)");

      int numberRunning;
      DescribeInstancesResponse responseDescribe;
      var requestDescribe = new DescribeInstancesRequest{
        InstanceIds = instanceIds};

      // Check every couple of seconds
      int wait = 2000;
      while(true)
      {
        // Get and check the status for each of the instances to see if it's past pending.
        // Once all instances are past pending, break out.
        // (For this example, we are assuming that there is only one reservation.)
        Console.Write(".");
        numberRunning = 0;
        responseDescribe = await ec2Client.DescribeInstancesAsync(requestDescribe);
        foreach(Instance i in responseDescribe.Reservations[0].Instances)
        {
          // Check the lower byte of State.Code property
          // Code == 0 is the pending state
          if((i.State.Code & 255) > 0) numberRunning++;
        }
        if(numberRunning == responseDescribe.Reservations[0].Instances.Count)
          break;

        // Wait a bit and try again (unless the user wants to stop waiting)
        Thread.Sleep(wait);
        if(Console.KeyAvailable)
          break;
      }

      Console.WriteLine("\nNo more instances are pending.");
      foreach(Instance i in responseDescribe.Reservations[0].Instances)
      {
        Console.WriteLine($"For {i.InstanceId}:");
        Console.WriteLine($"  VPC ID: {i.VpcId}");
        Console.WriteLine($"  Instance state: {i.State.Name}");
        Console.WriteLine($"  Public IP address: {i.PublicIpAddress}");
        Console.WriteLine($"  Public DNS name: {i.PublicDnsName}");
        Console.WriteLine($"  Key pair name: {i.KeyName}");
      }
    }
```

## コード全文
<a name="run-instance-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c21c19b9c27b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)

  クラス [InstanceType](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceType.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [DescribeInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeInstancesRequest.html)

  クラス [DescribeInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeInstancesResponse.html)

  クラス [Instance](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstance.html)

  クラス [InstanceNetworkInterfaceSpecification](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceNetworkInterfaceSpecification.html)

  クラス [RunInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesRequest.html)

  クラス [RunInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesResponse.html)

### コード
<a name="w2aac19c15c21c19b9c27b7b1"></a>

```
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2LaunchInstance
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to launch an EC2 instance
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string groupID =
        CommandLine.GetArgument(parsedArgs, null, "-g", "--group-id");
      string ami =
        CommandLine.GetArgument(parsedArgs, null, "-a", "--ami-id");
      string keyPairName =
        CommandLine.GetArgument(parsedArgs, null, "-k", "--keypair-name");
      string subnetID =
        CommandLine.GetArgument(parsedArgs, null, "-s", "--subnet-id");
      if(   (string.IsNullOrEmpty(groupID) || !groupID.StartsWith("sg-"))
         || (string.IsNullOrEmpty(ami) || !ami.StartsWith("ami-"))
         || (string.IsNullOrEmpty(keyPairName))
         || (!string.IsNullOrEmpty(subnetID) && !subnetID.StartsWith("subnet-")))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create an EC2 client
      var ec2Client = new AmazonEC2Client();

      // Create an object with the necessary properties
      RunInstancesRequest request = GetRequestData(groupID, ami, keyPairName, subnetID);

      // Launch the instances and wait for them to start running
      var instanceIds = await LaunchInstances(ec2Client, request);
      await CheckState(ec2Client, instanceIds);
    }


    //
    // Method to put together the properties needed to launch the instance.
    private static RunInstancesRequest GetRequestData(
      string groupID, string ami, string keyPairName, string subnetID)
    {
      // Common properties
      var groupIDs = new List<string>() { groupID };
      var request = new RunInstancesRequest()
      {
        // The first three of these would be additional command-line arguments or similar.
        InstanceType = InstanceType.T1Micro,
        MinCount = 1,
        MaxCount = 1,
        ImageId = ami,
        KeyName = keyPairName
      };

      // Properties specifically for EC2 in a VPC.
      if(!string.IsNullOrEmpty(subnetID))
      {
        request.NetworkInterfaces =
          new List<InstanceNetworkInterfaceSpecification>() {
            new InstanceNetworkInterfaceSpecification() {
              DeviceIndex = 0,
              SubnetId = subnetID,
              Groups = groupIDs,
              AssociatePublicIpAddress = true
            }
          };
      }

      // Properties specifically for EC2-Classic
      else
      {
        request.SecurityGroupIds = groupIDs;
      }
      return request;
    }


    //
    // Method to launch the instances
    // Returns a list with the launched instance IDs
    private static async Task<List<string>> LaunchInstances(
      IAmazonEC2 ec2Client, RunInstancesRequest requestLaunch)
    {
      var instanceIds = new List<string>();
      RunInstancesResponse responseLaunch =
        await ec2Client.RunInstancesAsync(requestLaunch);

      Console.WriteLine("\nNew instances have been created.");
      foreach (Instance item in responseLaunch.Reservation.Instances)
      {
        instanceIds.Add(item.InstanceId);
        Console.WriteLine($"  New instance: {item.InstanceId}");
      }

      return instanceIds;
    }


    //
    // Method to wait until the instances are running (or at least not pending)
    private static async Task CheckState(IAmazonEC2 ec2Client, List<string> instanceIds)
    {
      Console.WriteLine(
        "\nWaiting for the instances to start." +
        "\nPress any key to stop waiting. (Response might be slightly delayed.)");

      int numberRunning;
      DescribeInstancesResponse responseDescribe;
      var requestDescribe = new DescribeInstancesRequest{
        InstanceIds = instanceIds};

      // Check every couple of seconds
      int wait = 2000;
      while(true)
      {
        // Get and check the status for each of the instances to see if it's past pending.
        // Once all instances are past pending, break out.
        // (For this example, we are assuming that there is only one reservation.)
        Console.Write(".");
        numberRunning = 0;
        responseDescribe = await ec2Client.DescribeInstancesAsync(requestDescribe);
        foreach(Instance i in responseDescribe.Reservations[0].Instances)
        {
          // Check the lower byte of State.Code property
          // Code == 0 is the pending state
          if((i.State.Code & 255) > 0) numberRunning++;
        }
        if(numberRunning == responseDescribe.Reservations[0].Instances.Count)
          break;

        // Wait a bit and try again (unless the user wants to stop waiting)
        Thread.Sleep(wait);
        if(Console.KeyAvailable)
          break;
      }

      Console.WriteLine("\nNo more instances are pending.");
      foreach(Instance i in responseDescribe.Reservations[0].Instances)
      {
        Console.WriteLine($"For {i.InstanceId}:");
        Console.WriteLine($"  VPC ID: {i.VpcId}");
        Console.WriteLine($"  Instance state: {i.State.Name}");
        Console.WriteLine($"  Public IP address: {i.PublicIpAddress}");
        Console.WriteLine($"  Public DNS name: {i.PublicDnsName}");
        Console.WriteLine($"  Key pair name: {i.KeyName}");
      }
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2LaunchInstance -g <group-id> -a <ami-id> -k <keypair-name> [-s <subnet-id>]" +
        "\n  -g, --group-id: The ID of the security group." +
        "\n  -a, --ami-id: The ID of an Amazon Machine Image." +
        "\n  -k, --keypair-name - The name of a key pair." +
        "\n  -s, --subnet-id: The ID of a subnet. Required only for EC2 in a VPC.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="run-instance-additional"></a>
+ EC2 インスタンスの状態をチェックするときに、[DescribeInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeInstancesRequest.html) オブジェクトの `Filter` プロパティにフィルターを追加できます。この方法を使用すると、リクエストを特定のインスタンス (ユーザーが指定した特定のタグを持つインスタンスなど) に制限できます。
+ 時間短縮のために、いくつかのプロパティには代表的な値が与えられています。これらのプロパティの一部またはすべてを、プログラムまたはユーザー入力で置き換えることができます。
+ [RunInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesRequest.html) オブジェクトの `MinCount` と `MaxCount` プロパティに使用できる値は、ターゲットのアベイラビリティーゾーンと、対象のインスタンスタイプに対して許可されているインスタンスの最大数によって決まります。詳細については、「Amazon EC2 よくある質問」の「[Amazon EC2 ではいくつのインスタンスを実行できますか?](https://aws.amazon.com/ec2/faqs/#How_many_instances_can_I_run_in_Amazon_EC2)」を参照してください。
+ この例とは異なるインスタンスタイプを使用する場合は、いくつかのインスタンスタイプから選択できます。詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon EC2 インスタンスタイプ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html)」を参照してください。「[インスタンスタイプの詳細](https://aws.amazon.com/ec2/instance-types/)」と「[インスタンスタイプエクスプローラー](https://aws.amazon.com/ec2/instance-explorer/)」も参照してください。
+ インスタンスの起動時に、インスタンスに [IAM ロール](net-dg-hosm.md)をアタッチすることもできます。そのためには、`Name` プロパティに IAM ロールの名前が設定された [IamInstanceProfileSpecification](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIamInstanceProfileSpecification.html) オブジェクトを作成します。次に、そのオブジェクトを [RunInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesRequest.html) オブジェクトの `IamInstanceProfile` プロパティに追加します。
**注記**  
IAM ロールが添付された EC2 インスタンスを起動するには、IAM ユーザーの設定に特定のアクセス許可が含まれている必要があります。必要なアクセス許可の詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[IAM ロールをインスタンスに渡すアクセス許可をユーザーに付与する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#permission-to-pass-iam-roles)」を参照してください。

## (オプション) インスタンスへの接続
<a name="connect-to-instance"></a>

インスタンスが実行状態になったら、適切なリモートクライアントを使用してインスタンスにリモート接続できます。Linux インスタンスと Windows インスタンスのいずれの場合も、インスタンスのパブリック IP アドレスまたは公開 DNS 名が必要です。また、以下も必要になります。

**Linux インスタンスの場合**

SSH クライアントを使用して Linux インスタンスに接続できます。「[セキュリティグループの更新](authorize-ingress.md)」の説明に従って、インスタンスの起動時に使用したセキュリティグループで、ポート 22 での SSH トラフィックが許可されていることを確認します。

また、インスタンスの起動に使用したキーペアのプライベート部分、すなわち PEM ファイルも必要です。

詳細については、「Amazon EC2 ユーザーガイド」の「[Linux インスタンスへの接続](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html)」を参照してください。

**Windows インスタンスの場合**

RDP クライアントを使用してお使いのインスタンスに接続できます。「[セキュリティグループの更新](authorize-ingress.md)」の説明に従って、インスタンスの起動時に使用したセキュリティグループで、ポート 3389 での RDP トラフィックが許可されていることを確認します。

また、管理者パスワードも必要です。取得するには、以下のコード例を使用します。その際、インスタンス ID とインスタンスの起動に使用されたキーペアのプライベート部分、すなわち PEM ファイルが必要です。

詳細については、「Amazon EC2 ユーザーガイド」の「[Windows インスタンスに接続する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connecting_to_windows_instance.html)」を参照してください。

**警告**  
このサンプルコードは、インスタンスの管理者パスワードをプレーンテキストで返します。

### SDK リファレンス
<a name="w2aac19c15c21c19b9c35c23b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [GetPasswordDataRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TGetPasswordDataRequest.html)

  クラス [GetPasswordDataResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TGetPasswordDataResponse.html)

### コード
<a name="w2aac19c15c21c19b9c35c25b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2GetWindowsPassword
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to get the Administrator password of a Windows EC2 instance
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string instanceID =
        CommandLine.GetArgument(parsedArgs, null, "-i", "--instance-id");
      string pemFileName =
        CommandLine.GetArgument(parsedArgs, null, "-p", "--pem-filename");
      if(   (string.IsNullOrEmpty(instanceID) || !instanceID.StartsWith("i-"))
         || (string.IsNullOrEmpty(pemFileName) || !pemFileName.EndsWith(".pem")))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      // Get and display the password
      string password = await GetPassword(ec2Client, instanceID, pemFileName);
      Console.WriteLine($"\nPassword: {password}");
    }


    //
    // Method to get the administrator password of a Windows EC2 instance
    private static async Task<string> GetPassword(
      IAmazonEC2 ec2Client, string instanceID, string pemFilename)
    {
      string password = string.Empty;
      GetPasswordDataResponse response =
        await ec2Client.GetPasswordDataAsync(new GetPasswordDataRequest{
          InstanceId = instanceID});
      if(response.PasswordData != null)
      {
        password = response.GetDecryptedPassword(File.ReadAllText(pemFilename));
      }
      else
      {
        Console.WriteLine($"\nThe password is not available for instance {instanceID}.");
        Console.WriteLine($"If this is a Windows instance, the password might not be ready.");
      }
      return password;
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2GetWindowsPassword -i <instance-id> -p pem-filename" +
        "\n  -i, --instance-id: The name of the EC2 instance." +
        "\n  -p, --pem-filename: The name of the PEM file with the private key.");
    }
  }

  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## クリーンアップ
<a name="run-instance-cleanup"></a>

EC2 インスタンスが不要になった場合は、「[Amazon EC2 インスタンスの終了](terminate-instance.md)」の説明に従って必ずインスタンスを終了してください。

# Amazon EC2 インスタンスの終了
<a name="terminate-instance"></a>

Amazon EC2 インスタンスが必要なくなったときは、それらを終了できます。

この例では、 AWS SDK for .NET を使用して EC2 インスタンスを終了する方法を示します。アプリケーションは入力としてインスタンス ID を受け取ります。

## SDK リファレンス
<a name="w2aac19c15c21c19c11b7b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [TerminateInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesRequest.html)

  クラス [TerminateInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesResponse.html)

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2TerminateInstance
{
  class Program
  {
    static async Task Main(string[] args)
    {
      if((args.Length == 1) && (args[0].StartsWith("i-")))
      {
        // Terminate the instance
        var ec2Client = new AmazonEC2Client();
        await TerminateInstance(ec2Client, args[0]);
      }
      else
      {
        Console.WriteLine("\nCommand-line argument missing or incorrect.");
        Console.WriteLine("\nUsage: EC2TerminateInstance instance-ID");
        Console.WriteLine("  instance-ID - The EC2 instance you want to terminate.");
        return;
      }
    }

    //
    // Method to terminate an EC2 instance
    private static async Task TerminateInstance(IAmazonEC2 ec2Client, string instanceID)
    {
      var request = new TerminateInstancesRequest{
        InstanceIds = new List<string>() { instanceID }};
      TerminateInstancesResponse response =
        await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{
          InstanceIds = new List<string>() { instanceID }
        });
      foreach (InstanceStateChange item in response.TerminatingInstances)
      {
        Console.WriteLine("Terminated instance: " + item.InstanceId);
        Console.WriteLine("Instance state: " + item.CurrentState.Name);
      }
    }
  }
}
```

この例を実行した後、[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/)にサインインして [EC2 インスタンス](https://console.aws.amazon.com/ec2/v2/home#Instances)の終了を確認することをお勧めします。

# Amazon EC2 スポットインスタンスのチュートリアル
<a name="how-to-spot-instances"></a>

このチュートリアルでは、 AWS SDK for .NET を使用して Amazon EC2 スポットインスタンスを管理する方法を示します。

## 概要:
<a name="tutor-spot-net-overview"></a>

スポットインスタンスでは、未使用の Amazon EC2 コンピューティング性能をオンデマンド料金よりも低価格でリクエストできます。これにより、中断が可能なアプリケーションの EC2 コストを大幅に削減できます。

スポットインスタンスのリクエスト方法と使用方法の概要は次のとおりです。

1. 支払う上限価格を指定して、スポットインスタンスリクエストを作成します。

1. リクエストが受理されたら、他の Amazon EC2 インスタンスと同様にインスタンスを実行します。

1. *スポット料金*の変更によってインスタンスが自動的に終了しない限り、必要な期間インスタンスを実行し、終了します。

1. 不要になったスポットインスタンスリクエストをクリーンアップして、スポットインスタンスがそれ以上作成されないようにします。

以上が、スポットインスタンスに関する非常に大まかな概要です。スポットインスタンスの詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[スポットインスタンス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html)」を参照してください。

## このチュートリアルの内容
<a name="about-spot-instances-tutorial"></a>

このチュートリアルに従うときは、 AWS SDK for .NET を使用して以下を実行します。
+ スポットインスタンスリクエストを作成する
+ スポットインスタンスリクエストが受理されたかどうかを判断する
+ スポットインスタンスリクエストをキャンセルする
+ 関連するインスタンスを終了させる

以下のセクションでは、この例のスニペットとその他の情報を確認できます。スニペットの下には、[この例のコードの全文](#tutor-spot-net-main)が示されており、そのままビルドして実行できます。

**Topics**
+ [概要:](#tutor-spot-net-overview)
+ [このチュートリアルの内容](#about-spot-instances-tutorial)
+ [前提条件](#tutor-spot-net-prereq)
+ [必要な要素を集める](#tutor-spot-net-gather)
+ [スポットインスタンスリクエストの作成](#tutor-spot-net-submit)
+ [スポットインスタンスリクエストの状態を判断する](#tutor-spot-net-request-state)
+ [スポットインスタンスリクエストのクリーンアップ](#tutor-spot-net-clean-up-request)
+ [スポットインスタンスのクリーンアップ](#tutor-spot-net-clean-up-instance)
+ [コード全文](#tutor-spot-net-main)
+ [その他の考慮事項](#tutor-spot-net-additional)

## 前提条件
<a name="tutor-spot-net-prereq"></a>

API の詳細と前提条件については、親セクション ([Amazon EC2 の使用](ec2-apis-intro.md)) を参照してください。

## 必要な要素を集める
<a name="tutor-spot-net-gather"></a>

スポットインスタンスリクエストを作成するには、いくつかの要素が必要です。
+ インスタンスの数とそのインスタンスタイプ。選択できるインスタンスタイプは複数あります。詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon EC2 インスタンスタイプ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html)」を参照してください。「[インスタンスタイプの詳細](https://aws.amazon.com/ec2/instance-types/)」と「[インスタンスタイプエクスプローラー](https://aws.amazon.com/ec2/instance-explorer/)」も参照してください。

  このチュートリアルでは、デフォルトの数は 1 です。
+ インスタンスの作成に使用する Amazon マシンイメージ (AMI)。AMI の詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon マシンイメージ (AMI)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)」を参照してください。特に、「[AMI の検索](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html)」と「[共有 AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharing-amis.html)」を参照してください。
+ インスタンス時間あたりに支払う上限価格。すべてのインスタンスタイプ (オンデマンドインスタンスとスポットインスタンスの両方) の料金は、[Amazon EC2 の料金ページ](https://aws.amazon.com/ec2/pricing/)で確認いただけます。このチュートリアルのデフォルト料金については、後で説明します。
+ インスタンスにリモートで接続する場合は、適切な構成とリソースを持つセキュリティグループ。この詳細については「[Amazon EC2 でのセキュリティグループの使用](security-groups.md)」で説明されており、[必要な要素の収集](run-instance.md#run-instance-gather)と[インスタンスへの接続](run-instance.md#connect-to-instance)に関する情報は「[Amazon EC2 インスタンスの起動](run-instance.md)」で説明されています。簡単にするために、このチュートリアルではすべての新しい AWS アカウントに存在する **default** という名前のセキュリティグループを使用します。

スポットインスタンスをリクエストするには複数の方法があります。一般的な戦略は以下のとおりです。
+ オンデマンド料金を明確に下回るようにリクエストを作成します。
+ 計算結果の価値に基づいてリクエストを作成します。
+ コンピューティング性能をできるだけ早く獲得するようにリクエストを作成します。

以下の説明は、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[スポットインスタンスの料金履歴](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances-history.html)」を示しています。

### コストをオンデマンドよりも削減する
<a name="reduce-cost"></a>

実行完了までに何時間も、あるいは何日間もかかるバッチ処理ジョブがあるとします。ただし、いつ開始していつ終了するかについては、特に決められていないものとします。このジョブを完了するためのコストを、オンデマンドインスタンスを使用する場合よりも低くできるかどうかを考えます。

Amazon EC2 コンソールまたは Amazon EC2 API を使用して、インスタンスタイプ別のスポット料金の履歴を調べます。使用したいインスタンスタイプの、特定のアベイラビリティーゾーンでの価格履歴を分析した後は、リクエストのアプローチとして次の 2 つも考えられます。
+ スポット料金の範囲の上限 (ただしオンデマンド料金よりは下) でリクエストを指定します。こうすることで、この 1 回限りのスポットリクエストが受理されて、ジョブが完了するまで連続して実行される可能性が高くなります。
+ 価格範囲の下限でリクエストを指定し、1 つの永続リクエストで次々とインスタンスを起動するよう計画を立てます。これらのインスタンスの実行時間を合計すると、ジョブを完了するのに十分な長さとなり、合計コストも低くなります。

### 結果の価値以上は支払わない
<a name="value-of-result"></a>

データ処理ジョブを実行するとします。このジョブの結果が持つ価値は判明しており、計算コストに換算してどれくらいになるかもわかっています。

使用するインスタンスタイプのスポット料金履歴の分析が完了したら、計算時間のコストがこのジョブの結果の価値を上回ることのないように料金を選択します。永続リクエストを作成し、スポット料金がリクエスト以下となったときに断続的に実行するよう設定します。

### コンピューティング性能をすぐに獲得する
<a name="acquire-quickly"></a>

追加のコンピューティング性能が突然、短期間だけ必要になり、オンデマンドインスタンスではそのコンピューティング性能を確保できないとします。使用するインスタンスタイプのスポット料金履歴の分析が完了したら、履歴での最高料金を超える料金を選択します。こうすることで、リクエストがすぐに受理され、計算が完了するまで連続して計算できる可能性が飛躍的に高まります。

必要な要素を集めて戦略を選択したら、スポットインスタンスをリクエストする準備ができました。このチュートリアルでは、デフォルトの最大スポットインスタンス料金をオンデマンド料金と同額 (このチュートリアルでは 0.003 ドル) に設定します。このように料金を設定すると、リクエストが達成される可能性が最大になります。

## スポットインスタンスリクエストの作成
<a name="tutor-spot-net-submit"></a>

次のスニペットでは、上記で集めた要素を使用してスポットインスタンスリクエストを作成する方法を示しています。

[このトピックの最後](#tutor-spot-net-main)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to create a Spot Instance request
    private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest(
      IAmazonEC2 ec2Client, string amiId, string securityGroupName,
      InstanceType instanceType, string spotPrice, int instanceCount)
    {
      var launchSpecification = new LaunchSpecification{
        ImageId = amiId,
        InstanceType = instanceType
      };
      launchSpecification.SecurityGroups.Add(securityGroupName);
      var request = new RequestSpotInstancesRequest{
        SpotPrice = spotPrice,
        InstanceCount = instanceCount,
        LaunchSpecification = launchSpecification
      };

      RequestSpotInstancesResponse result =
        await ec2Client.RequestSpotInstancesAsync(request);
      return result.SpotInstanceRequests[0];
    }
```

このメソッドから返される重要な値は、スポットインスタンスリクエスト ID です。これは返された [SpotInstanceRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSpotInstanceRequest.html) オブジェクトの `SpotInstanceRequestId` メンバーに含まれています。

**注記**  
起動したすべてのスポットインスタンスに対して料金が発生します。不要なコストを回避するには、[リクエストをキャンセル](#tutor-spot-net-clean-up-request)して[インスタンスを削除](#tutor-spot-net-clean-up-instance)するようにしてください。

## スポットインスタンスリクエストの状態を判断する
<a name="tutor-spot-net-request-state"></a>

次のスニペットでは、スポットインスタンスリクエストに関する情報を取得する方法を示しています。この情報を使用して、スポットインスタンスリクエストが受理されるのを待つかどうかといった特定の決定をコード内で下すことができます。

[このトピックの最後](#tutor-spot-net-main)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to get information about a Spot Instance request, including the status,
    // instance ID, etc.
    // It gets the information for a specific request (as opposed to all requests).
    private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);
      return describeResponse.SpotInstanceRequests[0];
    }
```

このメソッドでは、スポットインスタンスリクエストに関する情報 (インスタンス ID、状態、ステータスコードなど) が返されます。スポットインスタンスリクエストのステータスコードの詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[スポットリクエストのステータス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html#spot-instance-bid-status-understand)」を参照してください。

## スポットインスタンスリクエストのクリーンアップ
<a name="tutor-spot-net-clean-up-request"></a>

スポットインスタンスをリクエストする必要がなくなった場合、未処理のリクエストをキャンセルして、リクエストが再び受理されないようにすることが重要です。次のスニペットでは、スポットインスタンスリクエストをキャンセルする方法を示しています。

[このトピックの最後](#tutor-spot-net-main)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to cancel a Spot Instance request
    private static async Task CancelSpotInstanceRequest(
      IAmazonEC2 ec2Client, string requestId)
    {
      var cancelRequest = new CancelSpotInstanceRequestsRequest();
      cancelRequest.SpotInstanceRequestIds.Add(requestId);

      await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest);
    }
```

## スポットインスタンスのクリーンアップ
<a name="tutor-spot-net-clean-up-instance"></a>

不要なコストを回避するには、スポットインスタンスリクエストから起動したインスタンスをすべて終了させることが重要です。単にスポットインスタンスリクエストをキャンセルするだけではインスタンスは終了しないので、引き続きインスタンスに対して料金が発生することになります。次のスニペットでは、アクティブなスポットインスタンスのインスタンス識別子を取得した後にインスタンスを終了する方法を示しています。

[このトピックの最後](#tutor-spot-net-main)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to terminate a Spot Instance
    private static async Task TerminateSpotInstance(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      // Retrieve the Spot Instance request to check for running instances.
      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);

      // If there are any running instances, terminate them
      if(   (describeResponse.SpotInstanceRequests[0].Status.Code
              == "request-canceled-and-instance-running")
         || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active))
      {
        TerminateInstancesResponse response =
          await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{
            InstanceIds = new List<string>(){
              describeResponse.SpotInstanceRequests[0].InstanceId } });
        foreach (InstanceStateChange item in response.TerminatingInstances)
        {
          Console.WriteLine($"\n  Terminated instance: {item.InstanceId}");
          Console.WriteLine($"  Instance state: {item.CurrentState.Name}\n");
        }
      }
    }
```

## コード全文
<a name="tutor-spot-net-main"></a>

次のコード例では、前述のメソッドを呼び出して、スポットインスタンスリクエストを作成およびキャンセルし、スポットインスタンスを終了しています。

### SDK リファレンス
<a name="w2aac19c15c21c21c43b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

プログラミング要素:
+ 名前空間 [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  クラス [AmazonEC2Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)

  クラス [InstanceType](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceType.html)
+ 名前空間 [Amazon.EC2.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  クラス [CancelSpotInstanceRequestsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCancelSpotInstanceRequestsRequest.html)

  クラス [DescribeSpotInstanceRequestsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSpotInstanceRequestsRequest.html)

  クラス [DescribeSpotInstanceRequestsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSpotInstanceRequestsResponse.html)

  クラス [InstanceStateChange](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceStateChange.html)

  クラス [LaunchSpecification](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TLaunchSpecification.html)

  クラス [RequestSpotInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRequestSpotInstancesRequest.html)

  クラス [RequestSpotInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRequestSpotInstancesResponse.html)

  クラス [SpotInstanceRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSpotInstanceRequest.html)

  クラス [TerminateInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesRequest.html)

  クラス [TerminateInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesResponse.html)

### コード
<a name="w2aac19c15c21c21c43b7b1"></a>

```
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2SpotInstanceRequests
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Some default values.
      // These could be made into command-line arguments instead.
      var instanceType = InstanceType.T1Micro;
      string securityGroupName = "default";
      string spotPrice = "0.003";
      int instanceCount = 1;

      // Parse the command line arguments
      if((args.Length != 1) || (!args[0].StartsWith("ami-")))
      {
        Console.WriteLine("\nUsage: EC2SpotInstanceRequests ami");
        Console.WriteLine("  ami: the Amazon Machine Image to use for the Spot Instances.");
        return;
      }

      // Create the Amazon EC2 client.
      var ec2Client = new AmazonEC2Client();

      // Create the Spot Instance request and record its ID
      Console.WriteLine("\nCreating spot instance request...");
      var req = await CreateSpotInstanceRequest(
        ec2Client, args[0], securityGroupName, instanceType, spotPrice, instanceCount);
      string requestId = req.SpotInstanceRequestId;

      // Wait for an EC2 Spot Instance to become active
      Console.WriteLine(
        $"Waiting for Spot Instance request with ID {requestId} to become active...");
      int wait = 1;
      var start = DateTime.Now;
      while(true)
      {
        Console.Write(".");

        // Get and check the status to see if the request has been fulfilled.
        var requestInfo = await GetSpotInstanceRequestInfo(ec2Client, requestId);
        if(requestInfo.Status.Code == "fulfilled")
        {
          Console.WriteLine($"\nSpot Instance request {requestId} " +
            $"has been fulfilled by instance {requestInfo.InstanceId}.\n");
          break;
        }

        // Wait a bit and try again, longer each time (1, 2, 4, ...)
        Thread.Sleep(wait);
        wait = wait * 2;
      }

      // Show the user how long it took to fulfill the Spot Instance request.
      TimeSpan span = DateTime.Now.Subtract(start);
      Console.WriteLine($"That took {span.TotalMilliseconds} milliseconds");

      // Perform actions here as needed.
      // For this example, simply wait for the user to hit a key.
      // That gives them a chance to look at the EC2 console to see
      // the running instance if they want to.
      Console.WriteLine("Press any key to start the cleanup...");
      Console.ReadKey(true);

      // Cancel the request.
      // Do this first to make sure that the request can't be re-fulfilled
      // once the Spot Instance has been terminated.
      Console.WriteLine("Canceling Spot Instance request...");
      await CancelSpotInstanceRequest(ec2Client, requestId);

      // Terminate the Spot Instance that's running.
      Console.WriteLine("Terminating the running Spot Instance...");
      await TerminateSpotInstance(ec2Client, requestId);

      Console.WriteLine("Done. Press any key to exit...");
      Console.ReadKey(true);
    }


    //
    // Method to create a Spot Instance request
    private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest(
      IAmazonEC2 ec2Client, string amiId, string securityGroupName,
      InstanceType instanceType, string spotPrice, int instanceCount)
    {
      var launchSpecification = new LaunchSpecification{
        ImageId = amiId,
        InstanceType = instanceType
      };
      launchSpecification.SecurityGroups.Add(securityGroupName);
      var request = new RequestSpotInstancesRequest{
        SpotPrice = spotPrice,
        InstanceCount = instanceCount,
        LaunchSpecification = launchSpecification
      };

      RequestSpotInstancesResponse result =
        await ec2Client.RequestSpotInstancesAsync(request);
      return result.SpotInstanceRequests[0];
    }


    //
    // Method to get information about a Spot Instance request, including the status,
    // instance ID, etc.
    // It gets the information for a specific request (as opposed to all requests).
    private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);
      return describeResponse.SpotInstanceRequests[0];
    }


    //
    // Method to cancel a Spot Instance request
    private static async Task CancelSpotInstanceRequest(
      IAmazonEC2 ec2Client, string requestId)
    {
      var cancelRequest = new CancelSpotInstanceRequestsRequest();
      cancelRequest.SpotInstanceRequestIds.Add(requestId);

      await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest);
    }


    //
    // Method to terminate a Spot Instance
    private static async Task TerminateSpotInstance(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      // Retrieve the Spot Instance request to check for running instances.
      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);

      // If there are any running instances, terminate them
      if(   (describeResponse.SpotInstanceRequests[0].Status.Code
              == "request-canceled-and-instance-running")
         || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active))
      {
        TerminateInstancesResponse response =
          await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{
            InstanceIds = new List<string>(){
              describeResponse.SpotInstanceRequests[0].InstanceId } });
        foreach (InstanceStateChange item in response.TerminatingInstances)
        {
          Console.WriteLine($"\n  Terminated instance: {item.InstanceId}");
          Console.WriteLine($"  Instance state: {item.CurrentState.Name}\n");
        }
      }
    }
  }
}
```

## その他の考慮事項
<a name="tutor-spot-net-additional"></a>
+ チュートリアルを実行したら、[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/)にサインインして、[スポットインスタンスリクエスト](https://console.aws.amazon.com/ec2/home#SpotInstances:)がキャンセル済みで[スポットインスタンス](https://console.aws.amazon.com/ec2/v2/home#Instances)が終了していることを確認するようお勧めします。

# を使用した AWS Identity and Access Management (IAM) へのアクセス AWS SDK for .NET
<a name="iam-apis-intro"></a>

は AWS SDK for .NET をサポートしています。これは[AWS Identity and Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/)、 AWS お客様がユーザーとユーザーのアクセス許可を管理できるようにするウェブサービスです AWS。

 AWS Identity and Access Management (IAM) *ユーザーは*、ユーザーが作成するエンティティです AWS。エンティティは、 がやり取りするユーザーまたはアプリケーションを表します AWS。IAM ユーザーの詳細については、IAM ユーザーガイドの「[IAM ユーザー](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)」および「[IAM と STS の制限](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html)」を参照してください。

IAM *ポリシー*を作成することによって、ユーザーにアクセス許可を付与します。ポリシーには、ユーザーが実行できるアクションと、そのアクションによって影響を受けるリソースの一覧が記載された*ポリシードキュメント*が含まれています。IAM ポリシーの詳細については、*IAM ユーザーガイド*の「[ポリシーとアクセス許可](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)」を参照してください。

**警告**  
セキュリティリスクを避けるため、専用ソフトウェアを開発するときや実際のデータを扱うときは、IAM ユーザーを認証に使用しないでください。代わりに、[AWS IAM アイデンティティセンター](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html) などの ID プロバイダーとのフェデレーションを使用してください。

## API
<a name="w2aac19c15c23c13"></a>

 AWS SDK for .NET は、IAM クライアント用の APIs を提供します。API を使用すると、ユーザー、ロール、アクセスキーなどの IAM の機能を操作できます。

このセクションでは、これらの API を操作する際に活用できるパターンを示すいくつかの例を紹介します。API の完全なセットを確認するには、[AWS SDK for .NET API リファレンス](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)を参照してください (「Amazon.IdentityManagement」までスクロールします)。

このセクションには、認証情報の管理を容易にするために IAM ロールを Amazon EC2 インスタンスにアタッチする方法を示す[例](net-dg-hosm.md)も含まれています。

IAM API は、[AWSSDK.IdentityManagement](https://www.nuget.org/packages/AWSSDK.IdentityManagement) NuGet パッケージで提供されます。

## 前提条件
<a name="w2aac19c15c23c15"></a>

開始する前に、[環境をセットアップ](net-dg-config.md)し、[プロジェクトを設定した](configuring-the-sdk.md)ことを確認してください。また、「[SDK の使用](net-dg-sdk-features.md)」の情報を確認してください。

## トピック
<a name="w2aac19c15c23c17"></a>

**Topics**
+ [API](#w2aac19c15c23c13)
+ [前提条件](#w2aac19c15c23c15)
+ [トピック](#w2aac19c15c23c17)
+ [JSON からのマネージドポリシーの作成](iam-policies-create-json.md)
+ [ポリシードキュメントの表示](iam-policies-display.md)
+ [ロールを使用したアクセス権の付与](net-dg-hosm.md)

# JSON からの IAM マネージドポリシーの作成
<a name="iam-policies-create-json"></a>

この例では、 AWS SDK for .NET を使用して、JSON の特定の[ポリシードキュメントから IAM 管理](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies)ポリシーを作成する方法を示します。アプリケーションは IAM クライアントオブジェクトを作成し、ファイルからポリシードキュメントを読み取ってポリシーを作成します。

**注記**  
JSON 形式のポリシードキュメントの例については、このトピックの最後にある[その他の考慮事項](#iam-policies-create-json-additional)を参照してください。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#iam-policies-create-json-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [ポリシーの作成](#iam-policies-create-json-create)
+ [コード全文](#iam-policies-create-json-complete-code)
+ [その他の考慮事項](#iam-policies-create-json-additional)

## ポリシーの作成
<a name="iam-policies-create-json-create"></a>

次のスニペットでは、指定された名前とポリシードキュメントを使用して IAM マネージドポリシーを作成します。

[このトピックの最後](#iam-policies-create-json-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to create an IAM policy from a JSON file
    private static async Task<CreatePolicyResponse> CreateManagedPolicy(
      IAmazonIdentityManagementService iamClient, string policyName, string jsonFilename)
    {
      return await iamClient.CreatePolicyAsync(new CreatePolicyRequest{
        PolicyName = policyName,
        PolicyDocument = File.ReadAllText(jsonFilename)});
    }
```

## コード全文
<a name="iam-policies-create-json-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c23c21c17b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.IdentityManagement](https://www.nuget.org/packages/AWSSDK.IdentityManagement)

プログラミング要素:
+ 名前空間 [Amazon.IdentityManagement](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAM.html)

  クラス [AmazonIdentityManagementServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TIAMServiceClient.html)
+ 名前空間 [Amazon.IdentityManagement.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAMModel.html)

  クラス [CreatePolicyRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TCreatePolicyRequest.html)

  クラス [CreatePolicyResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TCreatePolicyResponse.html)

### コード
<a name="w2aac19c15c23c21c17b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.IdentityManagement;
using Amazon.IdentityManagement.Model;

namespace IamCreatePolicyFromJson
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create an IAM policy with a given policy document
  class Program
  {
    private const int MaxArgs = 2;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if((parsedArgs.Count == 0) || (parsedArgs.Count > MaxArgs))
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string policyName =
        CommandLine.GetArgument(parsedArgs, null, "-p", "--policy-name");
      string policyFilename =
        CommandLine.GetArgument(parsedArgs, null, "-j", "--json-filename");
      if(   string.IsNullOrEmpty(policyName)
         || (string.IsNullOrEmpty(policyFilename) || !policyFilename.EndsWith(".json")))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create an IAM service client
      var iamClient = new AmazonIdentityManagementServiceClient();

      // Create the new policy
      var response = await CreateManagedPolicy(iamClient, policyName, policyFilename);
      Console.WriteLine($"\nPolicy {response.Policy.PolicyName} has been created.");
      Console.WriteLine($"  Arn: {response.Policy.Arn}");
    }


    //
    // Method to create an IAM policy from a JSON file
    private static async Task<CreatePolicyResponse> CreateManagedPolicy(
      IAmazonIdentityManagementService iamClient, string policyName, string jsonFilename)
    {
      return await iamClient.CreatePolicyAsync(new CreatePolicyRequest{
        PolicyName = policyName,
        PolicyDocument = File.ReadAllText(jsonFilename)});
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: IamCreatePolicyFromJson -p <policy-name> -j <json-filename>" +
        "\n  -p, --policy-name: The name you want the new policy to have." +
        "\n  -j, --json-filename: The name of the JSON file with the policy document.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="iam-policies-create-json-additional"></a>
+ 次に示すポリシードキュメントの例を JSON ファイルにコピーして、このアプリケーションの入力として使用できます。

------
#### [ JSON ]

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Id"  : "DotnetTutorialPolicy",
    "Statement" : [
      {
        "Sid" : "DotnetTutorialPolicyS3",
        "Effect" : "Allow",
        "Action" : [
          "s3:Get*",
          "s3:List*"
        ],
        "Resource" : "*"
      },
      {
        "Sid" : "DotnetTutorialPolicyPolly",
        "Effect": "Allow",
        "Action": [
          "polly:DescribeVoices",
          "polly:SynthesizeSpeech"
        ],
        "Resource": "*"
      }
    ]
  }
  ```

------
+ ポリシーが作成されたことを [IAM コンソール](https://console.aws.amazon.com/iam/home#/policies)で確認できます。[**Filter policies**] (フィルターポリシー) ドロップダウンリストで、[**Customer managed**] (カスタマー管理) を選択します。ポリシーが不要になった場合は削除します。
+  ポリシー作成の詳細については、[IAM ユーザーガイド](https://docs.aws.amazon.com/IAM/latest/UserGuide/)の「[IAM ポリシーの作成](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html)」と「[IAM JSON ポリシーリファレンス](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html)」を参照してください。

# IAM マネージドポリシーのポリシードキュメントの表示
<a name="iam-policies-display"></a>

この例では、 AWS SDK for .NET を使用してポリシードキュメントを表示する方法を示します。アプリケーションは IAM クライアントオブジェクトを作成し、指定された IAM マネージドポリシーのデフォルトバージョンを検索して、JSON 形式のポリシードキュメントを表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#iam-policies-display-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [デフォルトバージョンの検索](#iam-policies-display-version)
+ [ポリシードキュメントの表示](#iam-policies-display-doc)
+ [コード全文](#iam-policies-display-complete-code)

## デフォルトバージョンの検索
<a name="iam-policies-display-version"></a>

次のスニペットでは、指定された IAM ポリシーのデフォルトバージョンを検索します。

[このトピックの最後](#iam-policies-display-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to determine the default version of an IAM policy
    // Returns a string with the version
    private static async Task<string> GetDefaultVersion(
      IAmazonIdentityManagementService iamClient, string policyArn)
    {
      // Retrieve all the versions of this policy
      string defaultVersion = string.Empty;
      ListPolicyVersionsResponse reponseVersions =
        await iamClient.ListPolicyVersionsAsync(new ListPolicyVersionsRequest{
          PolicyArn = policyArn});

      // Find the default version
      foreach(PolicyVersion version in reponseVersions.Versions)
      {
        if(version.IsDefaultVersion)
        {
          defaultVersion = version.VersionId;
          break;
        }
      }

      return defaultVersion;
    }
```

## ポリシードキュメントの表示
<a name="iam-policies-display-doc"></a>

次のスニペットでは、指定された IAM ポリシーの JSON 形式のポリシードキュメントを表示します。

[このトピックの最後](#iam-policies-display-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to retrieve and display the policy document of an IAM policy
    private static async Task ShowPolicyDocument(
      IAmazonIdentityManagementService iamClient, string policyArn, string defaultVersion)
    {
      // Retrieve the policy document of the default version
      GetPolicyVersionResponse responsePolicy =
        await iamClient.GetPolicyVersionAsync(new GetPolicyVersionRequest{
          PolicyArn = policyArn,
          VersionId = defaultVersion});

      // Display the policy document (in JSON)
      Console.WriteLine($"Version {defaultVersion} of the policy (in JSON format):");
      Console.WriteLine(
        $"{HttpUtility.UrlDecode(responsePolicy.PolicyVersion.Document)}");
    }
```

## コード全文
<a name="iam-policies-display-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c23c23c19b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.IdentityManagement](https://www.nuget.org/packages/AWSSDK.IdentityManagement)

プログラミング要素:
+ 名前空間 [Amazon.IdentityManagement](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAM.html)

  クラス [AmazonIdentityManagementServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TIAMServiceClient.html)
+ 名前空間 [Amazon.IdentityManagement.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAMModel.html)

  クラス [GetPolicyVersionRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TGetPolicyVersionRequest.html)

  クラス [GetPolicyVersionResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TGetPolicyVersionResponse.html)

  クラス [ListPolicyVersionsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TListPolicyVersionsRequest.html)

  クラス [ListPolicyVersionsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TListPolicyVersionsResponse.html)

  クラス [PolicyVersion](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TPolicyVersion.html)

### コード
<a name="w2aac19c15c23c23c19b7b1"></a>

```
using System;
using System.Web;
using System.Threading.Tasks;
using Amazon.IdentityManagement;
using Amazon.IdentityManagement.Model;

namespace IamDisplayPolicyJson
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      if(args.Length != 1)
      {
        Console.WriteLine("\nUsage: IamDisplayPolicyJson policy-arn");
        Console.WriteLine("   policy-arn: The ARN of the policy to retrieve.");
        return;
      }
      if(!args[0].StartsWith("arn:"))
      {
        Console.WriteLine("\nCould not find policy ARN in the command-line arguments:");
        Console.WriteLine($"{args[0]}");
        return;
      }

      // Create an IAM service client
      var iamClient = new AmazonIdentityManagementServiceClient();

      // Retrieve and display the policy document of the given policy
      string defaultVersion = await GetDefaultVersion(iamClient, args[0]);
      if(string.IsNullOrEmpty(defaultVersion))
        Console.WriteLine($"Could not find the default version for policy {args[0]}.");
      else
        await ShowPolicyDocument(iamClient, args[0], defaultVersion);
    }


    //
    // Method to determine the default version of an IAM policy
    // Returns a string with the version
    private static async Task<string> GetDefaultVersion(
      IAmazonIdentityManagementService iamClient, string policyArn)
    {
      // Retrieve all the versions of this policy
      string defaultVersion = string.Empty;
      ListPolicyVersionsResponse reponseVersions =
        await iamClient.ListPolicyVersionsAsync(new ListPolicyVersionsRequest{
          PolicyArn = policyArn});

      // Find the default version
      foreach(PolicyVersion version in reponseVersions.Versions)
      {
        if(version.IsDefaultVersion)
        {
          defaultVersion = version.VersionId;
          break;
        }
      }

      return defaultVersion;
    }


    //
    // Method to retrieve and display the policy document of an IAM policy
    private static async Task ShowPolicyDocument(
      IAmazonIdentityManagementService iamClient, string policyArn, string defaultVersion)
    {
      // Retrieve the policy document of the default version
      GetPolicyVersionResponse responsePolicy =
        await iamClient.GetPolicyVersionAsync(new GetPolicyVersionRequest{
          PolicyArn = policyArn,
          VersionId = defaultVersion});

      // Display the policy document (in JSON)
      Console.WriteLine($"Version {defaultVersion} of the policy (in JSON format):");
      Console.WriteLine(
        $"{HttpUtility.UrlDecode(responsePolicy.PolicyVersion.Document)}");
    }
  }
}
```

# IAM ロールを使用したアクセス権の付与
<a name="net-dg-hosm"></a>

このチュートリアルでは、 AWS SDK for .NET を使用して Amazon EC2 インスタンスで IAM ロールを有効にする方法を示します。

## 概要:
<a name="hosm-overview"></a>

へのすべてのリクエストは、 によって発行された認証情報を使用して暗号化して署名 AWS する必要があります AWS。したがって、Amazon EC2 インスタンスで実行するアプリケーション用の認証情報を管理するための戦略が必要です。これらの認証情報を、アプリケーションからのアクセスを維持したまま安全に配信、保存、ローテーションする必要があります。

IAM ロールを使用すると、認証情報を効果的に管理できます。IAM ロールを作成し、アプリケーションに必要なアクセス許可を使用して設定を行った後で、そのロールを EC2 インスタンスにアタッチします。IAM ロールを使用する利点の詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Amazon EC2 の IAM ロール](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)」を参照してください。また、IAM ユーザーガイドの「[IAM ロール](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)」の情報も参照してください。

を使用して構築されたアプリケーションの場合 AWS SDK for .NET、アプリケーションが AWS サービスのクライアントオブジェクトを構築すると、オブジェクトはいくつかの潜在的なソースから認証情報を検索します。検索の順序は、「[認証情報とプロファイルの解決](creds-assign.md)」に示されています。

クライアントオブジェクトが他のソースから認証情報を見つけられなかった場合、クライアントオブジェクトは IAM ロールに設定された、EC2 インスタンスのメタデータにあるものと同じアクセス許可を持つ一時的な認証情報を取得します。これらの認証情報は、クライアントオブジェクト AWS から を呼び出すために使用されます。

## このチュートリアルの内容
<a name="about-hosm-tutorial"></a>

このチュートリアルでは、 AWS SDK for .NET (およびその他のツール) を使用して IAM ロールがアタッチされた Amazon EC2 インスタンスを起動し、IAM ロールのアクセス許可を使用してインスタンス上のアプリケーションを確認します。

**Topics**
+ [概要:](#hosm-overview)
+ [このチュートリアルの内容](#about-hosm-tutorial)
+ [サンプルの Amazon S3 アプリケーションの作成](#net-dg-hosm-sample-s3-app)
+ [IAM ロールの作成](#net-dg-hosm-create-the-role)
+ [EC2 インスタンスの起動と IAM ロールのアタッチ](#net-dg-hosm-launch-ec2-instance)
+ [EC2 インスタンスへの接続](#net-dg-hosm-connect)
+ [EC2 インスタンスでのサンプルアプリケーションの実行](#net-dg-hosm-run-the-app)
+ [クリーンアップ](#net-dg-hosm-cleanup)

## サンプルの Amazon S3 アプリケーションの作成
<a name="net-dg-hosm-sample-s3-app"></a>

このサンプルアプリケーションは、Amazon S3 からオブジェクトを取得します。アプリケーションを実行するには、以下が必要です。
+ テキストファイルを含む Amazon S3 バケット。
+ AWS バケットへのアクセスを許可する開発マシンの 認証情報。

Amazon S3 バケットの作成およびオブジェクトのアップロードの詳細については、「[Amazon Simple Storage Service ユーザーガイド](https://docs.aws.amazon.com/AmazonS3/latest/userguide/)」を参照してください。 AWS 認証情報の詳細については、「」を参照してください[AWS SDK for .NET を使用した の認証 AWS](creds-idc.md)。

以下のコードを使用して、.NET Core プロジェクトを作成します。次に、開発マシンでアプリケーションをテストします。

**注記**  
開発マシンには .NET Core Runtime がインストールされており、アプリケーションを公開しなくても実行できます。このチュートリアルの後半で EC2 インスタンスを作成するときに、インスタンスに .NET Core Runtime をインストールすることができます。こうすることで同様のエクスペリエンスを実現でき、ファイル転送量が小さくなります。  
 ただし、インスタンスに .NET Core Runtime をインストールしない選択も可能です。この場合は、インスタンスを転送するときにすべての依存関係が含まれるようにアプリケーションを公開する必要があります。

### SDK リファレンス
<a name="w2aac19c15c23c25c17c13b1"></a>

NuGet パッケージ:
+ [AWSSDK.S3](https://www.nuget.org/packages/AWSSDK.S3)

プログラミング要素:
+ 名前空間 [Amazon.S3](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/NS3.html)

  クラス [AmazonS3Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TS3Client.html)
+ 名前空間 [Amazon.S3.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/NS3Model.html)

  クラス [GetObjectResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectResponse.html)

### コード
<a name="w2aac19c15c23c25c17c15b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.S3;
using Amazon.S3.Model;

namespace S3GetTextItem
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to retrieve a text file from an S3 bucket and write it to a local file
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string bucket =
        CommandLine.GetArgument(parsedArgs, null, "-b", "--bucket-name");
      string item =
        CommandLine.GetArgument(parsedArgs, null, "-t", "--text-object");
      string outFile =
        CommandLine.GetArgument(parsedArgs, null, "-o", "--output-filename");
      if(   string.IsNullOrEmpty(bucket)
         || string.IsNullOrEmpty(item)
         || string.IsNullOrEmpty(outFile))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create the S3 client object and get the file object from the bucket.
      var response = await GetObject(new AmazonS3Client(), bucket, item);

      // Write the contents of the file object to the given output file.
      var reader = new StreamReader(response.ResponseStream);
      string contents = reader.ReadToEnd();
      using (var s = new FileStream(outFile, FileMode.Create))
      using (var writer = new StreamWriter(s))
        writer.WriteLine(contents);
    }


    //
    // Method to get an object from an S3 bucket.
    private static async Task<GetObjectResponse> GetObject(
      IAmazonS3 s3Client, string bucket, string item)
    {
        Console.WriteLine($"Retrieving {item} from bucket {bucket}.");
        return await s3Client.GetObjectAsync(bucket, item);
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: S3GetTextItem -b <bucket-name> -t <text-object> -o <output-filename>" +
        "\n  -b, --bucket-name: The name of the S3 bucket." +
        "\n  -t, --text-object: The name of the text object in the bucket." +
        "\n  -o, --output-filename: The name of the file to write the text to.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

必要に応じて、開発マシンで使用している認証情報を一時的に削除して、アプリケーションの応答を確認できます。(ただし、完了したら認証情報を忘れずに復元してください)

## IAM ロールの作成
<a name="net-dg-hosm-create-the-role"></a>

Amazon S3 にアクセスするための適切なアクセス許可を持つ IAM ロールを作成します。

1. [[IAM コンソール]](https://console.aws.amazon.com/iam/) を開きます。

1. ナビゲーションペインで [**Roles**] (ロール) を選択し、続いて [**Create Role**] (ロールの作成) を選択します。

1. **[AWS サービス]** を選択し、**[EC2]** を見つけて選択して、**[次へ: アクセス許可]** を選択します。

1. [**Attach permissions policies**] (アクセス許可ポリシーの添付) をクリックし、[**AmazonS3ReadOnlyAccess**] を見つけて選択します。必要に応じてポリシーを確認し、[**Next: Tags**] (次へ: タグ) を選択します。

1. 必要に応じてタグを追加し、[**Next: Review**] (次へ: レビュー) を選択します。

1. ロールの名前と説明を入力し、[**Create role**] (ロールの作成) を選択します。この名前は EC2 インスタンスを起動するときに必要になるため、忘れないでください。

## EC2 インスタンスの起動と IAM ロールのアタッチ
<a name="net-dg-hosm-launch-ec2-instance"></a>

先ほど作成した IAM ロールを使用して EC2 インスタンスを起動します。これは以下の方法で実行できます。
+ **EC2 コンソールの使用**

  EC2 コンソールを使用してインスタンスを起動するには、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[新しいインスタンス起動ウィザードを使用してインスタンスを起動する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-instance-wizard.html)」を参照してください。

  起動ページを見ながら、少なくとも **[詳細]** ペインを展開して、**[IAM インスタンスプロファイル]** で以前に作成した IAM ロールを指定できます。
+ **の使用 AWS SDK for .NET**

  詳細については、「[Amazon EC2 インスタンスの起動](run-instance.md)」を参照してください (トピックの最後近くにある「[その他の考慮事項](run-instance.md#run-instance-additional)」を含む)。

IAM ロールが添付された EC2 インスタンスを起動するには、IAM ユーザーの設定に特定のアクセス許可が含まれている必要があります。必要なアクセス許可の詳細については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[IAM ロールをインスタンスに渡すアクセス許可をユーザーに付与する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#permission-to-pass-iam-roles)」を参照してください。

## EC2 インスタンスへの接続
<a name="net-dg-hosm-connect"></a>

EC2 インスタンスに接続することで、サンプルアプリケーションをそのインスタンスに転送して、アプリケーションを実行できるようにします。また、インスタンスの起動に使用したキーペアのプライベート部分を含むファイル、すなわち PEM ファイルも必要です。

Linux インスタンスに接続する方法については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[Linux インスタンスに接続する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html)」または「[Windows インスタンスに接続する](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/connecting_to_windows_instance.html)」を参照してください。接続する際は、開発マシンからインスタンスにファイルを転送できるように接続してください。

Windows で Visual Studio を使用している場合は、Toolkit for Visual Studio を使用してインスタンスに接続することもできます。詳細については、「 AWS Toolkit for Visual Studio ユーザーガイド[」のAmazon EC2 インスタンスへの接続](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/tkv-ec2-ami.html#connect-ec2)」を参照してください。

## EC2 インスタンスでのサンプルアプリケーションの実行
<a name="net-dg-hosm-run-the-app"></a>

1. ローカルドライブからインスタンスにアプリケーションファイルをコピーします。

   転送するファイルは、アプリケーションのビルド方法と、インスタンスに .NET Core Runtime がインストールされているかどうかによって異なります。インスタンスにファイルを転送する方法については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の[「Linux インスタンスに接続する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html)」(該当するサブセクションを参照) または「[Windows インスタンスにファイルを転送する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instanceWindowsFileTransfer.html)」を参照してください。

1. アプリケーションを起動し、開発マシンと同じ実行結果が得られることを確認します。

1. アプリケーションで、IAM ロールによって提供されている認証情報が使用されていることを確認します。

   1. [Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/)を開きます。

   1. インスタンスを選択し、**[Actions]** (アクション)、**[Instance Settings]** (インスタンスの設定)、**[Attach/Replace IAM Role]** (IAM ロールの添付/置換) を使用して IAM ロールをデタッチします。

   1. アプリケーションを再度実行して、認可エラーが返されることを確認します。

## クリーンアップ
<a name="net-dg-hosm-cleanup"></a>

チュートリアルが終了し、作成した EC2 インスタンスが不要になった場合は、不要な料金が発生しないようにインスタンスを終了してください。この操作は [Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/) で、または [Amazon EC2 インスタンスの終了](terminate-instance.md) の説明に従ってプログラムを使用して実行できます。必要に応じて、このチュートリアル用に作成した他のリソースも削除できます。削除可能なリソースには、IAM ロール、EC2 キーペアと PEM ファイル、セキュリティグループなどがあります。

# Amazon Simple Storage Service インターネットストレージの使用
<a name="s3-apis-intro"></a>

は、インターネット用のストレージである [Amazon S3](https://aws.amazon.com/s3/) AWS SDK for .NET をサポートしています。Web スケールのコンピューティングを開発者が容易にできるように設計されています。

## API
<a name="w2aac19c15c25b5"></a>

 AWS SDK for .NET はAPIs Amazon S3を提供します。API を使用すると、バケットやアイテムなどの Amazon S3 リソースを操作できます。Amazon S3 向け API の完全なセットを表示するには、以下を参照してください。
+ [AWS SDK for .NET API リファレンス](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) (「Amazon.S3」までスクロールします）。
+ [Amazon.Extensions.S3.Encryption](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.html) のドキュメント

Amazon S3 API は、以下の NuGet パッケージによって提供されます。
+ [AWSSDK.S3](https://www.nuget.org/packages/AWSSDK.S3)
+ [Amazon.Extensions.S3.Encryption](https://www.nuget.org/packages/Amazon.Extensions.S3.Encryption)

## 前提条件
<a name="w2aac19c15c25b7"></a>

開始する前に、[環境をセットアップ](net-dg-config.md)し、[プロジェクトを設定した](configuring-the-sdk.md)ことを確認してください。また、「[SDK の使用](net-dg-sdk-features.md)」の情報を確認してください。

## このドキュメントで取り上げる例
<a name="s3-apis-examples"></a>

このドキュメントの以下のトピックでは、 AWS SDK for .NET を使用して Amazon S3 を操作する方法について説明します。
+ [S3 暗号化用 KMS キーの使用](kms-keys-s3-encryption.md)

## 他のドキュメントで取り上げられている例
<a name="s3-apis-examples-other"></a>

以下の [Amazon S3 デベロッパーガイドへのリンク](https://docs.aws.amazon.com/AmazonS3/latest/userguide/)は、 を使用して Amazon S3 AWS SDK for .NET を操作する方法の追加の例を示しています。

**注記**  
これらの例と追加のプログラミング上の考慮事項は、.NET Framework AWS SDK for .NET を使用する のバージョン 3 用に作成されていますが、.NET Core AWS SDK for .NET を使用する のそれ以降のバージョンでも実行可能です。コードの軽微な修正が必要になる場合があります。

**Amazon S3 プログラミングの例**
+  [ACL の管理](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-using-dot-net-sdk.html) 
+  [バケットの作成](https://docs.aws.amazon.com/AmazonS3/latest/dev/create-bucket-get-location-example.html#create-bucket-get-location-dotnet) 
+  [オブジェクトのアップロード](https://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpNET.html) 
+  [高レベル API でのマルチパートアップロード ([Amazon.S3.Transfer.TransferUtility](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TTransferUtility.html))](https://docs.aws.amazon.com/AmazonS3/latest/dev/usingHLmpuDotNet.html) 
+  [低レベル API でのマルチパートアップロード](https://docs.aws.amazon.com/AmazonS3/latest/dev/usingLLmpuDotNet.html) 
+  [オブジェクトのリスト作成](https://docs.aws.amazon.com/AmazonS3/latest/dev/list-obj-version-enabled-bucket.html#list-obj-version-enabled-bucket-sdk-examples) 
+  [キーのリスト表示](https://docs.aws.amazon.com/AmazonS3/latest/dev/ListingObjectKeysUsingNetSDK.html) 
+  [オブジェクトの取得](https://docs.aws.amazon.com/AmazonS3/latest/dev/RetrievingObjectUsingNetSDK.html) 
+  [オブジェクトのコピー](https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjectUsingNetSDK.html) 
+  [マルチパートアップロード API を使用したオブジェクトのコピー](https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjctsUsingLLNetMPUapi.html) 
+  [オブジェクトの削除](https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingOneObjectUsingNetSDK.html) 
+  [複数のオブジェクトの削除](https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingMultipleObjectsUsingNetSDK.html) 
+  [オブジェクトの復元](https://docs.aws.amazon.com/AmazonS3/latest/dev/restore-object-dotnet.html) 
+  [通知用のバケットの設定](https://docs.aws.amazon.com/AmazonS3/latest/dev/ways-to-add-notification-config-to-bucket.html) 
+  [オブジェクトのライフサイクルを管理する](https://docs.aws.amazon.com/AmazonS3/latest/dev/manage-lifecycle-using-dot-net.html) 
+  [署名付きオブジェクト URL の生成](https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURLDotNetSDK.html) 
+  [ウェブサイトの管理](https://docs.aws.amazon.com/AmazonS3/latest/dev/ConfigWebSiteDotNet.html) 
+  [Cross-Origin Resource Sharing (CORS) の有効化](https://docs.aws.amazon.com/AmazonS3/latest/dev/ManageCorsUsingDotNet.html) 

**プログラミングに関するその他の考慮事項**
+  [Amazon S3 プログラミングでの AWS SDK for .NET の使用](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingTheMPDotNetAPI.html) 
+  [IAM ユーザーの一時的な認証情報を使用したリクエストの実行](https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenDotNet.html) 
+  [フェデレーションユーザーの一時的な認証情報を使用したリクエストの実行](https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingTempFederationTokenDotNet.html) 
+  [サーバー側暗号化の指定](https://docs.aws.amazon.com/AmazonS3/latest/dev/SSEUsingDotNetSDK.html) 
+  [お客様が用意した暗号化キーを使用したサーバー側暗号化の指定](https://docs.aws.amazon.com/AmazonS3/latest/dev/sse-c-using-dot-net-sdk.html) 

# での Amazon S3 暗号化の AWS KMS キーの使用 AWS SDK for .NET
<a name="kms-keys-s3-encryption"></a>

この例では、 AWS Key Management Service キーを使用して Amazon S3 オブジェクトを暗号化する方法を示します。アプリケーションはカスタマーマスターキー (CMK) を作成し、これを使用してクライアント側の暗号化に使用する [AmazonS3EncryptionClientV2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3EncryptionClientV2.html) オブジェクトを作成します。アプリケーションはそのクライアントを使用して、既存の Amazon S3 バケット内の所定のテキストファイルから暗号化されたオブジェクトを作成します。次にオブジェクトを復号化して、その内容を表示します。

**警告**  
`AmazonS3EncryptionClient` という類似のクラスは `AmazonS3EncryptionClientV2` クラスよりも安全性が低く、非推奨です。`AmazonS3EncryptionClient` を使用している既存のコードを移行するには、「[S3 暗号化クライアントの移行 (V1 から V2)](s3-encryption-migration-v1-v2.md)」を参照してください。

**Topics**
+ [暗号化マテリアルの作成](#kms-s3-enc-mat)
+ [Amazon S3 オブジェクトの作成と暗号化](#kms-s3-create-ojbect)
+ [コード全文](#kms-s3-complete-code)
+ [その他の考慮事項](#kms-s3-additional)

## 暗号化マテリアルの作成
<a name="kms-s3-enc-mat"></a>

次のスニペットでは、KMS キー ID を含む `EncryptionMaterials` オブジェクトを作成します。

[このトピックの最後](#kms-s3-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
      // Create a customer master key (CMK) and store the result
      CreateKeyResponse createKeyResponse =
        await new AmazonKeyManagementServiceClient().CreateKeyAsync(new CreateKeyRequest());
      var kmsEncryptionContext = new Dictionary<string, string>();
      var kmsEncryptionMaterials = new EncryptionMaterialsV2(
        createKeyResponse.KeyMetadata.KeyId, KmsType.KmsContext, kmsEncryptionContext);
```

## Amazon S3 オブジェクトの作成と暗号化
<a name="kms-s3-create-ojbect"></a>

次のスニペットでは、先ほど作成した暗号化マテリアルを使用する `AmazonS3EncryptionClientV2` オブジェクトを作成します。次に、クライアントを使用して新しい Amazon S3 オブジェクトを作成し、暗号化します。

[このトピックの最後](#kms-s3-complete-code) で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to create and encrypt an object in an S3 bucket
    static async Task<GetObjectResponse> CreateAndRetrieveObjectAsync(
      EncryptionMaterialsV2 materials, string bucketName,
      string fileName, string itemName)
    {
      // CryptoStorageMode.ObjectMetadata is required for KMS EncryptionMaterials
      var config = new AmazonS3CryptoConfigurationV2(SecurityProfile.V2AndLegacy)
      {
        StorageMode = CryptoStorageMode.ObjectMetadata
      };
      var s3EncClient = new AmazonS3EncryptionClientV2(config, materials);

      // Create, encrypt, and put the object
      await s3EncClient.PutObjectAsync(new PutObjectRequest
      {
        BucketName = bucketName,
        Key = itemName,
        ContentBody = File.ReadAllText(fileName)
      });

      // Get, decrypt, and return the object
      return await s3EncClient.GetObjectAsync(new GetObjectRequest
      {
        BucketName = bucketName,
        Key = itemName
      });
    }
```

## コード全文
<a name="kms-s3-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c25c13c15b5b1"></a>

NuGet パッケージ:
+ [Amazon.Extensions.S3.Encryption](https://www.nuget.org/packages/Amazon.Extensions.S3.Encryption)

プログラミング要素:
+ 名前空間 [Amazon.Extensions.S3.Encryption](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.html)

  クラス [AmazonS3EncryptionClientV2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3EncryptionClientV2.html)

  クラス [AmazonS3CryptoConfigurationV2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3CryptoConfigurationV2.html)

  クラス [CryptoStorageMode](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.CryptoStorageMode.html)

  クラス [EncryptionMaterialsV2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.EncryptionMaterialsV2.html)
+ 名前空間 [Amazon.Extensions.S3.Encryption.Primitives](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.Primitives.html)

  クラス [KmsType](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.Primitives.KmsType.html)
+ 名前空間 [Amazon.S3.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/NS3Model.html)

  クラス [GetObjectRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectRequest.html)

  クラス [GetObjectResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectResponse.html)

  クラス [PutObjectRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TPutObjectRequest.html)
+ 名前空間 [Amazon.KeyManagementService](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/NKeyManagementService.html)

  クラス [AmazonKeyManagementServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/TKeyManagementServiceClient.html)
+ 名前空間 [Amazon.KeyManagementService.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/NKeyManagementServiceModel.html)

  クラス [CreateKeyRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/TCreateKeyRequest.html)

  クラス [CreateKeyResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/TCreateKeyResponse.html)

### コード
<a name="w2aac19c15c25c13c15b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.Extensions.S3.Encryption;
using Amazon.Extensions.S3.Encryption.Primitives;
using Amazon.S3.Model;
using Amazon.KeyManagementService;
using Amazon.KeyManagementService.Model;

namespace KmsS3Encryption
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to store text in an encrypted S3 object.
  class Program
  {
    private const int MaxArgs = 3;

    public static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if((parsedArgs.Count == 0) || (parsedArgs.Count > MaxArgs))
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string bucketName =
        CommandLine.GetArgument(parsedArgs, null, "-b", "--bucket-name");
      string fileName =
        CommandLine.GetArgument(parsedArgs, null, "-f", "--file-name");
      string itemName =
        CommandLine.GetArgument(parsedArgs, null, "-i", "--item-name");
      if(string.IsNullOrEmpty(bucketName) || (string.IsNullOrEmpty(fileName)))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");
      if(!File.Exists(fileName))
        CommandLine.ErrorExit($"\nThe given file {fileName} doesn't exist.");
      if(string.IsNullOrEmpty(itemName))
        itemName = Path.GetFileName(fileName);

      // Create a customer master key (CMK) and store the result
      CreateKeyResponse createKeyResponse =
        await new AmazonKeyManagementServiceClient().CreateKeyAsync(new CreateKeyRequest());
      var kmsEncryptionContext = new Dictionary<string, string>();
      var kmsEncryptionMaterials = new EncryptionMaterialsV2(
        createKeyResponse.KeyMetadata.KeyId, KmsType.KmsContext, kmsEncryptionContext);

      // Create the object in the bucket, then display the content of the object
      var putObjectResponse =
        await CreateAndRetrieveObjectAsync(kmsEncryptionMaterials, bucketName, fileName, itemName);
      Stream stream = putObjectResponse.ResponseStream;
      StreamReader reader = new StreamReader(stream);
      Console.WriteLine(reader.ReadToEnd());
    }


    //
    // Method to create and encrypt an object in an S3 bucket
    static async Task<GetObjectResponse> CreateAndRetrieveObjectAsync(
      EncryptionMaterialsV2 materials, string bucketName,
      string fileName, string itemName)
    {
      // CryptoStorageMode.ObjectMetadata is required for KMS EncryptionMaterials
      var config = new AmazonS3CryptoConfigurationV2(SecurityProfile.V2AndLegacy)
      {
        StorageMode = CryptoStorageMode.ObjectMetadata
      };
      var s3EncClient = new AmazonS3EncryptionClientV2(config, materials);

      // Create, encrypt, and put the object
      await s3EncClient.PutObjectAsync(new PutObjectRequest
      {
        BucketName = bucketName,
        Key = itemName,
        ContentBody = File.ReadAllText(fileName)
      });

      // Get, decrypt, and return the object
      return await s3EncClient.GetObjectAsync(new GetObjectRequest
      {
        BucketName = bucketName,
        Key = itemName
      });
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: KmsS3Encryption -b <bucket-name> -f <file-name> [-i <item-name>]" +
        "\n  -b, --bucket-name: The name of an existing S3 bucket." +
        "\n  -f, --file-name: The name of a text file with content to encrypt and store in S3." +
        "\n  -i, --item-name: The name you want to use for the item." +
        "\n      If item-name isn't given, file-name will be used.");
    }

  }

  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="kms-s3-additional"></a>
+ この例の結果を確認できます。そのためには [Amazon S3 コンソール](https://console.aws.amazon.com/s3)に移動し、アプリケーションに対して指定したバケットを開きます。次に、新しいオブジェクトを見つけてダウンロードし、テキストエディタで開きます。
+ [AmazonS3EncryptionClientV2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3EncryptionClientV2.html) クラスでは、標準の `AmazonS3Client` クラスと同じインターフェイスが実装されています。そのため、暗号化と復号化がクライアント側で自動的かつ透過的に行われるよう、コードを `AmazonS3EncryptionClientV2` クラスに移植するのが容易になります。
+ キーをマスター AWS KMS キーとして使用する利点の 1 つは、独自のマスターキーを保存および管理する必要がないことです。これは によって行われます AWS。もう 1 つの利点は、 の `AmazonS3EncryptionClientV2` クラス AWS SDK for .NET が の `AmazonS3EncryptionClientV2` クラスと相互運用できることです AWS SDK for Java。つまり、 で暗号化 AWS SDK for Java し AWS SDK for .NET、 で復号できます。逆も同様です。
**注記**  
の `AmazonS3EncryptionClientV2` クラスは、メタデータモードで実行されている場合にのみ KMS マスターキー AWS SDK for .NET をサポートします。の `AmazonS3EncryptionClientV2`クラスの命令ファイルモード AWS SDK for .NET は、 の `AmazonS3EncryptionClientV2`クラスの と互換性がありません AWS SDK for Java。
+ `AmazonS3EncryptionClientV2` クラスによるクライアント側の暗号化、およびエンベロープ暗号化の仕組みの詳細については、「 [AWS SDK for .NET および Amazon S3 によるクライアント側のデータ暗号化](https://aws.amazon.com/blogs/developer/client-side-data-encryption-with-aws-sdk-for-net-and-amazon-s3/)」を参照してください。

# Amazon Simple Notification Service を使用したクラウドからの通知の送信
<a name="sns-apis-intro"></a>

**注記**  
このトピックの情報は、.NET Framework および AWS SDK for .NET バージョン 3.3 以前のプロジェクトに固有のものです。

は、Amazon Simple Notification Service (Amazon SNS) AWS SDK for .NET をサポートしています。Amazon SNS は、アプリケーション、エンドユーザー、デバイスがクラウドから通知を即座に送信できるようにするウェブサービスです。詳細については、「[Amazon SNS](https://aws.amazon.com/sns/)」を参照してください。

## Amazon SNS トピックの一覧表示
<a name="sns-list-example"></a>

次の例では、Amazon SNS トピック、各トピックのサブスクリプション、および各トピックの属性を一覧表示する方法を示します。この例では、デフォルトのオペレーティングシステムである [AmazonSimpleNotificationServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SNS/TSNSClient.html) を使用します。

```
// using Amazon.SimpleNotificationService;
// using Amazon.SimpleNotificationService.Model;

var client = new AmazonSimpleNotificationServiceClient();
var request = new ListTopicsRequest();
var response = new ListTopicsResponse();

do
{
  response = client.ListTopics(request);

  foreach (var topic in response.Topics)
  {
    Console.WriteLine("Topic: {0}", topic.TopicArn);

    var subs = client.ListSubscriptionsByTopic(
      new ListSubscriptionsByTopicRequest
      {
        TopicArn = topic.TopicArn
      });

    var ss = subs.Subscriptions;

    if (ss.Any())
    {
      Console.WriteLine("  Subscriptions:");

      foreach (var sub in ss)
      {
        Console.WriteLine("    {0}", sub.SubscriptionArn);
      }
    }

    var attrs = client.GetTopicAttributes(
      new GetTopicAttributesRequest
      {
        TopicArn = topic.TopicArn
      }).Attributes;

    if (attrs.Any())
    {
      Console.WriteLine("  Attributes:");

      foreach (var attr in attrs)
      {
        Console.WriteLine("    {0} = {1}", attr.Key, attr.Value);
      }
    }

    Console.WriteLine();
  }

  request.NextToken = response.NextToken;

} while (!string.IsNullOrEmpty(response.NextToken));
```

## Amazon SNS トピックへのメッセージの送信
<a name="sns-send-message-example"></a>

次の例は、Amazon SNS トピックにメッセージを送信する方法を示します。この例では、1 つの引数 (Amazon SNS トピックの ARN) を取ります。

```
using System;
using System.Linq;
using System.Threading.Tasks;

using Amazon;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;

namespace SnsSendMessage
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Topic ARNs must be in the correct format:
             *   arn:aws:sns:REGION:ACCOUNT_ID:NAME
             *
             *  where:
             *  REGION     is the region in which the topic is created, such as us-west-2
             *  ACCOUNT_ID is your (typically) 12-character account ID
             *  NAME       is the name of the topic
             */
            string topicArn = args[0];
            string message = "Hello at " + DateTime.Now.ToShortTimeString();

            var client = new AmazonSimpleNotificationServiceClient(region: Amazon.RegionEndpoint.USWest2);

            var request = new PublishRequest
            {
                Message = message,
                TopicArn = topicArn
            };

            try
            {
                var response = client.Publish(request);

                Console.WriteLine("Message sent to topic:");
                Console.WriteLine(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught exception publishing request:");
                Console.WriteLine(ex.Message);
            }
        }
    }
}
```

GitHub で、コマンドラインからサンプルをビルドして実行する方法に関する情報を含む、[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/.dotnet/example_code_legacy/SNS/SnsSendMessage.cs)を参照してください。

## 1 つの電話番号に SMS メッセージを送信する
<a name="sns-send-sms-example"></a>

次の例は、電話番号に SMS メッセージを送信する方法を示します。この例では、1 つの引数 (電話番号) を取ります。この引数は、コメントに記載されている 2 つの形式のいずれかである必要があります。

```
using System;
using System.Linq;
using System.Threading.Tasks;
using Amazon;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;

namespace SnsPublish
{
    class Program
    {
        static void Main(string[] args)
        {
            // US phone numbers must be in the correct format:
            // +1 (nnn) nnn-nnnn OR +1nnnnnnnnnn
            string number = args[0];
            string message = "Hello at " + DateTime.Now.ToShortTimeString();

            var client = new AmazonSimpleNotificationServiceClient(region: Amazon.RegionEndpoint.USWest2);
            var request = new PublishRequest
            {
                Message = message,
                PhoneNumber = number
            };

            try
            {
                var response = client.Publish(request);

                Console.WriteLine("Message sent to " + number + ":");
                Console.WriteLine(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught exception publishing request:");
                Console.WriteLine(ex.Message);
            }
        }
    }
}
```

GitHub で、コマンドラインからサンプルをビルドして実行する方法に関する情報を含む、[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/.dotnet/example_code_legacy/SNS/SnsPublish.cs)を参照してください。

# Amazon SQS を使用したメッセージング
<a name="sqs-apis-intro"></a>

は[、Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/) AWS SDK for .NET をサポートします。これは、システム内のコンポーネント間のメッセージまたはワークフローを処理するメッセージキューイングサービスです。

Amazon SQS キューは、マイクロサービス、分散システム、サーバーレスアプリケーションなどのソフトウェアコンポーネント間でメッセージを送信、保存、受信できる仕組みを提供します。その結果、こうしたコンポーネントを切り離すことができるようになり、独自のメッセージングシステムを設計および運用する必要がなくなります。Amazon SQS でのキューとメッセージの仕組みに関する詳細については、[Amazon SQS のチュートリアル](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-other-tutorials.html)および「[Amazon Simple Queue Service デベロッパーガイド](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/)」の「[Amazon SQS の基本的なアーキテクチャ](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html)」を参照してください。

**重要**  
キューが持つ分散的な性質のため、Amazon SQS ではメッセージを送信された順序で受信することは保証できません。メッセージの順序を保持する必要がある場合は、[Amazon SQS FIFO キュー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-fifo-queues.html)を使用してください。

## API
<a name="w2aac19c15c29b9"></a>

 AWS SDK for .NET はAPIs Amazon SQS を提供します。API を使用すると、キューやメッセージなどの Amazon SQS 機能を操作できます。このセクションでは、これらの API を操作する際に活用できるパターンを示すいくつかの例を紹介します。API の完全なセットを確認するには、[AWS SDK for .NET API リファレンス](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)を参照してください (「Amazon.SQS」までスクロールします)。

Amazon SQS API は、[AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS) NuGet パッケージによって提供されます。

## 前提条件
<a name="w2aac19c15c29c11"></a>

開始する前に、[環境をセットアップ](net-dg-config.md)し、[プロジェクトを設定した](configuring-the-sdk.md)ことを確認してください。また、「[SDK の使用](net-dg-sdk-features.md)」の情報を確認してください。

## トピック
<a name="w2aac19c15c29c13"></a>

**Topics**
+ [API](#w2aac19c15c29b9)
+ [前提条件](#w2aac19c15c29c11)
+ [トピック](#w2aac19c15c29c13)
+ [キューの作成](CreateQueue.md)
+ [キューの更新](UpdateSqsQueue.md)
+ [キューの削除](DeleteSqsQueue.md)
+ [メッセージの送信](SendMessage.md)
+ [メッセージの受信](ReceiveMessage.md)

# Amazon SQS キューの作成
<a name="CreateQueue"></a>

この例では、 AWS SDK for .NET を使用して Amazon SQS キューを作成する方法を示します。ユーザーがデッドレターキューの ARN を指定しない場合、アプリケーションは[デッドレターキュー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)を作成します。次に、デッドレターキュー (ユーザーが指定したもの、または作成されたもの) を含む標準メッセージキューを作成します。

コマンドライン引数を何も指定しない場合、アプリケーションは単に既存のすべてのキューに関する情報を表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#CreateQueue-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [既存のキューの表示](#CreateQueue-show-queues)
+ [キューの作成](#CreateQueue-create-queue)
+ [キューの ARN の取得](#CreateQueue-get-arn)
+ [コード全文](#CreateQueue-complete-code)
+ [その他の考慮事項](#CreateQueue-additional)

## 既存のキューの表示
<a name="CreateQueue-show-queues"></a>

次のスニペットでは、SQS クライアントのリージョンにある既存のキューのリストと、各キューの属性を表示します。

[このトピックの最後](#CreateQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to show a list of the existing queues
    private static async Task ShowQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine();
      foreach(string qUrl in responseList.QueueUrls)
      {
        // Get and show all attributes. Could also get a subset.
        await ShowAllAttributes(sqsClient, qUrl);
      }
    }

    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      var attributes = new List<string>{ QueueAttributeName.All };
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl, attributes);
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }
```

## キューの作成
<a name="CreateQueue-create-queue"></a>

次のスニペットでは、キューが作成されます。このスニペットにはデッドレターキューの使用が含まれていますが、デッドレターキューは必ずしもキューに必要ではありません。

[このトピックの最後](#CreateQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to create a queue. Returns the queue URL.
    private static async Task<string> CreateQueue(
      IAmazonSQS sqsClient, string qName, string deadLetterQueueUrl=null,
      string maxReceiveCount=null, string receiveWaitTime=null)
    {
      var attrs = new Dictionary<string, string>();

      // If a dead-letter queue is given, create a message queue
      if(!string.IsNullOrEmpty(deadLetterQueueUrl))
      {
        attrs.Add(QueueAttributeName.ReceiveMessageWaitTimeSeconds, receiveWaitTime);
        attrs.Add(QueueAttributeName.RedrivePolicy,
          $"{{\"deadLetterTargetArn\":\"{await GetQueueArn(sqsClient, deadLetterQueueUrl)}\"," +
          $"\"maxReceiveCount\":\"{maxReceiveCount}\"}}");
        // Add other attributes for the message queue such as VisibilityTimeout
      }

      // If no dead-letter queue is given, create one of those instead
      //else
      //{
      //  // Add attributes for the dead-letter queue as needed
      //  attrs.Add();
      //}

      // Create the queue
      CreateQueueResponse responseCreate = await sqsClient.CreateQueueAsync(
          new CreateQueueRequest{QueueName = qName, Attributes = attrs});
      return responseCreate.QueueUrl;
    }
```

## キューの ARN の取得
<a name="CreateQueue-get-arn"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューの ARN を取得します。

[このトピックの最後](#CreateQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to get the ARN of a queue
    private static async Task<string> GetQueueArn(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt = await sqsClient.GetQueueAttributesAsync(
        qUrl, new List<string>{QueueAttributeName.QueueArn});
      return responseGetAtt.QueueARN;
    }
```

## コード全文
<a name="CreateQueue-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c29c17c25b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

プログラミング要素:
+ 名前空間 [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  クラス [AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)

  クラス [QueueAttributeName](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TQueueAttributeName.html)
+ 名前空間 [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  クラス [CreateQueueRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TCreateQueueRequest.html)

  クラス [CreateQueueResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TCreateQueueResponse.html)

  クラス [GetQueueAttributesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TGetQueueAttributesResponse.html)

  クラス [ListQueuesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TListQueuesResponse.html)

### コード
<a name="w2aac19c15c29c17c25b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSCreateQueue
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create a queue
  class Program
  {
    private const string MaxReceiveCount = "10";
    private const string ReceiveMessageWaitTime = "2";
    private const int MaxArgs = 3;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count > MaxArgs)
        CommandLine.ErrorExit(
          "\nToo many command-line arguments.\nRun the command with no arguments to see help.");

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // In the case of no command-line arguments, just show help and the existing queues
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        Console.WriteLine("\nNo arguments specified.");
        Console.Write("Do you want to see a list of the existing queues? ((y) or n): ");
        string response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await ShowQueues(sqsClient);
        return;
      }

      // Get the application arguments from the parsed list
      string queueName =
        CommandLine.GetArgument(parsedArgs, null, "-q", "--queue-name");
      string deadLetterQueueUrl =
        CommandLine.GetArgument(parsedArgs, null, "-d", "--dead-letter-queue");
      string maxReceiveCount =
        CommandLine.GetArgument(parsedArgs, MaxReceiveCount, "-m", "--max-receive-count");
      string receiveWaitTime =
        CommandLine.GetArgument(parsedArgs, ReceiveMessageWaitTime, "-w", "--wait-time");

      if(string.IsNullOrEmpty(queueName))
        CommandLine.ErrorExit(
          "\nYou must supply a queue name.\nRun the command with no arguments to see help.");

      // If a dead-letter queue wasn't given, create one
      if(string.IsNullOrEmpty(deadLetterQueueUrl))
      {
        Console.WriteLine("\nNo dead-letter queue was specified. Creating one...");
        deadLetterQueueUrl = await CreateQueue(sqsClient, queueName + "__dlq");
        Console.WriteLine($"Your new dead-letter queue:");
        await ShowAllAttributes(sqsClient, deadLetterQueueUrl);
      }

      // Create the message queue
      string messageQueueUrl = await CreateQueue(
        sqsClient, queueName, deadLetterQueueUrl, maxReceiveCount, receiveWaitTime);
      Console.WriteLine($"Your new message queue:");
      await ShowAllAttributes(sqsClient, messageQueueUrl);
    }


    //
    // Method to show a list of the existing queues
    private static async Task ShowQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine();
      foreach(string qUrl in responseList.QueueUrls)
      {
        // Get and show all attributes. Could also get a subset.
        await ShowAllAttributes(sqsClient, qUrl);
      }
    }


    //
    // Method to create a queue. Returns the queue URL.
    private static async Task<string> CreateQueue(
      IAmazonSQS sqsClient, string qName, string deadLetterQueueUrl=null,
      string maxReceiveCount=null, string receiveWaitTime=null)
    {
      var attrs = new Dictionary<string, string>();

      // If a dead-letter queue is given, create a message queue
      if(!string.IsNullOrEmpty(deadLetterQueueUrl))
      {
        attrs.Add(QueueAttributeName.ReceiveMessageWaitTimeSeconds, receiveWaitTime);
        attrs.Add(QueueAttributeName.RedrivePolicy,
          $"{{\"deadLetterTargetArn\":\"{await GetQueueArn(sqsClient, deadLetterQueueUrl)}\"," +
          $"\"maxReceiveCount\":\"{maxReceiveCount}\"}}");
        // Add other attributes for the message queue such as VisibilityTimeout
      }

      // If no dead-letter queue is given, create one of those instead
      //else
      //{
      //  // Add attributes for the dead-letter queue as needed
      //  attrs.Add();
      //}

      // Create the queue
      CreateQueueResponse responseCreate = await sqsClient.CreateQueueAsync(
          new CreateQueueRequest{QueueName = qName, Attributes = attrs});
      return responseCreate.QueueUrl;
    }


    //
    // Method to get the ARN of a queue
    private static async Task<string> GetQueueArn(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt = await sqsClient.GetQueueAttributesAsync(
        qUrl, new List<string>{QueueAttributeName.QueueArn});
      return responseGetAtt.QueueARN;
    }


    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      var attributes = new List<string>{ QueueAttributeName.All };
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl, attributes);
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
      "\nUsage: SQSCreateQueue -q <queue-name> [-d <dead-letter-queue>]" +
        " [-m <max-receive-count>] [-w <wait-time>]" +
      "\n  -q, --queue-name: The name of the queue you want to create." +
      "\n  -d, --dead-letter-queue: The URL of an existing queue to be used as the dead-letter queue."+
      "\n      If this argument isn't supplied, a new dead-letter queue will be created." +
      "\n  -m, --max-receive-count: The value for maxReceiveCount in the RedrivePolicy of the queue." +
      $"\n      Default is {MaxReceiveCount}." +
      "\n  -w, --wait-time: The value for ReceiveMessageWaitTimeSeconds of the queue for long polling." +
      $"\n      Default is {ReceiveMessageWaitTime}.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="CreateQueue-additional"></a>
+ キュー名は、英数字、ハイフン、およびアンダースコアで構成する必要があります。
+ キュー名とキュー URL では大文字と小文字が区別されます。
+ キュー URL が必要なときにキュー名しかない場合には、`AmazonSQSClient.GetQueueUrlAsync` メソッドのいずれかを使用してください。
+ 設定できるさまざまなキュー属性の詳細については、[AWS SDK for .NET API リファレンス](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)の「[CreateQueueRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TCreateQueueRequest.html)」か、または [Amazon Simple Queue Service API リファレンス](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/)の「[SetQueueAttributes](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html)」を参照してください。
+ この例では、作成するキュー上のすべてのメッセージに対してロングポーリングを指定します。これは `ReceiveMessageWaitTimeSeconds` 属性を使用して行われます。

  [AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html) クラスの `ReceiveMessageAsync` メソッドの呼び出し中にロングポーリングを指定することもできます。詳細については、「[Amazon SQS メッセージの受信](ReceiveMessage.md)」を参照してください。

  ショートポーリングとロングポーリングの違いに関する詳細については、*Amazon Simple Queue Service デベロッパーガイド*の「[ショートポーリングとロングポーリング](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html)」を参照してください。
+ デッドレターキューとは、他の (送信元) キューが正常に処理されないメッセージの送信先として使用できるキューのことです。詳細については、Amazon Simple Queue Service デベロッパーガイドの「[Amazon SQS デッドレターキュー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)」を参照してください。
+ キューのリストとこの例の結果は、[Amazon SQS コンソール](https://console.aws.amazon.com/sqs)でも確認できます。

# Amazon SQS キューの更新
<a name="UpdateSqsQueue"></a>

この例では、 AWS SDK for .NET を使用して Amazon SQS キューを更新する方法を示します。アプリケーションはいくつかのチェックを行った後、指定された属性を指定された値で更新し、キューのすべての属性を表示します。

コマンドライン引数にキュー URL のみを含めた場合、アプリケーションは単にキューのすべての属性を表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#UpdateSqsQueue-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [キュー属性の表示](#UpdateSqsQueue-show-attributes)
+ [属性名の検証](#UpdateSqsQueue-validate-attribute)
+ [キュー属性の更新](#UpdateSqsQueue-update-attribute)
+ [コード全文](#UpdateSqsQueue-complete-code)
+ [その他の考慮事項](#UpdateSqsQueue-additional)

## キュー属性の表示
<a name="UpdateSqsQueue-show-attributes"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューの属性を表示します。

[このトピックの最後](#UpdateSqsQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl,
          new List<string>{ QueueAttributeName.All });
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }
```

## 属性名の検証
<a name="UpdateSqsQueue-validate-attribute"></a>

次のスニペットでは、更新される属性の名前を検証します。

[このトピックの最後](#UpdateSqsQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to check the name of the attribute
    private static bool ValidAttribute(string attribute)
    {
      var attOk = false;
      var qAttNameType = typeof(QueueAttributeName);
      List<string> qAttNamefields = new List<string>();
      foreach(var field in qAttNameType.GetFields())
       qAttNamefields.Add(field.Name);
      foreach(var name in qAttNamefields)
        if(attribute == name) { attOk = true; break; }
      return attOk;
    }
```

## キュー属性の更新
<a name="UpdateSqsQueue-update-attribute"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューの属性を更新します。

[このトピックの最後](#UpdateSqsQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to update a queue attribute
    private static async Task UpdateAttribute(
      IAmazonSQS sqsClient, string qUrl, string attribute, string value)
    {
      await sqsClient.SetQueueAttributesAsync(qUrl,
        new Dictionary<string, string>{{attribute, value}});
    }
```

## コード全文
<a name="UpdateSqsQueue-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c29c19c25b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

プログラミング要素:
+ 名前空間 [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  クラス [AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)

  クラス [QueueAttributeName](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TQueueAttributeName.html)
+ 名前空間 [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  クラス [GetQueueAttributesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TGetQueueAttributesResponse.html)

### コード
<a name="w2aac19c15c29c19c25b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSUpdateQueue
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to update a queue
  class Program
  {
    private const int MaxArgs = 3;
    private const int InvalidArgCount = 2;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }
      if((parsedArgs.Count > MaxArgs) || (parsedArgs.Count == InvalidArgCount))
        CommandLine.ErrorExit("\nThe number of command-line arguments is incorrect." +
          "\nRun the command with no arguments to see help.");

      // Get the application arguments from the parsed list
      var qUrl = CommandLine.GetArgument(parsedArgs, null, "-q");
      var attribute = CommandLine.GetArgument(parsedArgs, null, "-a");
      var value = CommandLine.GetArgument(parsedArgs, null, "-v", "--value");

      if(string.IsNullOrEmpty(qUrl))
        CommandLine.ErrorExit("\nYou must supply at least a queue URL." +
          "\nRun the command with no arguments to see help.");

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // In the case of one command-line argument, just show the attributes for the queue
      if(parsedArgs.Count == 1)
        await ShowAllAttributes(sqsClient, qUrl);

      // Otherwise, attempt to update the given queue attribute with the given value
      else
      {
        // Check to see if the attribute is valid
        if(ValidAttribute(attribute))
        {
          // Perform the update and then show all the attributes of the queue
          await UpdateAttribute(sqsClient, qUrl, attribute, value);
          await ShowAllAttributes(sqsClient, qUrl);
        }
        else
        {
          Console.WriteLine($"\nThe given attribute name, {attribute}, isn't valid.");
        }
      }
    }


    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl,
          new List<string>{ QueueAttributeName.All });
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }


    //
    // Method to check the name of the attribute
    private static bool ValidAttribute(string attribute)
    {
      var attOk = false;
      var qAttNameType = typeof(QueueAttributeName);
      List<string> qAttNamefields = new List<string>();
      foreach(var field in qAttNameType.GetFields())
       qAttNamefields.Add(field.Name);
      foreach(var name in qAttNamefields)
        if(attribute == name) { attOk = true; break; }
      return attOk;
    }


    //
    // Method to update a queue attribute
    private static async Task UpdateAttribute(
      IAmazonSQS sqsClient, string qUrl, string attribute, string value)
    {
      await sqsClient.SetQueueAttributesAsync(qUrl,
        new Dictionary<string, string>{{attribute, value}});
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine("\nUsage: SQSUpdateQueue -q queue_url [-a attribute -v value]");
      Console.WriteLine("  -q: The URL of the queue you want to update.");
      Console.WriteLine("  -a: The name of the attribute to update.");
      Console.WriteLine("  -v, --value: The value to assign to the attribute.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## その他の考慮事項
<a name="UpdateSqsQueue-additional"></a>
+ `RedrivePolicy` 属性を更新するには、値全体を引用符で囲み、キーと値のペアの引用符をお使いのオペレーティングシステムに応じた適切な方法でエスケープする必要があります。

  例えば Windows では、値は次のような形で構成されます。

  ```
  "{\"deadLetterTargetArn\":\"DEAD_LETTER-QUEUE-ARN\",\"maxReceiveCount\":\"10\"}"
  ```

# Amazon SQS キューの削除
<a name="DeleteSqsQueue"></a>

この例では、 AWS SDK for .NET を使用して Amazon SQS キューを削除する方法を示します。アプリケーションはキューを削除し、キューがなくなるまで一定時間待ってから、残っているキューのリストを表示します。

コマンドライン引数を何も指定しない場合、アプリケーションは単に既存のキューのリストを表示します。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#DeleteSqsQueue-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [キューの削除](#DeleteSqsQueue-delete-queue)
+ [キューがなくなるまで待機](#DeleteSqsQueue-wait)
+ [既存のキューのリストの表示](#DeleteSqsQueue-list-queues)
+ [コード全文](#DeleteSqsQueue-complete-code)
+ [その他の考慮事項](#DeleteSqsQueue-additional)

## キューの削除
<a name="DeleteSqsQueue-delete-queue"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューを削除します。

[このトピックの最後](#DeleteSqsQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to delete an SQS queue
    private static async Task DeleteQueue(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"Deleting queue {qUrl}...");
      await sqsClient.DeleteQueueAsync(qUrl);
      Console.WriteLine($"Queue {qUrl} has been deleted.");
    }
```

## キューがなくなるまで待機
<a name="DeleteSqsQueue-wait"></a>

次のスニペットでは、削除プロセスが完了するまで待機します。この処理には 60 秒かかる場合があります。

[このトピックの最後](#DeleteSqsQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to wait up to a given number of seconds
    private static async Task Wait(
      IAmazonSQS sqsClient, int numSeconds, string qUrl)
    {
      Console.WriteLine($"Waiting for up to {numSeconds} seconds.");
      Console.WriteLine("Press any key to stop waiting. (Response might be slightly delayed.)");
      for(int i=0; i<numSeconds; i++)
      {
        Console.Write(".");
        Thread.Sleep(1000);
        if(Console.KeyAvailable) break;

        // Check to see if the queue is gone yet
        var found = false;
        ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
        foreach(var url in responseList.QueueUrls)
        {
          if(url == qUrl)
          {
            found = true;
            break;
          }
        }
        if(!found) break;
      }
    }
```

## 既存のキューのリストの表示
<a name="DeleteSqsQueue-list-queues"></a>

次のスニペットでは、SQS クライアントのリージョンにある既存のキューのリストを表示します。

[このトピックの最後](#DeleteSqsQueue-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to show a list of the existing queues
    private static async Task ListQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine("\nList of queues:");
      foreach(var qUrl in responseList.QueueUrls)
        Console.WriteLine($"- {qUrl}");
    }
```

## コード全文
<a name="DeleteSqsQueue-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c29c21c25b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

プログラミング要素:
+ 名前空間 [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  クラス [AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)
+ 名前空間 [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  クラス [ListQueuesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TListQueuesResponse.html)

### コード
<a name="w2aac19c15c29c21c25b7b1"></a>

```
using System;
using System.Threading;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSDeleteQueue
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to update a queue
  class Program
  {
    private const int TimeToWait = 60;

    static async Task Main(string[] args)
    {
      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // If no command-line arguments, just show a list of the queues
      if(args.Length == 0)
      {
        Console.WriteLine("\nUsage: SQSCreateQueue queue_url");
        Console.WriteLine("   queue_url - The URL of the queue you want to delete.");
        Console.WriteLine("\nNo arguments specified.");
        Console.Write("Do you want to see a list of the existing queues? ((y) or n): ");
        var response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await ListQueues(sqsClient);
        return;
      }

      // If given a queue URL, delete that queue
      if(args[0].StartsWith("https://sqs."))
      {
        // Delete the queue
        await DeleteQueue(sqsClient, args[0]);
        // Wait for a little while because it takes a while for the queue to disappear
        await Wait(sqsClient, TimeToWait, args[0]);
        // Show a list of the remaining queues
        await ListQueues(sqsClient);
      }
      else
      {
        Console.WriteLine("The command-line argument isn't a queue URL:");
        Console.WriteLine($"{args[0]}");
      }
    }


    //
    // Method to delete an SQS queue
    private static async Task DeleteQueue(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"Deleting queue {qUrl}...");
      await sqsClient.DeleteQueueAsync(qUrl);
      Console.WriteLine($"Queue {qUrl} has been deleted.");
    }


    //
    // Method to wait up to a given number of seconds
    private static async Task Wait(
      IAmazonSQS sqsClient, int numSeconds, string qUrl)
    {
      Console.WriteLine($"Waiting for up to {numSeconds} seconds.");
      Console.WriteLine("Press any key to stop waiting. (Response might be slightly delayed.)");
      for(int i=0; i<numSeconds; i++)
      {
        Console.Write(".");
        Thread.Sleep(1000);
        if(Console.KeyAvailable) break;

        // Check to see if the queue is gone yet
        var found = false;
        ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
        foreach(var url in responseList.QueueUrls)
        {
          if(url == qUrl)
          {
            found = true;
            break;
          }
        }
        if(!found) break;
      }
    }


    //
    // Method to show a list of the existing queues
    private static async Task ListQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine("\nList of queues:");
      foreach(var qUrl in responseList.QueueUrls)
        Console.WriteLine($"- {qUrl}");
    }
  }
}
```

## その他の考慮事項
<a name="DeleteSqsQueue-additional"></a>
+ `DeleteQueueAsync` API コールでは、削除しようとしているキューがデッドレターキューとして使用されているかどうかはチェックされません。チェックするには、より高度な手順が必要になります。
+ キューのリストとこの例の結果は、[Amazon SQS コンソール](https://console.aws.amazon.com/sqs)でも確認できます。

# Amazon SQS メッセージの送信
<a name="SendMessage"></a>

この例では、 を使用して Amazon SQS キューに AWS SDK for .NET メッセージを送信する方法を示します。このキューは、[プログラムで](CreateQueue.md)作成することも、[Amazon SQS コンソール](https://console.aws.amazon.com/sqs)を使用して作成することもできます。アプリケーションは 1 つのメッセージをキューに送信し、次にメッセージのバッチを送信します。その後、アプリケーションはユーザーからの入力を待ちます。入力としては、キューに送信する追加メッセージや、アプリケーションの終了要求などが考えられます。

この例と、[次のメッセージの受信に関する例](ReceiveMessage.md)を一緒に使用して、Amazon SQS のメッセージフローを確認できます。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#SendMessage-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [メッセージの送信](#SendMessage-send-message)
+ [メッセージのバッチの送信](#SendMessage-send-batch)
+ [キューからのすべてのメッセージの削除](#SendMessage-purge-messages)
+ [コード全文](#SendMessage-complete-code)
+ [その他の考慮事項](#SendMessage-additional)

## メッセージの送信
<a name="SendMessage-send-message"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューにメッセージを送信します。

[このトピックの最後](#SendMessage-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to put a message on a queue
    // Could be expanded to include message attributes, etc., in a SendMessageRequest
    private static async Task SendMessage(
      IAmazonSQS sqsClient, string qUrl, string messageBody)
    {
      SendMessageResponse responseSendMsg =
        await sqsClient.SendMessageAsync(qUrl, messageBody);
      Console.WriteLine($"Message added to queue\n  {qUrl}");
      Console.WriteLine($"HttpStatusCode: {responseSendMsg.HttpStatusCode}");
    }
```

## メッセージのバッチの送信
<a name="SendMessage-send-batch"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューにメッセージのバッチを送信します。

[このトピックの最後](#SendMessage-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to put a batch of messages on a queue
    // Could be expanded to include message attributes, etc.,
    // in the SendMessageBatchRequestEntry objects
    private static async Task SendMessageBatch(
      IAmazonSQS sqsClient, string qUrl, List<SendMessageBatchRequestEntry> messages)
    {
      Console.WriteLine($"\nSending a batch of messages to queue\n  {qUrl}");
      SendMessageBatchResponse responseSendBatch =
        await sqsClient.SendMessageBatchAsync(qUrl, messages);
      // Could test responseSendBatch.Failed here
      foreach(SendMessageBatchResultEntry entry in responseSendBatch.Successful)
        Console.WriteLine($"Message {entry.Id} successfully queued.");
    }
```

## キューからのすべてのメッセージの削除
<a name="SendMessage-purge-messages"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューからすべてのメッセージを削除します。この操作は、*キューの消去*とも呼ばれます。

[このトピックの最後](#SendMessage-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to delete all messages from the queue
    private static async Task DeleteAllMessages(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"\nPurging messages from queue\n  {qUrl}...");
      PurgeQueueResponse responsePurge = await sqsClient.PurgeQueueAsync(qUrl);
      Console.WriteLine($"HttpStatusCode: {responsePurge.HttpStatusCode}");
    }
```

## コード全文
<a name="SendMessage-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c29c23c25b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

プログラミング要素:
+ 名前空間 [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  クラス [AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)
+ 名前空間 [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  クラス [PurgeQueueResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TPurgeQueueResponse.html)

  クラス [SendMessageBatchResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageBatchResponse.html)

  クラス [SendMessageResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageResponse.html)

  クラス [SendMessageBatchRequestEntry](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageBatchRequestEntry.html)

  クラス [SendMessageBatchResultEntry](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageBatchResultEntry.html)

### コード
<a name="w2aac19c15c29c23c25b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSSendMessages
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to send messages to a queue
  class Program
  {
    // Some example messages to send to the queue
    private const string JsonMessage = "{\"product\":[{\"name\":\"Product A\",\"price\": \"32\"},{\"name\": \"Product B\",\"price\": \"27\"}]}";
    private const string XmlMessage = "<products><product name=\"Product A\" price=\"32\" /><product name=\"Product B\" price=\"27\" /></products>";
    private const string CustomMessage = "||product|Product A|32||product|Product B|27||";
    private const string TextMessage = "Just a plain text message.";

    static async Task Main(string[] args)
    {
      // Do some checks on the command-line
      if(args.Length == 0)
      {
        Console.WriteLine("\nUsage: SQSSendMessages queue_url");
        Console.WriteLine("   queue_url - The URL of an existing SQS queue.");
        return;
      }
      if(!args[0].StartsWith("https://sqs."))
      {
        Console.WriteLine("\nThe command-line argument isn't a queue URL:");
        Console.WriteLine($"{args[0]}");
        return;
      }

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // (could verify that the queue exists)
      // Send some example messages to the given queue
      // A single message
      await SendMessage(sqsClient, args[0], JsonMessage);

      // A batch of messages
      var batchMessages = new List<SendMessageBatchRequestEntry>{
        new SendMessageBatchRequestEntry("xmlMsg", XmlMessage),
        new SendMessageBatchRequestEntry("customeMsg", CustomMessage),
        new SendMessageBatchRequestEntry("textMsg", TextMessage)};
      await SendMessageBatch(sqsClient, args[0], batchMessages);

      // Let the user send their own messages or quit
      await InteractWithUser(sqsClient, args[0]);

      // Delete all messages that are still in the queue
      await DeleteAllMessages(sqsClient, args[0]);
    }


    //
    // Method to put a message on a queue
    // Could be expanded to include message attributes, etc., in a SendMessageRequest
    private static async Task SendMessage(
      IAmazonSQS sqsClient, string qUrl, string messageBody)
    {
      SendMessageResponse responseSendMsg =
        await sqsClient.SendMessageAsync(qUrl, messageBody);
      Console.WriteLine($"Message added to queue\n  {qUrl}");
      Console.WriteLine($"HttpStatusCode: {responseSendMsg.HttpStatusCode}");
    }


    //
    // Method to put a batch of messages on a queue
    // Could be expanded to include message attributes, etc.,
    // in the SendMessageBatchRequestEntry objects
    private static async Task SendMessageBatch(
      IAmazonSQS sqsClient, string qUrl, List<SendMessageBatchRequestEntry> messages)
    {
      Console.WriteLine($"\nSending a batch of messages to queue\n  {qUrl}");
      SendMessageBatchResponse responseSendBatch =
        await sqsClient.SendMessageBatchAsync(qUrl, messages);
      // Could test responseSendBatch.Failed here
      foreach(SendMessageBatchResultEntry entry in responseSendBatch.Successful)
        Console.WriteLine($"Message {entry.Id} successfully queued.");
    }


    //
    // Method to get input from the user
    // They can provide messages to put in the queue or exit the application
    private static async Task InteractWithUser(IAmazonSQS sqsClient, string qUrl)
    {
      string response;
      while (true)
      {
        // Get the user's input
        Console.WriteLine("\nType a message for the queue or \"exit\" to quit:");
        response = Console.ReadLine();
        if(response.ToLower() == "exit") break;

        // Put the user's message in the queue
        await SendMessage(sqsClient, qUrl, response);
      }
    }


    //
    // Method to delete all messages from the queue
    private static async Task DeleteAllMessages(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"\nPurging messages from queue\n  {qUrl}...");
      PurgeQueueResponse responsePurge = await sqsClient.PurgeQueueAsync(qUrl);
      Console.WriteLine($"HttpStatusCode: {responsePurge.HttpStatusCode}");
    }
  }
}
```

## その他の考慮事項
<a name="SendMessage-additional"></a>
+ 許可される文字など、メッセージのさまざまな制限については、[Amazon Simple Queue Service デベロッパーガイド](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/)の「[メッセージに関連するクォータ](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-quotas.html#quotas-messages)」を参照してください。
+ メッセージは削除されるか、またはキューが消去されるまでキューに残ります。アプリケーションがメッセージを受信すると、そのメッセージはキュー内にまだ存在していたとしてもキューで表示されなくなります。可視性タイムアウトの詳細については、「[Amazon SQS 可視性タイムアウト](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html)」を参照してください。
+ メッセージ本文に加えて、メッセージに属性を追加することもできます。詳細については、「[メッセージメタデータ](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html)」を参照してください。

# Amazon SQS メッセージの受信
<a name="ReceiveMessage"></a>

この例では、 を使用して Amazon SQS キューからメッセージ AWS SDK for .NET を受信する方法を示します。このキューは、[プログラムまたは](CreateQueue.md) [Amazon SQS コンソール](https://console.aws.amazon.com/sqs)を使用して作成できます。アプリケーションはキューから 1 つのメッセージを読み取り、メッセージを処理 (この例ではコンソールにメッセージ本文を表示) した後で、キューからメッセージを削除します。アプリケーションは、ユーザーがキーボードでキーを入力するまで、これらの手順を繰り返します。

この例と、[前のメッセージの送信に関する例](SendMessage.md)を一緒に使用して、Amazon SQS のメッセージフローを確認できます。

以下のセクションでは、この例のスニペットを確認できます。その下には、[この例のコードの全文](#ReceiveMessage-complete-code)が示されており、そのままビルドして実行できます。

**Topics**
+ [メッセージの受信](#ReceiveMessage-receive)
+ [メッセージの削除](#ReceiveMessage-delete)
+ [コード全文](#ReceiveMessage-complete-code)
+ [その他の考慮事項](#ReceiveMessage-additional)

## メッセージの受信
<a name="ReceiveMessage-receive"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューからメッセージを受信します。

[このトピックの最後](#ReceiveMessage-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to read a message from the given queue
    // In this example, it gets one message at a time
    private static async Task<ReceiveMessageResponse> GetMessage(
      IAmazonSQS sqsClient, string qUrl, int waitTime=0)
    {
      return await sqsClient.ReceiveMessageAsync(new ReceiveMessageRequest{
        QueueUrl=qUrl,
        MaxNumberOfMessages=MaxMessages,
        WaitTimeSeconds=waitTime
        // (Could also request attributes, set visibility timeout, etc.)
      });
    }
```

## メッセージの削除
<a name="ReceiveMessage-delete"></a>

次のスニペットでは、指定されたキュー URL で特定されるキューからメッセージを削除します。

[このトピックの最後](#ReceiveMessage-complete-code)で、スニペットが実際に使用されている例を確認できます。

```
    //
    // Method to delete a message from a queue
    private static async Task DeleteMessage(
      IAmazonSQS sqsClient, Message message, string qUrl)
    {
      Console.WriteLine($"\nDeleting message {message.MessageId} from queue...");
      await sqsClient.DeleteMessageAsync(qUrl, message.ReceiptHandle);
    }
```

## コード全文
<a name="ReceiveMessage-complete-code"></a>

このセクションでは、例に関連する参考資料とコードの全文を示します。

### SDK リファレンス
<a name="w2aac19c15c29c25c21b5b1"></a>

NuGet パッケージ:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

プログラミング要素:
+ 名前空間 [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  クラス [AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)
+ 名前空間 [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  クラス [ReceiveMessageRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TReceiveMessageRequest.html)

  クラス [ReceiveMessageResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TReceiveMessageResponse.html)

### コード
<a name="w2aac19c15c29c25c21b7b1"></a>

```
using System;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSReceiveMessages
{
  class Program
  {
    private const int MaxMessages = 1;
    private const int WaitTime = 2;
    static async Task Main(string[] args)
    {
      // Do some checks on the command-line
      if(args.Length == 0)
      {
        Console.WriteLine("\nUsage: SQSReceiveMessages queue_url");
        Console.WriteLine("   queue_url - The URL of an existing SQS queue.");
        return;
      }
      if(!args[0].StartsWith("https://sqs."))
      {
        Console.WriteLine("\nThe command-line argument isn't a queue URL:");
        Console.WriteLine($"{args[0]}");
        return;
      }

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // (could verify that the queue exists)
      // Read messages from the queue and perform appropriate actions
      Console.WriteLine($"Reading messages from queue\n  {args[0]}");
      Console.WriteLine("Press any key to stop. (Response might be slightly delayed.)");
      do
      {
        var msg = await GetMessage(sqsClient, args[0], WaitTime);
        if(msg.Messages.Count != 0)
        {
          if(ProcessMessage(msg.Messages[0]))
            await DeleteMessage(sqsClient, msg.Messages[0], args[0]);
        }
      } while(!Console.KeyAvailable);
    }


    //
    // Method to read a message from the given queue
    // In this example, it gets one message at a time
    private static async Task<ReceiveMessageResponse> GetMessage(
      IAmazonSQS sqsClient, string qUrl, int waitTime=0)
    {
      return await sqsClient.ReceiveMessageAsync(new ReceiveMessageRequest{
        QueueUrl=qUrl,
        MaxNumberOfMessages=MaxMessages,
        WaitTimeSeconds=waitTime
        // (Could also request attributes, set visibility timeout, etc.)
      });
    }


    //
    // Method to process a message
    // In this example, it simply prints the message
    private static bool ProcessMessage(Message message)
    {
      Console.WriteLine($"\nMessage body of {message.MessageId}:");
      Console.WriteLine($"{message.Body}");
      return true;
    }


    //
    // Method to delete a message from a queue
    private static async Task DeleteMessage(
      IAmazonSQS sqsClient, Message message, string qUrl)
    {
      Console.WriteLine($"\nDeleting message {message.MessageId} from queue...");
      await sqsClient.DeleteMessageAsync(qUrl, message.ReceiptHandle);
    }
  }
}
```

## その他の考慮事項
<a name="ReceiveMessage-additional"></a>
+ ロングポーリングを指定するために、この例では `ReceiveMessageAsync` メソッドへの各呼び出しで `WaitTimeSeconds` プロパティを使用しています。

  キューの[作成時](CreateQueue.md)または[更新時](UpdateSqsQueue.md)に `ReceiveMessageWaitTimeSeconds` 属性を使用して、キューのすべてのメッセージにロングポーリングを指定することもできます。

  ショートポーリングとロングポーリングの違いに関する詳細については、*Amazon Simple Queue Service デベロッパーガイド*の「[ショートポーリングとロングポーリング](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html)」を参照してください。
+ メッセージの処理中に受信ハンドルを使用して、メッセージの可視性タイムアウトを変更できます。その方法については、[AmazonSQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html) クラスの `ChangeMessageVisibilityAsync` メソッドを参照してください。
+ `DeleteMessageAsync` メソッドを無条件で呼び出すと、可視性タイムアウトの設定にかかわらず、メッセージがキューから削除されます。