简体   繁体   中英

Some powershell cmd-lets not available if run from python?

So this is an unusual one, and perhaps I am simply missing the obvious, but I have the following python code that creates a powershell script and runs it.

# Create the PowerShell file 
f = open("getKey.ps1", "w")

f.write('$c = Get-BitlockerVolume -MountPoint C:\n')
f.write('$c.KeyProtector[1].RecoveryPassword | Out-File C:\\Temp\\recovery.key\n')

# Invoke Script
startPS = subprocess.Popen([r'C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe',
                                           '-ExecutionPolicy', 'Unrestricted', './getKey.ps1'], cwd=os.getcwd())

result = startPS.wait()

When this is run, it gives me the following error:

The term 'Get-BitlockerVolume' is not recognized as the name of a cmdlet, function, script file, or operable program.

However, if I then go and manually run the generated script, it works perfectly. To add to the oddity, if I run the same command exactly as above ie:

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted ./getKey.ps1

it also works exactly as expected.

Clearly, the above error is a powershell error, so it is successfully running the script. It almost seems like powershell somehow knows that this is being run from python and has some restricted library of commands when a script is run from a particular source. I grant that that idea makes no real sense, but it's certainly how things appear.

I don't think this is a permissions issue, because when you run the same command from an unelevated powershell prompt, you get an Access is denied type error, rather than a command doesn't exist kind of error.

Anyway, any help would be greatly appreciated!

  • Edits

Edit: New evidence to help figure this out:

It's definitely an issue of cmdlets being loaded properly. If I programmatically run a script to dump the list of all available commands to a text file, it is only about 2/3's as big as if I do so through a powershell prompt directly

I bet Python is running as a 32-bit process on 64-bit Windows. In this case, you'll end up running 32-bit PowerShell, which in practice is a Bad Thing since many PowerShell modules depend on native binaries that may not have 32-bit equivalents. I hit this with IIS Manager commandlets--the commandlets themselves are registered in 32-bit PowerShell, but the underlying COM objects they rely on are not.

If you need to run 64-bit PowerShell from a 32-bit process, specify the path as %SystemRoot%\\SysNative\\WindowsPowerShell\\v1.0\\PowerShell.exe instead of System32.

System32 is actually virtualized for 32-bit processes and refers to the 32-bit binaries in %SystemRoot%\\SysWow64. This is why your paths (and PSMODULEPATH) will look the same, but aren't. (SysNative is also a virtualized path that only exists in virtualized 32-bit processes.)

Adding to what @jbsmith said in the comment, also check to make sure that the environment variable that PowerShell relies on to know where it's modules are is populated correctly when python starts the process.

%PSMODULEPATH% is the environment variable in question, and it works the same way the %PATH% variable does, multiple directories separated by ; . Based on what you say your observed behavior is, it seems that you are using PowerShell 3.0, and cmdlet autoloading is in effect.

The solution here: Run a powershell script from python that uses Web-Administration module got me the cmdlet I needed, however there are still missing cmdlets even when using this method. I'm still at a loss as to why some are loaded and others are not, but for the time being, my script does what I need it to and I can't spend any more time to figure it out.

For reference here is the code that worked for me

startPS = subprocess.Popen([r'C:\Windows\sysnative\cmd.exe', '/c', 'powershell',
    '-ExecutionPolicy', 'Unrestricted', './getKey.ps1'], cwd=os.getcwd())

I had the same issue, and it was simply that the BitLocker feature was not installed, hence the module wasn't present.

I fixed it by installing the Bitlocker feature:

Windows Server:

Install-WindowsFeature BitLocker -IncludeAllSubFeature -IncludeManagementTools -Restart

Windows Desktop:

Enable-WindowsOptionalFeature -Online -FeatureName BitLocker -All

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM