PowerShell in C# Development

C61c4df7cb3f2da2b4a7e7fe08bca7e1?s=47 guitarrapc
September 26, 2015

PowerShell in C# Development

開発現場でのPowerShell活用について実例を紹介します。

リポジトリ : https://github.com/guitarrapc/Comuplus2015

C61c4df7cb3f2da2b4a7e7fe08bca7e1?s=128

guitarrapc

September 26, 2015
Tweet

Transcript

  1. Sep-26/2015 Comm Tech Festival (COMU+) @guitarrapc_tech

  2. @Job @Private http://tech.guitarrapc.com @guitarrapc_tech https://jpposh.doorkeeper.jp/

  3. あるある もしかして

  4. Just a tool 必要なシーンの見極め

  5. None
  6. VS2015 and PowerShell Roslyn ASP .NET で Razor Helper を使った際のインテリセンスエラー対策

    ->さくっと直す。さくっと使えるツールとしてのPowerShell NuGet AD 利用時にPackage Manager Console の初期化エラー Editor VS でのPowerShell 編集がMSにサポート
  7. Roslyn cause Intellisense error Razor @function Error VS2015 で ASP

    .NET MVC の App_Code に @function/ヘルパーを置くと発生 http://stackoverflow.com/questions/28513532/asp-global-asax-does-not-exist-in-the-namespace-asp View の中に置いた Helper では起こらない Roslyn
  8. Sample Code Roslyn https://github.com/guitarrapc/Comuplus2015/tree/master/RoslynIntellisesnseError

  9. Reproduce Roslyn

  10. Add App_Code, .cshtml and helper Roslyn @functions { public static

    string GetActiveClassIf(string controllerName, string actionName = null) { var routeData = @HttpContext.Current.Request.RequestContext.RouteData; string currentController = routeData.Values["controller"].ToString(); string currentAction = routeData.Values["action"].ToString(); return controllerName == currentController && (String.IsNullOrEmpty(actionName) || currentAction == actionName) ? "active" : ""; } }
  11. Intellisense Error (Repeat on build) Roslyn

  12. Temp File Roslyn

  13. Compile Error is too tough…. ダメな方法 : Microsoft.CodeDom.Providers.DotNetCompilerPlatform NuGet で入れることでRoslyn

    による検出を正常にできる が、/langversion:6 を aspnet_compiler が対応していない (待つしかない) => コンパイル解決ができにゃい http://forums.asp.net/t/2060343.aspx?Compile+error+after+changing+NET+Framework+version+in+MVC+project+in+VS+2015+C ommunity+RTM <system.codedom> <compilers> <compiler language="c#;cs;csharp" extension=".cs“ type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Prov iders.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35“ warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/> </compilers> </system.codedom> Roslyn
  14. Just replace it :) Roslynが検出するTempファイルをビルド後アクションで書き換える system.codedom を使わなければコンパイルで困らない(langversion:5のまま) Roslyn <PropertyGroup> <PostBuildEvent>powershell

    –ExecutionPolicy RemoteSigned - Command "if(![string]::IsNullOrWhiteSpace('$(ProjectDir)')){$(ProjectDir)AfterBuildEvent.ps1}else{'ProjectDir was empty. Skip BuildAfterEvent.ps1'} "</PostBuildEvent> </PropertyGroup>
  15. Replace Temp file Script No effect to production ローカルデバッグのみ対処 $target

    = "$env:TEMP¥Temporary ASP.NET Files¥root"; # 対象のパスがないならさっさと終わる if (!(Test-Path $target)) { [Console]::WriteLine("$target path not found. Exit AfterBuildEvent immediately."); return; } # 対象のパスから C# 6.0 の Roslyn が余計なインテリセンスエラーとして検知する ASP.global_asax が含まれる .cs を拾って置き換える Get-ChildItem $target -Recurse -File ` | where Extension -eq .cs ` | where {(Get-Content $_.FullName -Raw -Encoding utf8).Contains("ASP.global_asax")} ` | %{ $file = $_.FullName; [Console]::WriteLine("Replacing ASP.global_asax to System.Web.HttpApplication for file : {0}" -f $file); # 2度ファイル読み込みが発生してるけど、大したことないので見やすさ優先 (Get-Content $file -Raw -Encoding utf8).Replace("ASP.global_asax", "System.Web.HttpApplication") ` | Out-File -FilePath $file -Encoding utf8; } Roslyn
  16. PackageManager Console Initialization Error VS2015 RTM のままでは NuGet 3.0.0に初期化時にハングする問題多発 1.

    AD の GroupPolicy によるエラー : http://tech.guitarrapc.com/entry/2015/07/24/084117 2. posh-git他、profile.ps1 で ホスト初期化にエラーが起こることも NuGet # 適切にposh-git のprofile.example.ps1 が読めるようにする . $env:UserProfile¥Documents¥WindowsPowerShell¥Modules¥posh-git¥profile.example.ps1
  17. Active Directory Group Policy Don’t restrict too much すでに PowerShell

    の実行を制限すると影響が多々出ることのいい例 NuGet Bad Good
  18. Dear Active Directory Administrator Don’t Force Execution Policy すでに PowerShell

    の実行ポリシーをグループポリシーで強制よくない Idempotency is much better もとの 実行ポリシーに戻るようにレジストリを操作したほうが健全 大事なのは、もとに戻せること、繰り返し実行できること (冪等性) NuGet
  19. VS as a PowerShell Editor 追加サポート Visual Studio 2015 でインストール時に追加可能に

    .ps1 / .psm1 の編集時にインストールされてなければ VSIX への誘導も Editor
  20. Everything in VS All Project file can be complete in

    VS PowerShell ISE つかうとかエディターいちいち変えるのめんどくさすぎ VS で プロジェクトの操作が完結できるといろいろうれしい Editor
  21. PowerShell Tools for Visual Studio インテリセンス / シンタックスハイライト / DSC

    構文サポート(Win10) ファイル追加時の PowerShell サポート Editor
  22. None
  23. Continuous CI – Script Jenkins や AppVeyor などの処理はプロジェクトに仕込んだスクリプトで Deploy –

    DSC? TopShelf は DSC を使った自動デプロイという手段もある 大事なのはやりすぎず、でも便利に。実際ローカルなら DocketTools 便利
  24. Bind to Project Projectに含めるべきは含める CI でどのようにビルドするか、どこにビルドするかは含めるのも手 パスワード etc…は含めないように (Gitなどバージョン管理では特に) メリット

    ビルド設定はCI からスクリプトを呼ぶように => やらなくていいシーン CI
  25. Oh my PowerShell :( ExitCode cmd から PowerShell を呼び出す。 =>

    PowerShell の呼び出し自体が成功すれば ExitCode 0 扱い => PowerShell 内部でのエラーは関係にゃい! try/catch PowerShell に処理を任せる場合は、try/catch でエラーを拾わないとダメ エラーを拾えないと処理が失敗しても成功扱いになる エラー時は exit 1 で EXITCODE を出すこと CI
  26. CI Param( [string]$WorkSpace, # CIのワークスペース [string]$Configuration, # ビルド構成 [string]$ComputerName, #

    デプロイ先PC [string]$BuildTarget, # ビルド環境とか [string]$DestContentPath, # デプロイ先PCの配置パス [string]$UserName, [string]$Password ) $ErrorActionPreference = 'Stop'; try { $msdeploy = "C:¥Program Files¥IIS¥Microsoft Web Deploy V3¥msdeploy.exe"; $project = "ProjectName"; $sourceContentPath = "$WorkSpace¥$project¥bin¥$Configuration"; switch ($BuildTarget) { 分岐A {} 分岐B {} default { $argument = "-verb:sync -source:contentPath=$sourceContentPath - dest:contentPath=$DestContentPath,computerName="http://$ComputerName/MSDeployAgentService",userName="$UserName",password="$Password",includeAc ls="False" Start-Process -FilePath $msdeploy -ArgumentList $argument -Wait -PassThru } } } catch { Write-Error $_; exit -1; } exit 0;
  27. Some of Deploy is complex…. T_T Windows Service TopShelf は

    Windows Service なアプリを簡単に作るためのライブラリ 問題はWindows Service のデプロイは厄介 なにが厄介 インストール前にはサービスが存在しないことの保証が必要 インストールにはデプロイされた .exe への絶対パスが必要 Deploy
  28. No way….. やってられにゃい Deploy

  29. PowerShell DSC is one of choice MSDeploy : 任意のタイミングでビルド -PreSync:runCommand

    でサービスの確認、停止 -PostSync:runCommand でサービスの開始 PowerShell DSC : 定期的にビルド MSDeploy同様に デプロイ対象を指定してデプロイも可能(PUSH) git push -> CIビルド -> Blob/S3 へアップロード -> 自動更新も可能(PULL) インストール状態の保証は DSC が 行うため放置プレイが可能 Deploy
  30. Sample Code https://github.com/guitarrapc/Comuplus2015/tree/master/LightNodeSample Deploy

  31. cS3Content SampleTopShelfContinuousDelivery { S3BucketName = $s3Bucket Key = $zip DestinationPath

    = $downloadPath PreAction = { if(Get-Service | where Name -eq $using:serviceName){ Stop-Service $using:serviceName } if(Test-Path $using:unzipPath){ Remove-Item -Path $using:unzipPath -Recurse -Force } } } Archive SampleTopShelfContinuousDelivery { Ensure = 'Present' Path = $downloadPath Destination = $unzipPath } cTopShelf SampleTopShelfContinuousDelivery { Ensure = "Present" Path = $servicePath ServiceName = $serviceName DependsOn = "[Archive]InstallRapidHouse" } Service SampleTopShelfContinuousDelivery { Name = $serviceName State = 'Running' DependsOn = "[cTopShelf]InstallRapidHouse" } } configuration SampleTopShelfContinuousDelivery { $s3Bucket = "INPUT YOUR S3 BUCKET NAME" $zip = "S3 KEY ZIP FILE NAME" $exe = "SERVICE EXE NAME" $serviceName = "SERVICE NAME DEFINED IN TOPSHELF" $destination = "C:¥DOWNLOADPATH" $downloadPath = Join-Path $destination $zip $unzipPath = Join-Path $destination $serviceName $servicePath = Join-Path $unzipPath "MSBUILD¥EXTRACT¥PATH¥TO¥$exe" Import-DSCResource -ModuleName GraniResource Deploy
  32. None
  33. Test and invoke LightNode | Web API PowerShell は Json

    で返却されるものを取り扱いしやすい LightNode のようにクライアント生成がとても楽な場合でも、 サクッとAPIをテストするのにどうぞ # Invoke-RestMethod はJsonをデシリアライズした結果で取得 Invoke-RestMethod $uri -Method Get
  34. Sample Code API https://github.com/guitarrapc/Comuplus2015/tree/master/LightNodeSample

  35. LightNode Sample irm "http://localhost:8080/api/tests/Echo?x=hoge&y=fuga" -Method Post API

  36. BOM Hell ConvertFrom-Json can’t treat BOM BOM が頭にあると Json の解釈ができず失敗するので注意

    API
  37. None
  38. Package Management PackageManagement (a.k.a. OneGet) 開発ソフトウェアの展開 PowerShellGet PowerShellGet による開発周りのツール展開 (posh-git

    とか)
  39. OneGet can distribute package OneGet Unity や VS2015 など、開発に必要なソフトウェアを OneGet

    で社内配布 Private NuGet を立てられる + NuGet標準なので 構築が簡単 Customize NuGet.Server にすぎないので途中に処理を差し込んだりも可能 Unity の RSS Feed 読んで更新を検知したり OneGet
  40. Sample Code OneGet https://github.com/guitarrapc/Comuplus2015/tree/master/MyOneGetServer

  41. MyOneGet Sample OneGet # Get-PackageSource で Chocolatey の登録がされてない場合 Register-PackageSource -Name

    chocolatey -Provider PSModule -Trusted -Location http://chocolatey.org/api/v2/ # MyOneGet の登録 Register-PackageSource -Name MyOneGet -Location https://myoneget- comtechfest.azurewebsites.net/nuget -Trusted -Force -ProviderName chocolatey # Package 検索 Find-Package -Source MyOneGet
  42. Distribute Dev Tools Windows now automate Package Install Ubuntu や

    Mac にあった portage、Homebrew や apt-get これと似たニュアンスでの OneGet 開発ツールを各自ダウンロード->インストールは終わりにしたいにゃ? 自動化のために、OneGet は使えるとうれしい! OneGet
  43. Still buggy Uncompleted Install but installed!? インストール周りのハンドリングがくず インストールに失敗してもインストールされたことに! 一度アンインストールしてね….!! インストール先の指定ができない

    プロバイダー側の問題と言ってて対処する気なさげ (ほげ OneGet
  44. None
  45. やりすぎない やりすぎと思ったら C# なりにすぐ切り替える 自動化をあきらめない 手段としてPowerShell があることを思い出して!きっと役に立ちます。 cmd にあるなら変えなくていい xcopy

    最高でしょ。
  46. None