himorogiの日記

主にプログラミングに関することなど。少々ハード(電子工作)についても。

macOS で Powershell - rehabilitation 編 -2 : 環境変数

Env は PSDrive のプロバイダの一つ。

PS /Users/hoge> get-psdrive

Name           Used (GB)     Free (GB) Provider      Root                                Current
                                                                                         Locatio
                                                                                               n
----           ---------     --------- --------      ----                                -------
/                 291.38        173.74 FileSystem    /                                   ...hoge
Alias                                  Alias                                                    
Env                                    Environment                                              
Function                               Function                                                 
Variable                               Variable                                                 


PS /Users/hoge> 

なので Get-ChiledItem してみる。

PS /Users/hoge> gci env: | format-list    


Name  : _
Value : /usr/local/bin/pwsh

Name  : __CF_USER_TEXT_ENCODING
Value : 0x1F5:0x1:0xE

Name  : Apple_PubSub_Socket_Render
Value : /private/tmp/com.apple.launchd.PN8TixRg7E/Render

Name  : COMMAND_MODE
Value : unix2003

Name  : GROOVY_HOME
Value : /Users/hoge/.sdkman/candidates/groovy/current

Name  : HOME
Value : /Users/hoge

Name  : LANG
Value : ja_JP.UTF-8

Name  : LOGNAME
Value : hoge

Name  : PATH
Value : /usr/local/microsoft/powershell/6:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/loca
        l/share/dotnet:~/.dotnet/tools:/Library/Frameworks/Mono.framework/Versions/Current/Comma
        nds:/Applications/Xamarin Workbooks.app/Contents/SharedSupport/path-bin:/Users/hoge/
        .sdkman/candidates/groovy/current/bin

Name  : PSModulePath
Value : /Users/hoge/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/usr
        /local/microsoft/powershell/6/Modules

Name  : PWD
Value : /Users/hoge

Name  : SDKMAN_CANDIDATES_API
Value : https://api.sdkman.io/2

Name  : SDKMAN_CANDIDATES_DIR
Value : /Users/hoge/.sdkman/candidates

Name  : SDKMAN_DIR
Value : /Users/hoge/.sdkman

Name  : SDKMAN_PLATFORM
Value : Darwin

Name  : SDKMAN_VERSION
Value : 5.7.3+337

Name  : SHELL
Value : /bin/bash

Name  : SHLVL
Value : 2

Name  : SSH_AUTH_SOCK
Value : /private/tmp/com.apple.launchd.5dmj0JEs17/Listeners

Name  : TERM
Value : xterm-256color

Name  : TERM_PROGRAM
Value : vscode

Name  : TERM_PROGRAM_VERSION
Value : 1.32.3

Name  : TMPDIR
Value : /var/folders/xj/qkbp11_91mg0blbzgp2tmcw80000gn/T/

Name  : USER
Value : hoge

Name  : XPC_FLAGS
Value : 0x0

Name  : XPC_SERVICE_NAME
Value : 0



PS /Users/hoge>

環境変数 PATH の参照。

PS /Users/hoge> gci env:PATH | format-list


Name  : PATH
Value : /usr/local/microsoft/powershell/6:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/loca
        l/share/dotnet:~/.dotnet/tools:/Library/Frameworks/Mono.framework/Versions/Current/Comma
        nds:/Applications/Xamarin Workbooks.app/Contents/SharedSupport/path-bin:/Users/hoge/
        .sdkman/candidates/groovy/current/bin


PS /Users/hoge>

つながって見にくいので、PATH 毎に改行いれてみた。

PS /Users/hoge> gci env:PATH |%{ $_.value -replace ( ":","`n" ) }
/usr/local/microsoft/powershell/6
/usr/bin
/bin
/usr/sbin
/usr/local/share/dotnet
~/.dotnet/tools
/Library/Frameworks/Mono.framework/Versions/Current/Commands
/Applications/Xamarin Workbooks.app/Contents/SharedSupport/path-bin
/Users/hoge/.sdkman/candidates/groovy/current/bin
PS /Users/hoge> 

変数 $env としても参照できる。同じ PATH 見てもつまらない(?)ので PSModulePath。

PS /Users/hoge> $env:PSModulePath |%{ $_ -replace (":","`n")}
/Users/hoge/.local/share/powershell/Modules
/usr/local/share/powershell/Modules
/usr/local/microsoft/powershell/6/Modules
PS /Users/hoge>

macOS で Powershell - rehabilitation 編 -1 : スクリプトファイルの起動

macOS での Powershell core について記事を書こうと思っていたけど、風邪でヘタってしまった。
まだ本調子ではないのと、Powershell を使わなくなって2年以上経過してしまったので、今回からしばらくは軽いネタ。

Powershellスクリプトファイルの実行方法は…

  1. Powershell(pwsh)の中から .file path で起動
  2. bash から pwsh -File で起動
  3. スクリプトファイルに shebang を埋め込んで、実行権限付与で起動

の3通りがある(他にもあるかもしれないけど、今ちょっと思いつかない)。

1. と2. の場合、Windows では予め実行権限(Executionpolicy)の設定を確認する必要があるのだけど Powershell core は Executionpolicy が Unrestrikted 固定で変更できないため無視でき、スクリプトファイルには単にスクリプトを記載するだけで済む。

script を pipe で set-content に渡している。
set-content は WindowsPowershell では alias が sc だったけど、bash のコマンドとぶつかるので Powershell core ではこの alias は使えないっぽい。

PS /Users/hoge> "Write-Host 'Hello World'" | set-content develop/hello.ps1 
PS /Users/hoge>

1. Powershell(pwsh)の中から .file path で呼び出す

PS /Users/hoge> ./develop/hello.ps1
Hello World
PS /Users/hoge>

2. shell(bash)から pwsh に続けて -FIle オプションで呼び出す

MacTheKnife:~ hoge$ pwsh -FILE develop/hello.ps1
Hello World
MacTheKnife:~ hoge$ 

3. の場合、スクリプトファイルに shebang を埋め込む。

shebang を埋め込む都合で script が2行になったので、here-string を pipe で set-content に渡している。

PS /Users/hoge> @"
#!/usr/local/bin/pwsh -File
Write-Host 'test!!'
"@ | set-content develop/test.ps1
PS /Users/hoge>

shell(bash)からスクリプトファイルに実効権限を付与し、スクリプトファイルを呼ぶ。

MacTheKnife:~ hoge$  chmod +x Develop/test.ps1
MacTheKnife:~ hoge$  Develop/test.ps1
test!!
MacTheKnife:~ hoge$  

macOS で Powershell - install 編

定年までの現役時代 Windows 端末しか使えず、でちょっと凝った(スマートな)処理をしようとすると、VBA を使うことになるのが嫌だった。
VBA も悪くはないけど、C 系の記法を一度経験した身には、少し野暮ったい。

そういうわけで、定年前の職場に移動直後( 10 年くらい前)は、WindowsScriptHost(WSH)でゴリゴリ書いてた。
Windows7 になってからは Powershell を利用して、バッチ処理走らせたり、コマンドやアプリケーションをフィルタ化してパイプで連携したりしてたので、つまり Powershell に馴染んでしまった。

定年後、macOS を好きなように弄れるようになったけど、(Javascript for Automation という手もあるけど)今更 AppleScript はまどろっこしい、
中途半端に覚えてる bash script (というか PerlRubyPython)よりも、Powershell 使いたいな…と思ってたら、macOS にも Powershell がやってきた。

macOS への PowerShell Core のインストール | Microsoft Docsdocs.microsoft.com

細かい手順は上記のリンク先を参照してもらうとして、私は既に Homebrew も Homebrew-Cask も install 済みなので、以下の手順で install できた。

brew cask install powershell

実は、既に macOSPowershell をインストール済み(MS から初めて公海されたとき、直ぐに入れた)なので、実際には upgrade を実行しただけである。

brew update
brew cask upgrade powershell

Homebrew、及び Homebrew-Cask は macOS に最初から入っているわけではないので、予め install しておく必要がある。
やり方は簡単なので、各自 Homebrew、Homebrew-Cask で検索し、手順を確認してほしい。

なお、terminal(私は VisualCode Studio 使ってる)から Powershell の起動するには pwsh をタイプする。

MacTheKnife:~ hoge$ pwsh
PowerShell 6.1.3
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /Users/hoge> 

とりあえず get-executionpolicy 実行してみた

PS /Users/hoge> get-executionpolicy
Unrestricted
PS /Users/hoge> 

駄菓子菓子、set-executionpolicy は操作できないっぽい。PlatformNotSupportedException だってお。

PS /Users/hoge> set-executionpolicy restricted
set-executionpolicy : Operation is not supported on this platform.
At line:1 char:1
+ set-executionpolicy restricted
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Set-ExecutionPolicy], PlatformNotSupportedException
+ FullyQualifiedErrorId : System.PlatformNotSupportedException,Microsoft.PowerShell.Commands.SetE
xecutionPolicyCommand
 
PS /Users/hoge> 

【2019/03/04 ここから追記】
PowerShell Core 6.0 の新機能 | Microsoft Docsdocs.microsoft.com
上記情報によると…

スクリプト エンジンは現在サポートされていないため、Windows 以外のプラットフォームで PowerShell を実行するときは -ExecutionPolicy スイッチを無視します。 (#3481)

【2019/03/04 追記終わり】

Powershell の中から JSC(JavaScriptCore)を呼び出してみた。
JSC は macOSbash で呼べる Javascript shell。
macOS には標準で入ってる(多分 /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc)ので、スクリプトファイルなら shebang 書けば直ちに実行できるはず。
対話的(REPL)に使いたいなら JSC への path を通しておく。
まぁ、今なら JSC より node.js なんだろうけど、それを言ったら macOS 環境に Powershell (しかもまだ移植が半端)入れる意味って…

PS /Users/hoge> jsc 
>>> print("Hello World!");
Hello World!
undefined
>>> quit();
PS /Users/hoge> 

VBA から commad.com や PowerShell を呼び出す

社会人になってから30余年、ずっとプログラマでやってきたけど、もう Excel VBA とか MacOS なら AppleScriptAutomator より面倒くさい仕事(コーディング)はしたくない。

かといって Excel VBA でコーディングするのは、コードがシンプルに書けないから嫌だ。
以前は ScriptControl で JScriptVBA モジュールに埋め込んでたが、64bit 環境では使えないっぽい。

ならばいっそ、VBA 環境から PowerShell を呼びだせば pipe も使えて良いんじゃね、と調べてみた。

anosonote.hatenablog.com

thom.hateblo.jp

上記の情報とコードを元に、以下のモジュールを書いてみた。

函数 doCmdSh は command prompt と PowerShell呼び出しについて共通両方に対応している。
ただし PowerShell のコマンド文字列を渡すときのみ、第二引数に true を添える(モードスイッチ)。

他は特に説明要らないと思う。

Function doCmdSh( _
        ByVal cmdStr As String, _
        Optional ByVal pwrsw As Boolean = False _
    ) As String
    Dim Wsh: Set Wsh = CreateObject("Wscript.shell")
    Dim Fso: Set Fso = CreateObject("Scripting.FileSystemObject")
    Dim tempPath As String: tempPath = Environ$("temp") & "\" & Fso.GetTempName: Fso.CreateTextFile (tempPath)
    Dim cmdBody
    If Not pwrsw Then
        cmdBody = "cmd.exe /c " & cmdStr & " > " & tempPath
    Else
        cmdBody = "powershell -ExecutionPolicy RemoteSigned -Command Invoke-Expression """
        cmdBody = cmdBody & cmdStr & " | Out-File -filePath " & tempPath & " -encoding Default"""
    End If

    Wsh.Run cmdBody, 0, True ' WshHide = 0
    
    Dim result As String
    Dim strm As Object: Set strm = Fso.OpenTextFile(tempPath, 1) ' ForReading = 1
    result = strm.ReadAll
    strm.Close
    Call Fso.DeleteFile(tempPath, True)
    doCmdSh = result
End Function

Function doCmdShAsArray(cmdString As String, Optional ByVal pwrsw As Boolean = False) As String()
    doPwrShAsArray = Split(doPwrSh(cmdString, pwrsw), vbNewLine)
End Function

2017/08/20 22:22 追記
doCmdSh で awk 呼ぶのも良いかも。

WSH の参照設定一覧

PowerShell を使うようになると .Net Framework が利用できるので WSH の参照設定を忘れてしまいそうになってる。

WSH(や VBA からの)参照設定は、なかなか一つに纏まった資料がないため、必要なる度に必死になって検索していたけど、昔作ったコードは、開発環境(端末若しくは職場)が変わるたびにアクセスできなくなし、勤めてるときは下手にコードをクラウドにも置けないので、殆ど手元に残ってない。

VBA ならは VBE の参照設定フォームから選択することもできるけど、この方法だと参照設定がコードに明示的に示されないため、あとからメンテナンスする人が結構やりづらい。VBA は基本的に使い捨ての道具だと思うので、あまり共有すべきではないのだけど。
ともかく人様が纏めてくれた記事へのリンクを紹介する。

http://www.thom.jp/vbainfo/refsetting.htmlwww.thom.jp

ProgID や GUID、参照名称のリスト、及びそのリストを取得するスクリプトも作っていたけど現在手元には無いので、そのうち思い出したら投稿する。

はてなダイアリーから移行しました

 

Qiita に投稿する内容の下書きというか、ネタの覚書を先ずははてなブログに書いてゆきます。

推敲・統合したら逐次 Qiita にあげてゆきますので、ここは実験室みたな感じで。 

 <追記>

はてなダイアリーから移行ついでに、初期の記事を読み返してみたら… Java やってたんだな…俺。

もう Java なんか忘れちゃったよ。