*this question is on windows only. When attempting to retrieve all WiFi passcodes and names stored, I ran into a error running a netsh command due to a mis-encoding of a character through the subprocess module.
Context:
When i run
netsh wlan show profiles name=*
, I notice that only the first result displays its key content. So, to capture all keys, I had to run the command once for every profile name (that I got throughnetsh wlan show profiles
). The problem is, usingsubprocess.run
for each of these this is incredibly slow, so I decided to use one process throughsubprocess.Popen
, and just write to it's stdin.
Testing code:
import subprocess
process = subprocess.Popen(
"cmd",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding='utf-8',
creationflags=subprocess.CREATE_NO_WINDOW)
process.stdin.write(f'netsh wlan show profiles name="Leonard’s iPhone iP15" key=clear\n')
process.stdin.flush()
process.stdin.write(f'echo test’test\n')
process.stdin.flush()
print(process.communicate())
running it has the result:
C:>netsh wlan show profiles name="Leonard’s iPhone iP15" key=clear
Profile "LeonardΓÇÖs iPhone iP15" is not found on the system.
C:>echo test’test
test’test
as you can see, the ’
has been read as ΓÇÖ
in the netsh command result, but correctly in echo and command input area.
This error does not occur when running netsh wlan show profiles name="Leonard’s iPhone iP15" key=clear
directly in CMD, as i get the successful result:
Profile Leonard’s iPhone iP15 on interface Wi-Fi: ...
How can iI have the command correctly passed to netsh? Is there an easier way to do the same thing?
Additional Details:
I chose
encoding='utf-8'
because i had been having problems reading the’
symbol from process.stdout without directly specifying that I wanted to useutf-8
. I have tried other encodings such ascp437
(from this post), andcp1252
(fromlocale.getpreferredencoding
) but these led to more encoding/decoding problems than withutf-8
.
You face a mojibake case:
print("test’test".encode( 'utf-8').decode( 'cp437')) ### testΓÇÖtest
This comes from .stdin.write
as default cmd
code page is OEMCP
in Windows; please check it yourself using
REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage" -v *CP|find "REG_SZ"
The following script should work:
import subprocess
cmd_cmds = '&'.join([
'echo test’test',
'echo "Leonard’s iPhone iP15"',
'netsh wlan show profiles name="Leonard’s iPhone iP15"'
])
process = subprocess.Popen(
f'cmd /C {cmd_cmds}',
# shell = True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding='utf-8',
creationflags=subprocess.CREATE_NO_WINDOW,
process_group=None
)
for xx in process.communicate():
print(xx)
Output: D:\Pythons\SO\79317942.py
test’test "Leonard’s iPhone iP15" Profile "Leonard’s iPhone iP15" is not found on the system.