DBのテーブルを使っているか検索するスクリプト その1
データベースに含まれる全テーブルについて、特定のフォルダに含まれるソースコードで、テーブルが使われているかを検索。保存するという代物を用意しようと考えた。
C#でという事も考えたが、横合いからPowerShellの仕事をかっさらっていくスーパープログラマもいないことなので、学習を含めてPowerShellで実装することにする。
まずはアウトラインから考えると
- GUIをある程度使いながらの実装
- 何度か使う事を考え、さらにデータベースへの接続変数等を保持したいので設定を保存
- ファイルを一つ一つ検索するのも良いがWindowsSearchなどと連携できる形にした方が早くないか
という要件で進めたいと考える。
また、普段EmEditorでのファイルからの検索を利用しているので、
これと速度的にそん色のない物ができたかどうかを判定出来れば良いという結果を出したい。
設定の保存には特殊フォルダを使いたい。
Googleで調べてみると、C#の環境変数呼び出しなどが記載されているが、それではPowerShellらしくない。
何かないかと調べてみるとenv:ドライブについての記述があった。
PowerShell/環境変数一覧を表示する方法・Get-ChildItem env: - Windowsと暮らす
これはPowerShellらしくて良い。早速試してみる。
PS C:\Users\yamaguchi> get-ChildItem env: Name Value ---- ----- ALLUSERSPROFILE C:\ProgramData APPDATA C:\Users\yamaguchi\AppData\Roaming BPADir C:\Program Files (x86)\Microsoft Team Foundation Server 2010 Power Tools\Best Practic... CLIENTNAME Y****T****-n CommonProgramFiles C:\Program Files\Common Files CommonProgramFiles(x86) C:\Program Files (x86)\Common Files CommonProgramW6432 C:\Program Files\Common Files COMPUTERNAME Y****T****-PC ComSpec C:\WINDOWS\system32\cmd.exe ESET_OPTIONS ... HOMEDRIVE C: HOMEPATH \Users\y**** LOCALAPPDATA C:\Users\y****\AppData\Local LOGONSERVER \\Y****-PC NUMBER_OF_PROCESSORS 8 OneDrive C:\Users\y****\OneDrive - 株式会社ぼん家具 OPENSSL_CONF C:\OpenSSL-Win64\bin\openssl.cfg OS Windows_NT Path D:\app\y****\product\11.2.0\client_1\bin;C:\Program Files (x86)\Intel\iCLS Client... PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL PROCESSOR_ARCHITECTURE AMD64 PROCESSOR_IDENTIFIER Intel64 Family 6 Model 94 Stepping 3, GenuineIntel PROCESSOR_LEVEL 6 PROCESSOR_REVISION 5e03 ProgramData C:\ProgramData ProgramFiles C:\Program Files ProgramFiles(x86) C:\Program Files (x86) ProgramW6432 C:\Program Files PSModulePath C:\Users\y****\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerS... PUBLIC C:\Users\Public SESSIONNAME RDP-Tcp#80 SystemDrive C: SystemRoot C:\WINDOWS TEMP C:\Users\Y****~1\AppData\Local\Temp TFSPowerToolDir C:\Program Files (x86)\Microsoft Team Foundation Server 2010 Power Tools\ TMP C:\Users\Y****~1\AppData\Local\Temp USERDOMAIN Y****-PC USERDOMAIN_ROAMINGPROFILE Y****-PC USERNAME y**** USERPROFILE C:\Users\y**** VS100COMNTOOLS C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools\ windir C:\WINDOWS
オブジェクト・配列ではなく、文字列として$path_app_dataに値を放り込むため&1行で記述したいがためにパイプ+カッコで囲んだうえでValueを取る。
念のためAPPDATA2などという無いキーで取った場合でもエラーは出ないのを確認。
2つ以上、要素があった場合にはエラーになるか予期しない処理になりそうだが、
今回はあくまでキー固定なのでこれで取得することにする。
PS C:\Users\yamaguchi> $path_app_data = (get-ChildItem env: | Where-Object {$_.Name -eq "APPDATA"} | Select-Object Value ).Value PS C:\Users\yamaguchi> $path_app_data C:\Users\yamaguchi\AppData\Roaming PS C:\Users\yamaguchi> $path_app_data = (get-ChildItem env: | Where-Object {$_.Name -eq "APPDATA2"} | Select-Object Valu e).Value PS C:\Users\yamaguchi> $path_app_data PS C:\Users\yamaguchi>
考え通りに取得できた。次はこれのエラー処理を含めてps1ファイルに記述を移す。
次はフォルダの存在確認チェック処理。
Test-Path
Test-Path -Path $path_app_data
で行けそうだが、これだとフォルダであろうがファイルであろうが、Trueを返してくる。
- PathType オプションでContainerを選べば他の要素を含むもの、すなわちディレクトリであるかレジストリであればキーと認識する模様。(Leafであれば枝葉、ファイルなどを指すようだ)これで、
Test-Path -Path $path_app_data -PathType Container
にて条件分岐させる。
さて、ここでメッセージボックスを表示させたいと考えてみたものの、実際のところSystem.Windows.Formsを呼び出して処理させている模様。
いくつか当たってみたものの他に方法はなさそうで・・・
あまり好きではないが、これを実装してみる。
#特殊フォルダのパスを確認 if((Test-Path -Path $path_app_data -PathType Container) -eq False){ # メッセージボックスの表示 [System.Windows.Forms.MessageBox]::Show("特殊フォルダ" + $path_app_data + "が存在しないかアクセスできません", "致命的なエラー") exit 1 }
さあ、これでばっちりだ...と思うもののエラーが発生・・・
何故だっと検索すると
> 実は、PowerShellではブール値を先頭に$を付けて $TRUEや$FALSE と表します。
Bool値とNull値の表し方(PowerShell 入門) – PowerShell from Japan!! Blog
Oh...基礎の基礎やんか…。
if((Test-Path -Path $path_app_data -PathType Leaf) -eq $FALSE){ # メッセージボックスの表示 [System.Windows.Forms.MessageBox]::Show("特殊フォルダ" + $path_app_data + "が存在しないかアクセスできません", "致命的なエラー") exit 1 }
さあ、これでOK。一旦PathTypeをLeafに変更して実行してみる。
思いっきり文字化け...。
$OutputEncoding.EncodingNameがUS-ASCIIのために発生するのだという。
Hello, world! : PowerShellでコマンド実行時の文字化け
実際上記の出力を試してみると
PS C:\Users\y****> $OutputEncoding.EncodingName US-ASCII
これを上記のサイトの記述と同様に変更してみる
PS C:\Users\y****> [console]::OutputEncoding BodyName : iso-2022-jp EncodingName : 日本語 (シフト JIS) HeaderName : iso-2022-jp WebName : shift_jis WindowsCodePage : 932 IsBrowserDisplay : True IsBrowserSave : True IsMailNewsDisplay : True IsMailNewsSave : True IsSingleByte : False EncoderFallback : System.Text.InternalEncoderBestFitFallback DecoderFallback : System.Text.InternalDecoderBestFitFallback IsReadOnly : True CodePage : 932 PS C:\Users\y****> $OutputEncoding = [console]::OutputEncoding; PS C:\Users\y****> $OutputEncoding.EncodingName 日本語 (シフト JIS)
気になるのはセッションが切れてからもずっとこれが残るのかという点。
一旦、PowerShellのウィンドウを閉じて開きなおしたときにどう変わるかを確認。
PS C:\Users\y***> $OutputEncoding IsSingleByte : True BodyName : us-ascii EncodingName : US-ASCII HeaderName : us-ascii WebName : us-ascii WindowsCodePage : 1252 IsBrowserDisplay : False IsBrowserSave : False IsMailNewsDisplay : True IsMailNewsSave : True EncoderFallback : System.Text.EncoderReplacementFallback DecoderFallback : System.Text.DecoderReplacementFallback IsReadOnly : True CodePage : 20127 PS C:\Users\y***> $OutputEncoding.EncodingName US-ASCII PS C:\Users\y***>
大丈夫戻っているようだ。処理の中にこれを入れるが、戻す処理は今回は無しで。
もし、途中でおかしな具合になるようであれば、Try-Catch-Finallyで漏れなく戻す処理にしてみよう。
さらに、ファイルがUTF-8のためSJISに変更する。
PowerShellの日本語文字コード: 私家版 ITプロフェッショナルの仕事術
こちらではSJISもしくはUTF-16という事だが、残念ながらVisualStudioCodeが対応できない模様。
さて、大分慣れてきた。
アプリケーション保存用のフォルダを作ることにする。
#このスクリプトのためのフォルダがあるかどうかを判断。 #無ければ作る if((Test-Path -Path $path_my_app_data -PathType Container) -eq $FALSE) { #アプリケーションデータの保存先フォルダを作成する #処理的にはIOを伴うのでtry-catchを入れる try{ #フォルダを作る処理 New-Item -Path $path_my_app_data -ItemType Directory }catch [Exception] { #タイミング的に作られていたら気にせず進む。 #無ければ何らかのエラーなので、エラーメッセージを表示して終了 if((Test-Path -Path $path_my_app_data -PathType Container) -eq $FALSE){ # メッセージボックスの表示 [System.Windows.Forms.MessageBox]::Show( "アプリケーションデータ保存用フォルダ:" + $path_my_app_data + "の作成に失敗しました(" + $error + ")", "致命的なエラー" ) exit 1 } } }
実行結果は
C:\Users\y****\Documents\powershell> c:\Users\y****\Documents\powershell\dbtable_search.ps1 ディレクトリ: C:\Users\y****\AppData\Roaming Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2017/05/25 13:36 DbTableSearch
作成には成功。オブジェクトが返ってくるのか。
これは今回は無視。プラス、同名のファイルがあった時の処理を考えたいところだが、今回は良いかな。
ずいぶんと長くなってきたので、次へ