PowerShell(7以降)でConvertTo-SecureStringが動かない事がある
PowerShellでスクリプトを書いていて遊んでいてとてもはまった出来事。
何のことか
- PowerShell7がインストールされている環境でスクリプト(PythonやJavaScript1)経由でConvertTo-SecureStringを呼ぶとなぜか失敗する
- PowerShell7のコマンドプロンプトやConvertTo-SecureStringや(Windowsで標準インストールされている)PowerShell5から呼び出した場合は動作する
サンプルコード
以下のサンプルコードはPowerShell 7環境から呼び出すと失敗します。
#!/usr/bin/env python3
import subprocess
PWSH = 'powershell -Command'
def run_powershell(cmd: str) -> None:
'''PowerShellコマンドを実行する'''
cmd = f'{PWSH} "{cmd}"'
rslt = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True, encoding='cp932')
if rslt.stdout:
print('成功')
for v in rslt.stdout.splitlines():
print(v)
else:
print(f'失敗: {cmd}')
for v in rslt.stderr.splitlines():
print(v)
def main():
cmd = 'ConvertTo-SecureString -AsPlainText \\"hogehoge\\" -Force'
run_powershell(cmd)
if __name__=="__main__":
main()
どういうことなのか
スクリプト経由でPowerShellのコマンドを呼び出す場合、各スクリプトの新しいプロセスを呼び出す関数(Pythonだとsubprocess.run辺り)を使います。
このとき、PowerShellのコマンドを使う場合は実行関数としてpowershell.exe2を、引数として-Commandを使います。
このときの動作は以下の流れになります。
powerShell 7 → cmd → powershell → ConvertToSecureString
どうやらこの処理にバグがあるようで、ConvertToSecureString関数が実行ファイルを見つけられず失敗してしまうようです。
対処方法
対処方法としては以下の二種類があります。
- PowerShell5から実行する
- 環境変数PSModulePathの値を削除する
上記コードの該当箇所を以下のように変更する。
# cmd = 'ConvertTo-SecureString -AsPlainText \\"hogehoge\\" -Force'
cmd = 'Remove-Item Env:PSModulePath;ConvertTo-SecureString -AsPlainText \\"hogehoge\\" -Force'
最後に
日本語の情報が無くて本当に苦労したよ…