20210728のC#に関する記事は6件です。

同期メソッドから非同期メソッドを呼び出す

いろいろあって非同期にできないメソッドから非同期メソッドを呼び出す必要があって、単純に Task.Wait()したらスレッドがデッドロックした。解決するためには? 呼び出される方 public class BarModel{ public int Id {get; set;} public string Name {get; set;} } public class FooService{ public async Task<BarModel> GetBarAsync(){ // ... ここで ToListAsync()とかやる } } 呼び出す方 public class Program{ public static void Main(){ var service = new FooService(); var model = Task.Run(()=>{ return service.GetBarAsync(); }).GetAwaiter().GetResult(); } } 呼び出しを Task.Run() で囲み、 GetAwaiter().GetResult() とする。 正しいかな?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AzureFunctionsでGoogle Workspaceのレポートデータを取得する

こんにちは、ATL Systems 鍋島です。 今回は、Azure Functionsで Google Workspaceのレポートデータを取得する手順について説明していきます。 ちなみに、Consoleアプリで実行する場合は、こちらのドキュメントを公式参考にしてください。 OAuth 認証を使ったサンプルコードがあります。 Google Workspace Admin SDK > .Net >.NET quickstart Reports APIをAzure Functionsなどサーバーで利用する場合、OAuthによる認証を利用できません。その代わりサービスアカウントを使います。 Google Consoleでプロジェクトを追加 まずはサービスアカウントを作る前にプロジェクトを作成します。 Google Consoleにログインします。 https://console.cloud.google.com/ 次に、Google Cloud Platformで新しいプロジェクトを追加します。 ここではプロジェクト名を AzureFunctionProject とします。 プロジェクトを作成したら、作成したプロジェクトに切り替えます。 Admin SDK APIの有効化 次に利用するAPIを有効化します。ここでは Admin SDK APIを有効化していきます。 Admin SDK API を検索して、有効にする ボタンをクリックします。 Google Consoleでサービスアカウントの追加 次に、認証情報を作成ボタンをクリックして、認証情報追加していきます。 使用するAPIはAdmin SDK APIを選択し、アクセスするデータの種類は アプリケーションデータを選択します。 ロールはオーナーを選択します。 最後に完了をクリックして、認証情報の追加を完了します。 サービスアカウントが作成されたことを確認します。 次にReports APIを利用するために、サービスアカウントの設定を変更て、 Google Workspace ドメイン全体の委任を有効にする にチェックを入れます。 チェックを入れると ドメイン全体の委任を変更するには、OAuth 同意画面でプロダクト名を構成する必要があります。 と表示されるので、プロダクト名を入力して、保存 ボタンをクリックします。 Google AdminでクライアントIDの追加 Google Admin で APIの制御 にアクセスします。 Google Admin > セキュリティ > APIの制御 にアクセスします。 https://admin.google.com/ac/owl/domainwidedelegation?hl=ja 次に[新しく追加] ボタンをクリックして、新しいクライアントIDを追加します。ここで登録するクライアントIDは Google Cloud Consoleで追加したサービスアカウントのクライアントIDです。 以下のドキュメントを参考にOAUTHスコープも追加します。 https://developers.google.com/admin-sdk/reports/v1/guides/authorizing 範囲 意味 https://www.googleapis.com/auth/admin.reports.audit.readonly アクティビティレポートを取得するときの読み取り専用アクセス。 https://www.googleapis.com/auth/admin.reports.usage.readonly 使用状況レポートを取得するときの読み取り専用アクセス。 サービスアカウントで秘密鍵の作成 Google Cloud Platformに戻り、サービスアカウントメニューから作成したサービスアカウントを表示して、キータブを表示します。 JSONを選択して、作成ボタンをクリックして、秘密鍵ファイルを作成します。 秘密鍵入りのJSONファイルが端末へ保存されると、以下のメッセージが表示されます。 AzureFunctions のプロジェクトの作成 Visual Studio 2019を起動し、新しいプロジェクトを作成します。 スケジュールされた間隔で実行される、Time trigger を選択します。 ちなみに実行間隔を5分から1分に変更するには 5 を 1に変更します。 パッケージマネージャーコンソールで必要なパッケージ Google.Apis.Admin.Reports.reports_v1を追加します。 PM> Install-Package Google.Apis.Admin.Reports.reports_v1 秘密鍵ファイルを追加します。 サービスアカウントで作成した秘密鍵ファイルをプロジェクトに追加します。 その際、ファイルのプロパティで出力ディレクトリにコピーを常にコピーするに変更します。 警告 Azureに発行する時には秘密鍵ファイルをAzure KeyValutなどのキーコンテナと連携することをお勧めします。KeyVaultはjson形式のファイルをサポートしていないので、ひと工夫必要で、別の機会に記事化する予定です。 最後に、Azure Functionsのコードを変更します。 Functions1.csを開いて、以下のコードを貼り付けます。 コード中の以下のワークスペース名や定数については各自の環境に合わせて変更してください。 項目 値 Google Workspaceの管理者ユーザ foo@exmaple.com 秘密鍵のファイル名 azurefunctionproject-123456789.json using Google.Apis.Admin.Reports.reports_v1; using Google.Apis.Admin.Reports.reports_v1.Data; using Google.Apis.Auth.OAuth2; using Google.Apis.Services; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using static Google.Apis.Admin.Reports.reports_v1.ActivitiesResource.ListRequest; namespace GoogleWorkspaceReportsFunctionApp { public static class Function1 { static string[] Scopes = { ReportsService.Scope.AdminReportsAuditReadonly, ReportsService.Scope.AdminReportsUsageReadonly }; static string ApplicationName = "Reports API .NET Quickstart"; static string User = "foo@example.com"; static string JsonPath = "azurefunctionproject-123456789.json"; [FunctionName("Function1")] public static void RunAsync([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log) { log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); //以下のドキュメントが参考になった。 //CreateWithUserで特定のユーザとしてクレデンシャルを作成すると401にならない。 //https://github.com/googleapis/google-api-dotnet-client/issues/1629 var credential = GoogleCredential.FromFile(JsonPath).CreateScoped(Scopes).CreateWithUser(User); // Create Reports API service. var service = new ReportsService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = ApplicationName, }); // Define parameters of request. ActivitiesResource.ListRequest request = service.Activities.List("all", ApplicationNameEnum.Login); request.MaxResults = 10; // List activities. IList<Activity> activities = request.Execute().Items; Console.WriteLine("Logins:"); if (activities != null && activities.Count > 0) { foreach (var activityItem in activities) { Console.WriteLine("{0}: {1} {2}", activityItem.Id.Time, activityItem.Actor.Email, activityItem.Events.First<Activity.EventsData>().Name); } } else { Console.WriteLine("No logins found."); } Console.Read(); } } } エミュレーターの実行 最後にエミュレータを実行して試します。 うまくいきましたね! まとめ Azure Functionsのエミュレータで Google Workspaceのレポートデータを取得できました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#で日付を和暦で表示したい場合

C#のコードを書く際に、日付を和暦で表示したい場合の方法についてまとめた。 日付を和暦で表示するための準備 まずは名前空間に using System.Globalization; を定義する。 そして、クラスやメソッド内にCultureInfoクラスを定義する。引数は「ja-JP」。 var culture = new CultureInfo("ja-JP"); culture.DateTimeFormat.Calendar = new JapaneseCalendar(); こうすることで、日付を和暦で表示する準備が整った。 日付を和暦で表示する。 var date1 = new DateTime(2001, 12, 25); Console.WriteLine(date1.ToString("ggyy年M月d日", culture)); // 平成13年12月25日 元号は「gg」で取得できる。 曜日を日本語で取得する var dayOfWeekJapanese = culture.DateTimeFormat.GetDayName(date1.DayOfWeek); Console.WriteLine(dayOfWeekJapanese); // 火曜日 元号名を取得する また、ただ元号名を取得したい場合は、 var gengo = culture.DateTimeFormat.Calendar.GetEra(date1); var gengoName = culture.DateTimeFormat.GetEraName(gengo); Console.WriteLine(gengoName);// 平成 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ASP.NET Core WebAPIでHttpヘッダーの特定のキーの値を取得する。

はじめに リクエストで送られてくる際にHttpヘッダーの特定のキーの値を用いて認証することがあると思います。 今回はASP.NET Core WebAPIプロジェクトを例にしてHttpヘッダーのTESTキーの値を取得してみます。 テンプレートの用意と動作確認 ASP.NET Core WebAPIプロジェクトを立ち上げます。 テンプレートで用意されているWeatherForecastController.csは以下のようになっています。 WeatherForecastController.cs using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; namespace WebApplication1.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } } } まずはそのままビルドし、実行してみます。 立ち上がりました。 次にこちらへGetメソッドでリクエストを送ってみます。 APIが正常に終了し、データが返却されたことを確認できました。 HttpヘッダーのTESTキーに値が入っている場合のみデータが返却されるようにする さて、それでは本題であるHttpヘッダーの特定のキーの値を取得する方法を書いていこうと思います。 認証的にはとてつもなくダメダメな例ではありますが、TESTキーに値が入っている場合はデータが返却され、入っていない場合は401エラー(Unauthorized)が返却される仕様を例にサンプルコードを書いていきましょう。 Httpヘッダーの特定のキーの値を取得する際は以下のHttpRequest.Headersプロパティを利用します。 こちらを用いると先ほど記載したテンプレート(WeatherForecastController.cs)のGetメソッドは以下のように書けます。 WeatherForecastController2.cs [HttpGet] // エラー時の対処のために戻り値の型をActionResultで囲っています。 public ActionResult<IEnumerable<WeatherForecast>> Get() { //ControllerBaseクラスを継承しているため、その中のRequestプロパティを利用。 Request.Headers.TryGetValue("TEST", out var extractedApiKey); if (string.IsNullOrEmpty(extractedApiKey)) { return Unauthorized(); } var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } 動作を確認してみましょう。 TESTキーをセットしていない場合 TESTキーをセットしていない場合は401エラーで落ちます。 TESTキーをセットした場合 TESTキーをセットした場合は値が返却されていることが分かります。 おわりに 以上、Httpヘッダーの特定のキーから値を取得する方法でした。 同様の処理を行う方々の参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#の基本イディオムについてその6~DateTime構造体~

C#での日時・時間の設定・取得をできるDateTime構造体についてまとめた。 DateTimeに値を設定する DateTimeには、 ・年 ・月 ・日 ・時 ・分 ・秒 ・1/1000秒(ミリセカンド) の値をセットすることができる var date1 = new DateTime(2007, 7, 7); DateTime date2 = new DateTime(2011, 1, 1, 11, 3, 5); var date3 = new DateTime(2000, 1, 1, 12, 24, 36, 123); 出力結果 7/7/2007 12:00:00 AM  // date1 1/1/2011 11:03:05 AM // date2 1/1/2000 12:24:36 PM // date3 ○年月日をセットすると、「セットした年月日 + 時間は午前12時」を返す。 ○年月日と時分秒をセットすると、「セットした年月日 + セットした時分秒」を返す。 ※時間は24時間単位でセットするのだが、返ってくる値は、「12時間単位 + AMかPM」 (例) 時→9、分→5、秒→1 なら、「9:05:01 AM」というように返ってくる。 なぜか、時だけ、0埋めされない。 そして、ミリセカンドはセットしても、時間には表示されない。 また、時分秒を入れる場合は、全部セットしないといけない。 不思議なのが、年月日だけ日、月、年の順で表示される。 以下の書き方は構文エラーになる var date3 = new DateTime(2007, 7, 7, 1);  // 分と秒がセットされていない var date4 = new DateTime(2007, 7, 7, 1, 1); // 秒がセットされていない 「今」と「今日」を取得する場合は特殊 var now = DateTime.Now; var today = DateTime.Today; 7/28/2021 9:51:57 PM  // now 7/28/2021 12:00:00 AM // Today Nowの場合、今の日付と今の時間を返す。 Todayの場合、今の日付を返すが、時間は「12:00:00 AM」を返す。 DateTime構造体のプロパティ DateTime構造体はいくつかプロパティを持っている。 var date3 = new DateTime(2000, 1, 1, 12, 24, 36, 123); date5.Year; // 年 2000 date5.Month; // 月 1 date5.Day; // 日 1 date5.Hour; // 時 12 date5.Minute; // 分 24 date5.Second; // 秒 36 date5.Millisecond; // 1/1000秒 123 ただし、上記のプロパティは読み取り専用なので、値を書き換えることはできない。 構文エラー date5.Hour = 21; 「CS0200: Property or indexer 'DateTime.XXXX' cannot be assigned to -- it is read only (CS0200) (xxxxxxxxxxx)」という「読み取り専用の値は変更ができない」といった旨の構文エラーになる。 曜日を取得する date3.DayOfWeek; // Saturday 曜日は英語で返ってくる。 うるう年かどうかを判定する なんと、C#の日時操作には、年がうるう年かどうかを判定するメソッドがある。 DateTime.IsLeepYear(2016); // True DateTime.IsLeapYear(2018); // True 文字列からDateTimeのオブジェクトを作成する この場合は、DateTime構造体に含まれている静的メソッドであるTryParseを使用する。 また、TryParseメソッドで値が変換されれば、Trueが返り、変換ができないと例外が発生する。 第一引数に変換する日時の文字列、第二引数にoutキーワード付きのDateTime型の変数を指定する。 Console.WriteLine(date2); // この時点では、「1/1/2011 11:03:05 AM」が返ってくる // date2はDateTime型なので、変換され、Trueが返るので条件を満たす。 if(DateTime.TryParse("2020/1/1 14:15:30", out date2)) {  Console.WriteLine(date2);      // この時点で、「2020/1/1 2:15:30  PM」が返ってくる } 出力結果 1/1/2011 11:03:05 AM 1/1/2020 2:15:30 PM DateTime型の変数をフォーマットを指定して文字列に変換する var date3 = new DateTime(2000, 1, 1, 12, 24, 36); date3.ToString("d"); // 1/1/2000 date3.ToString("D");  // Saturday, January 1, 2000 date3.ToString("yyyy-MM-dd") // 2000-01-01 date3.ToString("yyyy年MM月dd日(ddd)"); // 2000年01月01日(Sat) date3.ToString("HH時mm分ss秒"); // 12時24分36秒 date3.ToString("f"); // Saturday, January 1, 2000 12:24 PM date3.ToString("F"); // Saturday, January 1, 2000 12:24:36 PM date3.ToString("t"); // 12:24 PM date3.ToString("T"); // 12:24:36 PM ※フォーマットについてはいろいろある。 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# PowerPoint プレゼンテーションに動画を追加

パワーポイントで作ったプレゼンテーションに音声付きの動画を挿入することで聞き手の注目を集めることができますし、プレゼンテーションを鮮やかな手段で、一層ビジュアル化させることができます。さあ、今日はFree Spire.Presentationという無料のライブラリを使って、プレゼンテーションに動画を追加する方法を紹介します。  下準備 1.E-iceblueの公式サイトからFree Spire. Presentation無料版をダウンロードしてください。 2.Visual Studioを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire. Presentation.dllを参照に追加してください。 (Net 4.0を例としたら、デフォルトパスは“Bin→NET4.0→Presentation.dll”というようになります。) ビデオ(動画)を挿入 using System.Drawing; using Spire.Presentation; namespace ConsoleApp6 { class Program { static void Main(string[] args) { //PPTファイルをロードします。 Presentation ppt = new Presentation(); ppt.LoadFromFile("サンプル.pptx"); //スライドを取得します。 ISlide slide = ppt.Slides[0]; //スライドに動画を挿入します。 slide.Shapes.AppendVideoMedia(@"ビデオ.mp4", new RectangleF(300, 150, 300, 150)); ppt.SaveToFile("動画追加.pptx", FileFormat.Pptx2010); } } } 実行結果 using System.Drawing; using Spire.Presentation; namespace ConsoleApp6 { class Program { static void Main(string[] args) { //PPTファイルをロードします。 Presentation ppt = new Presentation(); ppt.LoadFromFile(@"動画追加.pptx"); int i = 0; //スライドをループします。 foreach (ISlide slide in ppt.Slides) { //スライド内のシェイプをループします。 foreach (IShape shape in slide.Shapes) { //シェイプが動画なのか判断します。 if (shape is IVideo) { //動画を保存します。 (shape as IVideo).EmbeddedVideoData.SaveToFile(string.Format(@"動画{0}.mp4", i)); i++; } } }      
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む