Some powershell cmd-lets not available if run from python? - 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

Related

Java ProcessBuilder cant run ".\venv\Scripts\active" in windows

Using Java's ProcessBuilder, I try to run a python script with activating virtual environment but i'm getting error like '.\venv\Scripts\activate" "' is not recognized as an internal or external command.
In command window cmd, I can use ".\venv\Scripts\activate" directly with no problem but in my code at below, error occured.
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c","cd C:\\Users\\onurc\\PycharmProjects\\OCR", "& .\\venv\\Scripts\\activate", "& python main.py");
That command doesn't look valid to me. You may be confused about what ProcessBuilder does / how windows (or any OS) works.
When you type a command in a dosbox or terminal, you're sending it to the shell - on linux, probably /bin/bash, or zsh or whatnot. On windows, you're sending it to cmd.exe. That program (so, bash or cmd) then decodes what you typed and does all sorts of fancy things to it, and then it in turns asks the underlying kernel to actually go run that app.
Java's ProcessBuilder does not invoke cmd/bash/zsh, it is a sibling to cmd/bash/zsh - it also does some fancy things, but far fewer fancy things. On windows, even the OS (or rather, the tool) does some fancy things whereas on linux it does not.
In general, trying to even guess whether the tool you run does fancy things, and which fancy things java's ProcessBuilder does, is not a sound way to write dependable software. Especially considering the relative hardship of testing this, given that it involves invoking external stuff.
Hence, you should opt out. Of all the fancy things. Thus:
Always call the command with a complete and absolute path.
Always use the multi-string/list version, never rely on java to split on spaces.
Never use *, ? or any other glob. Write out each and every parameter in full.
Do not try to use > or & or any other 'symbol that means something specific'. An OS doesn't support any of this stuff - you just pass [A] the full path to an executable and [B] a bunch of strings that the kernel will directly pass to the process without doing any processing on it. If you want to do stuff to standard out, error out, or standard in - then use Process's methods to do this.
Those &s in your command sure look like shellisms to me.
To fix:
You can tell the process which directory to run in, so there is no need for a cd command.
You should write the absolute path to CMD.exe. You can ask the environment. You're now relying on a combination of a properly configured PATH + the undefined behaviour of the JVM that does a bare minimum of fancy things (turning relative paths to absolute ones by PATH-scanning is a 'fancy thing' you should not be relying on).
I don't know what that & thing is, but you don't want that.
If activate is a script (shouldn't that end in .bat or .js or .vbs or whatnot?), run that, then run python separately. If activate sets things in the local environment table, make a script file that runs both and run the script instead.
Running python is not a good idea. Run C:\whatever\python.exe.
You have the right idea for activate, more or less (you're in a known dir and then write an actual path. If python.exe is guaranteeed to be in that OCR dir, run .\\python.exe, not python.
Convert command as a single string instead of passing separate arguments to the ProcessBuilder.
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c","cd C:\\Users\\onurc\\PycharmProjects\\OCR & .\\venv\\Scripts\\activate & python main.py");
Another way could be, if all command has to run under same folder, then change ProcessBuilder working directory using directory method:
Path rootDir = Paths.get("C:\\Users\\onurc\\PycharmProjects\\OCR");
ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/C", ".\\venv\\Scripts\\activate & python main.py");
processBuilder.directory(rootDir.toFile());
Process process = processBuilder.start();
process.waitFor();

Command "python" works in windows power-shell, but not if in a .sh file

Good afternoon,
I have been stuck with this problem for a couple of days now, and can't seem to get out of it.
Before running a model I have to generate the data in a certain format. To do so I have to run a .sh file, in which there are some calls to python. If I run the command "python" inside the power shell(my machine has Windows 10 as the Operating System), it works just fine. I have infact addedd python to the PATH variable of my system variables.
If instead I try to run the .sh file, in which I have calls to python, I get the following behaviour:
PS C:\Users\....\scripts>bash FILE_NAME.sh SRC_FILE.csv
data_mr exist
Start to converting data.
FILE_NAME.sh: line 48: python: command not found
It seems that when I try to run python inside a file, he cannot recognize/retrieve it from the system variables, which seems very odd to me. The bash file I am trying to run is provided by https://github.com/mindspore-ai/models/tree/master/official/gnn/bgcf , hence I doubt the problem is in the file.
Do you have any idea of where the problem could be and how to possibly solve it?
As far as I know, Windows does not have a shell which can handle .sh files. I believe you have a so-called WSL (Windows Subsystem for Linux), which means that you have a Linux/UNIX-system in top of your Windows.
This system has its own environment variables (check env | grep "PATH"). I would advise you to find the location of Python and add it to that specific PATH variable, but be aware that your Windows Python might not run on that Linux/UNIX system.
Oh, now that I think about it: are you talking about bash or GIT-bash?

Python on Windows opens new window

Here's the problem, after installing Python (3.6, 3.7, 3.8) on Microsoft Windows when you invoke it, it opens in a new window.
This question has been raised before, and replies talk about modifying the code to pause the output or keep the program running so it doesn't close the window. I can not modify every python package ever made for windows compatability.
My problem is that this is not how Python works on *nix platforms. Surely there must be a way to get python to execute within a command prompt ?
My immediate issue is that I loose the console output on so many python programs. From Jupyter Notebook to AWS GRC (remote-codecommit).
-=-=-=-=-= ANSWER =-=-=-=-=-
After much frustration, it turns out the problem was related to account privileges.
The behaviour above occurred when a user with elevated rights executed Python.
When I log out and run with another user that is a local admin, it now behaves normally.
I cant tell you the exact difference between elevated rights and local admin, but there is something in the permissioning that effects how Python is run on Windows.
This happened to me when the current directory of the terminal didn't exist (was deleted/renamed after the terminal was started).
Solution: cd to some directory.
Find you python folder and select python.exe and create a shortcut for it.
Example Image
There's probably a better way, but this is a simple workaround.

GOPATH interpreted differently when calling directly versus Python subprocess

I recently found a fix for Python getpass not working on Windows: Python not working in the command line of git bash
Or at least that was the last thing I remember about changing my python configurations. (This is for Python 3.6.1 on Windows 10)
Now I also use Python to other tasks which simply has subprocess calls to type several commands on terminal:
go build ./folder/
mv ./src/ ./bin/
I get the error: go: GOPATH entry is relative; must be absolute: "/c/Users/OP/work". But I don't get it if I type go build ./src/folder myself.
I have GOPATH set to C:\work in Environment Variables. I have tried with a ;.
Is there a way to reverse the alias python every time? Or what is happening exactly when setting an alias for python to winpty?
I'm thinking that when I call go build directly, it is called by either my user profile or system. And when python's subprocess calls it, it calls the opposite. Therefore, I have two GOPATH variables even though I have only 1 set in environment variable.
Side Note: another recent change on GOPATH was changing it from C:/go because it couldn't be the same as GOROOT. That error popped up randomly for some reason. It worked with that setting for a while and I don't remember changing anything before except adding another import package on top of the many other ones already being used.
Update: with type python I get the result: python is aliased to 'winpty python.exe'. Therefore I tried to undo that with unalias python. The new result I get is: python is hashed (/c/Users/OP/AppData/Local/Programs/Python/Python36/python).
This fixed the go build command within Python's subprocess. However, that alias was a fix for another Python issue with using getpass package.
On top of my unalias python fix, I also discovered something interesting: when I change the environment variables for GOPATH from C:\work; to C:\go, all go commands still spit the error go: GOPATH entry is relative; must be absolute: "". I got this same error (but different path) from updating Windows 10 Fall Creators update. Maybe it is related.
Simply closing MINGW and reopening it fixed the issue. So perhaps it was saying a copy of my environment variables and using that as a reference instead of the actual system properties.
I know this is not a popular question, but someone could benefit from my hours of investigating and debugging.
Under Windows you must use a Windows style GOPATH like eg d:\code and probably you should use cmd shell and nothing else. Unfortunately cygwin paths (and probably others too) do no longer work especially for go get reaching out to git.
Stick to Windows paths and Windows shell.

Streaming and shell. Trivial query

The contents of the file a.py are:
a = input()
print(a)
and fearless.txt contains the string : pink floyd.
Now, when I simply type in %a.py < fearless.txt at the command prompt (windows), it gives an error "lost.stdin".
However, when I type %python a.py < fearless.txt, no error occurs.
I don't understand this, given that .py is a recognized extension and is run by python. Shouldn't then, both be equivalent?
Note I'm using the symbol % in place of the actual directory.
( Python version : 3.4.3:9b73f1c3e601 and winXP-32 bit. )
It depends a bit on how the .py files are registered. It should work when the py.exe launcher is set up correctly. You can verify this by looking up the following key in the registry: HKEY_CLASSES_ROOT\Python.File\shell\open\command. The default value should be "C:\WINDOWS\py.exe" "%1" %*.
You can also try using the following instead:
type fearless.txt | a.py
I just noticed that you are using Windows XP. The problem you are seeing might be because of an old Windows bug with redirection. It was said to be fixed at some point, but maybe XP was still partially affected. I suggest you to update your system anyway because Windows XP is no longer supported by Microsoft.
If this is on a Unix system (as I'm guessing it is), you'll need to have a shebang line at the top of the file to tell the kernel that this is a file whose contents need to be executed by the specified interpreter. The .py extension is just a detail and is not used to decide "how to run" the given program.
When you try to run the file without the shebang, it's being executed by your current shell and that's what's giving you the errors. Python doesn't even come into the picture.

Categories

Resources