20210410のC#に関する記事は8件です。

NPOIでWord文書を操作する

はじめに 需要があるかは知らないけれど、Apache POIでMicrosoft Word文書を操作できます。 普通はOLEやらマクロやらを使うけれど、POIでも操作できます。 POIはJavaのライブラリですが、今回はC#用のNPOIでWord文書を操作してみました。 準備 まず、なにはともあれ新規プロジェクトを作成します。 VisualStudio2019を使って、コンソールアプリケーションを作成しました。 次に、NugetでNPOIを参照します。 操作 そしてコードを書きましょう。 今回は 1. 新規ファイル作成 2. テキストを追加 3. 名前をつけて保存 というシンプルなものを作成します。 本来はクラス化するのが良いですが、サンプルのため1ファイルにベタ書きします。 実装 XWPFDocumentインスタンスを生成します。 XWPFDocumentは拡張子がdocx、HWPFDocumentはdocです。 引数にFileStreamを渡すと、既存ファイルを開くことができます。 Paragraph(段落)を追加します。 Run(文字の塊)を追加します。 Runの文字列を「テスト」にします。 これまた例文のセンスが無い。。。 もうひとつRunを追加して、文字列を「モード」にします。 Runのフォントサイズを大きく太字にしてやります。 ここまで設定したら、保存を行います。 書き込み用のFileStreamを用意して、保存します。 using NPOI.XWPF.UserModel; using System.IO; namespace ConsoleAppNPOI { class Program { static void Main(string[] args) { XWPFDocument Doc = new XWPFDocument(); XWPFParagraph Paragraph = Doc.CreateParagraph(); XWPFRun RunTest = Paragraph.CreateRun(); RunTest.SetText("テスト"); RunTest.FontFamily ="Meiryo UI"; XWPFRun RunTest2 = Paragraph.CreateRun(); RunTest2.SetText("モード"); RunTest2.FontFamily = "Meiryo UI"; RunTest2.FontSize = 18; RunTest2.IsBold = true; FileStream s = new FileStream("sample.docx", FileMode.OpenOrCreate, FileAccess.Write); Doc.Write(s); s.Close(); } } } 確認 保存されたファイルを開くと、無事に指定した文字が入っていることがわかります。 (「モード」の主張が強い!) おわりに 今回はものすごくシンプルに文字を入れるだけの超カンタンな操作でした。 実際は表挿入などもっといろいろなことができます。 いつかまたもう少し掘り下げたものを書こうと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure Functions をwindows の IIS へ Deploy して動かす

はじめに 基本は この記事 にかいてるけど、オレも含めて一度は失敗してハマるから覚書する それと、そんな必要あんの?と思うけど、functionsで処理が閉じていれば必要ないが、その向こう側に作成する予定の別APIを開発者がローカルで一気通貫テストしたいと要望あって、ここに行きついた ただ、ひっくるめて、ソースもらってデバックするのが一番早いかもね インストールするもの ASP.Net Core Runtime Hosting Bundle の二つ ダウンロードして、インストールする。 ダウンロードするもの Functions.3.0.14191.zip Functions.3.0.14191.zipをダウンロードした後、IISのサイトフォルダに解凍する たとえば、こんな感じ F:\WebApp\hosting に解凍 正直、解凍するフォルダはどこでもよくて C:\Toolsなんて自分専用のツール格納群フォルダでもいいけど、あとでFunctionsをデプロイした後に、このフォルダの中にある Microsoft.Azure.WebJobs.Script.WebHost.exe へのパスを web.config ファイルへ記述する作業が出てくる。 その際に、絶対パスで記述する事になるが、後々面倒を起こす(開発者毎に設定する必要があって、たいてい一人くらいは動かないと手を挙げる人が出てくる)から、最初からWEBフォルダの中につっこんでおいて、web.config に相対パスで記述して配布すると、面倒が出なくていい。今回は web 用のフォルダに突っ込んでおく。 ちなみに、Microsoft.Azure.WebJobs.Script.WebHost.exe は ここにあるけど、今どきのPCは 64bit なので、次のパスをメモ帳あたりにメモっておく F:\WebApp\hosting\3.0.14191\64bit\Microsoft.Azure.WebJobs.Script.WebHost.exe 次に、ここに site フォルダ作成 site フォルダの中に次の空のフォルダを作成 CSharp Java Node powershell Python 各言語で作成した functions をここに配置するため。 次にローカルIISにデプロイしたい対象のFunctionsプロジェクトから、フォルダーにPublishする たとえば、VisualStudioだと、発行ツール経由で、フォルダにPublishできる 今回、適当な httptrigger の get要求で文字返すAPIをC#で作った。 ↑の中で作成した空フォルダの中では、CSharpフォルダへデプロイする 無事デプロイできた host.json が設定ファイルになる。 各種設定があるなら、ここで編集して設定する。 たとえば、AzureWebJobsStorageみたいな設定のこと web.config の作成 先ほどデプロイしたフォルダに web.config ファイルを新規作成 中身はコレをコピペで張り付け web.config <?xml version="1.0" encoding="utf-8"?> <configuration> <!-- To customize the asp.net core module uncomment and edit the following section. For more info see https://go.microsoft.com/fwlink/?linkid=838655 --> <system.webServer> <handlers> <remove name="aspNetCore" /> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="..\..\3.0.14191\64bit\Microsoft.Azure.WebJobs.Script.WebHost.exe" arguments="" stdoutLogEnabled="false" startupTimeLimit="3600" stdoutLogFile=".\logs\stdout" hostingModel="InProcess" /> <httpProtocol> <customHeaders> <remove name="X-Powered-By" /> </customHeaders> </httpProtocol> <security> <requestFiltering allowDoubleEscaping="true" removeServerHeader="true"> <requestLimits maxQueryString="4096" maxUrl="8192" maxAllowedContentLength="104857600" /> </requestFiltering> </security> </system.webServer> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.0.2.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration> aspNetCore の prosessPath がキモで、これがさっきメモ帳に退避した、Microsoft.Azure.WebJobs.Script.WebHost.exeへのパスになる。 開発者にフォルダ毎配ると面倒がないので、相対パスで記述できるようにした方がよいと思う。 windows IIS の設定 さっきのweb.config見るとわかるけど、InProcessで exe を動かすことになるので、アプリケーションプールには管理者権限が必要になる。 アプリケーションプールの追加 IISマネージャーを起動して、アプリケーションプールを右クリック、プールの追加を選択 名前はなんでもいいから適当につけて追加 作ったプールの詳細設定から、 プロセスモデルのIDをデフォルトのApplicationPoolIdentityから、...を元に ビルトインアカウントをカスタムアカウントに変えて、 自分のローカルPCの管理者権限のあるユーザーに変更する FunctionsはEXE経由で実行することになるから、IISの権限だと動かない 次に、Default WebSite を右クリックしてアプリケーションの追加 エイリアス名は適当に付けて、アプリケーションプールはさっき作成した管理者権限のあるプールを選択 物理パスは、さっき functions をデプロイして、web.configを配置したパスを指定 設定はこれで全て完了。 サイトもローカルIISにできた URLは Azure Functions と同じで、api/xxx になる 補足 Functions の authLevel が anonymous 以外だと動かないと思うので、デプロイした フォルダの中にある function.json を直接編集して、anonymous にするとよい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】クラス名のミスがないのにスクリプトがアタッチできない現象の解決策

概要 Unityを使用していて、スクリプトのファイル名とクラス名が一致しているにも関わらず インスペクターに「No MonoBehaviour scripts in the file~」、 アタッチしようとすると「Can't add script component [コンポーネント名] because the script class~」 と表示され、スクリプトをアタッチできなくなった現象が発生しました。また既にアタッチしてあったスクリプトは全てエラーとなってしまいました。 自分はUnity初心者ではありますが、本現象を解決する方法が分かったので、備忘録&誰かの役に立てばいいなぁと思いここに残しておきます。 筆者の環境 Unity2019.4.20f1(LTS) VisualStudio2017 解決法 結果的には、 C:\Program Files\Unity\Hub\Editor\2019.20f1\Editor\Data\Tools\RoslynScripts 内の unity_csc.bat ファイルをメモ帳で管理者権限で開き、 @ECHO OFF set APPLICATION_CONTENTS=%~dp0..\.. "%APPLICATION_CONTENTS%\Tools\Roslyn\csc.exe" /shared %* exit /b %ERRORLEVEL% 引用:https://www.programmersought.com/article/60285000064/ こちらに書き換えることで直りました。 解決までの流れ まず検索より、この記事にたどり着きました。 この記事の追記にあった から C:\Program Files\Unity\Hub\Editor\2019.20f1\Editor\Data\Tools\RoslynScripts 内の unity_csc.bat ファイルをメモ帳で管理者権限で開き、 記事内で修正すべき文とされている "%APPLICATION_CONTENTS%\Tools\Roslyn\csc" /shared %* を探しましたが、見つかりませんでした。 そこでさらに検索を重ね、こちらの記事を見つけました。 こちらも前の公式記事と言っていることは同じなのですが、書き直した後のファイルの中身が記載されていました。そこでその内容をunity_csc.bat内に書いたところ、エラーが直りました。 備考 Unity2019.4.2~系のバージョンでは時々起こる現象のようです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

別のWindowを表示する

はじめに PrismでMVVMパターンを使用していると、基本的にWindowは一つで、RegionにModuleを表示させるのが基本的な流れです。 Webアプリや最近のアプリでは、Single Windowが基本のように思いますが、業務アプリを作成していると、複数のWindowを使用する必要がでる場合があります。 昔は、MDIアプリケーションが一般的だったように思うのですが、最近はあまり見かけなくなりました。 複数のWindowを使用するアプリを作るために、まずはメインWindowとは別のWindowを表示させる方法の一つを紹介します。 方法は旧来からあるものです。 ただ、以前アプリを開発していた時に、どうすればいいのか悩んだことがあるので、プログラミングを始めたばかりの人には悩みどころの一つではないかと思います。 別Winodowの表示 基本的には、Win Formsでも同じですが、ボタンをクリックしたら、別Windowを表示させるためのコードです。 ボタンをクリックするたびに、Windowが表示されるのは防ぐようにしています。 // ボタンをクリックで呼び出すコード private void ShowWindow() { // SampleWindow : WPF のView Type winType = typeof(SampleWindow); // Windowのインスタンスを取得 Window win = GetWindowInstance(winType); // Windowを表示させます win.Show(); win.Title = "サンプル"; win.Activate(); win.WindowState = WindowState.Normal; } // Windowのインスタンス取得処理 private Window GetWindowInstance(Type winType) { // Windowsを取得 Window win; win =System.Windows.Application.Current.Windows .OfType<Window>() .SingleOrDefault(w => w.GetType() == winType); // まだ表示されていない場合はインスタンスを生成する if (win == null) { win = (Window)Activator.CreateInstance(winType, _regionManager); } return win; } ShowWindowのところで、引数にView(Window)を指定するようにすれば汎用的に使用することもできます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

catch(Exception)のエラー文が見たい

結論 Controller.cs try { hogehoge ...... } catch(Exception e) { return e.Message; } これで 戻り値でエラー文をゲットできた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Google Drive API使ってアップロードから共有リンククリップボードコピーまでやってくれる便利ツールつくった

はじめに 今勤めてる会社でGoogleDriveのお世話になってるんですが、アップロードが結構地味に手間で。 手順的には 資源を用意 適当な場所でZIP圧縮 ブラウザでGoogleDriveのページを開く 一時保存置き場にしているフォルダを開く ZIPをD&Dでアップロード アップロード完了したらファイルに対してドメイン共有を有効にする 共有リンクをコピー と、こんなかんじ... まぁめんどくさいこと。 ということで2〜7をまるっとボタン1発でできないか考え、アプリをつくってみました。 そんなに難しいことはしてないんですが、ちょこちょこハマったところがあるので(あとC#での事例も少なそうだったので)ポイントを共有しておきます。 つくったもの リポジトリはこちら https://github.com/ambleside138/GoogleDriveSender こんなかんじで動かします #キャプチャはプライベートの個人アカウントで動かしたものです アップロードしたいファイル/フォルダを右クリック 送るメニューからアプリ(GoogleDriveSender)を選択 アップロード処理が完了するとクリップボードにリンクURLがコピーされている という流れ。だいぶ手数が減りました! アプリ作成のポイント どうやって1発でアプリを呼び出すか いろいろ方法があると思うんですが、 汎用的(=特定のアプリに依存しない) で、 リスクが低そう(=レジストリいじらない) な手段を検討しました。 軽くググった結果、Windowsの右クリックメニューに用意されている「送る」メニューが比較的カスタマイズしやすい仕様だったのでこちらを利用します。ここからアプリ起動する場合、右クリックメニューの対象となっているファイルパスが第一引数として渡されているようなのでそれを利用します。 GoogleDriveAPIのハマりどころ ▽ 新規追加と更新は明確にAPIを呼び分ける必要がある GoogleDriveではファイル名ではなく独自のIDをもとにファイルを識別しているため、同一ファイルで何度もCreateメソッドを呼んでアップロードしているとドライブ上に同一名称のファイルがいくつも表示されるようになってしまいます。 そこで、同一名称のファイルがアップロード済みであれば更新処理に切り替える仕様にしました。すでにアップロードされているかどうかはFiles.List APIにファイル名を検索条件に渡してファイルの有無で判定してます。 ▽ ドメイン共有 アップロードしたファイルに対して、権限変更のリクエストを送る感じに実装すればOK。 ▽ 共有リンク Files.Create APIの戻り値で取得できるWebViewLinkプロパティが使えました。 そんなこんなで、アップロード部分のロジックは↓のようになってます DriveSender.cs private File Upload(string filePath, DriveService service) { var fileName = System.IO.Path.GetFileName(filePath); var listRequest = service.Files.List(); listRequest.Q = $"name = '{fileName}' and '{_Configuration.DriveDirectoryId}' in parents and trashed=false"; listRequest.Fields = "nextPageToken, files(id, name, webViewLink) "; // アップロード済みのファイルを更新するにはAPIを切り替える必要がある var meta = new File() { Name = System.IO.Path.GetFileName(filePath), }; using var stream = new System.IO.FileStream(filePath, System.IO.FileMode.Open); var file = listRequest.Execute().Files.FirstOrDefault(); if(file != null) { // 更新 var request = service.Files.Update(meta, file.Id, stream, GetMimeType(filePath)); request.Fields = "id, name, webViewLink"; request.KeepRevisionForever = false; _Logger.Info("Request Files.Update"); var result = request.Upload(); if(result.Status == UploadStatus.Failed) throw result.Exception; request.Body.WebViewLink = file.WebViewLink; return request.Body; } else { // 新規追加 meta.MimeType = GetMimeType(filePath); meta.Parents = new List<string> { _Configuration.DriveDirectoryId }; var request = service.Files.Create(meta, stream, GetMimeType(filePath)); request.Fields = "id, name, webViewLink"; request.KeepRevisionForever = false; _Logger.Info("Request Files.Create"); var result = request.Upload(); if (result.Status == UploadStatus.Failed) throw result.Exception; _Logger.Info("権限変更"); { PermissionsResource.CreateRequest permissionRequest; if(string.IsNullOrEmpty(_Configuration.Domain)) { permissionRequest = service.Permissions.Create(new Permission { Type = "anyone", Role = "reader", }, request.ResponseBody.Id); } else { permissionRequest = service.Permissions.Create(new Permission { Type = "domain", Role = "reader", Domain = _Configuration.Domain, }, request.ResponseBody.Id); } _Logger.Info("Request Permissions.Create"); permissionRequest.Execute(); } return request.ResponseBody; } } おわりに ひとつひとつの操作は大したことないんですけど、一日に何度もやってると地味にストレス溜まってたんですよね。思ってたよりは時間かからなかった(実質2日くらい?)ので、もっと早く作ってしまっとけばよかったなぁとちょっと後悔。テンプレ作業を何度も脳死状態でやりつづけるのはプログラマにとってけしからん状態なのでこれからもバシバシ効率化していきます! 参考サイト・記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】Coding Guidelines and Practices@2021の紹介

■概要 VINCENT MAVERICK DURANOさん(Microsft MVP C#)がまとめた[C# Coding Guidelines and Practices 2021]の紹介です。 避けるべき書き方/推奨する書き方の組み合わせが計35個あります。 「こんな書き方ができるのか!?」って発見があり、面白いです。 C#9.0の機能まで使用されています。 ご参考 記事のリンク ■本記事を書いた背景 C#はコードの書き方のバリエーションが多い。 コードの可読性と言語のトレンドを踏まえ、「如何にコーディングすべきか?」と 疑問を持ち、調査した。その過程で見つけた記事を共有します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C# 】Coding Guidelines and Practices@2021の紹介

■概要 VINCENT MAVERICK DURANOさん(Microsft MVP C#)がまとめた[C# Coding Guidelines and Practices 2021]の紹介です。 避けるべき書き方/推奨する書き方の組み合わせが計35個あります。 「こんな書き方ができるのか!?」って発見があり、面白いです。 C#9.0の機能まで使用されています。 ご参考 記事のリンク ■本記事を書いた背景 C#はコードの書き方のバリエーションが多い。 コードの可読性と言語のトレンドを踏まえ、「如何にコーディングすべきか?」と 疑問を持ち、調査した。その過程で見つけた記事を共有します。 同じ悩みを持つ方々のヒントになればと思います。 ==== 追記 ResharperなどVisual studio環境でコーディングが容易になるツールをご存知でしたら、 教えていただけると嬉しいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む