0

I am trying to set my IP address to a specific one on a LAN Network.

To do this i have tried using the following:

import subprocess
command='netsh interface ipv4 set address name="Local Area Connection* 4" source=static address=192.168.173.234 mask=255.255.255.0 gateway=192.168.0.1'
subprocess.call(["cmd.exe", command])

The only thing this results in is the starting up of an empty cmd.exe that isn't doing anything.

Also, what for would the shell=True be used ? When I try to use it, python returns a SyntaxError

UPDATE: If I use:

command='netsh interface ipv4 set address name="Local Area Connection* 4" source=static address=192.168.173.222 mask=255.255.255.0 gateway=192.168.0.1'
subprocess.check_call(["netsh.exe", command])

Python Returns the error:

Traceback (most recent call last):
  File "D:file path", line 8, in <module>
    subprocess.check_call(["netsh.exe", netsh_cmd])
  File "C:\Python27\lib\subprocess.py", line 540, in check_call
    raise CalledProcessError(retcode, cmd)
CalledProcessError: Command '['netsh.exe', 'netsh interface ipv4 set address name="Local Area Connection* 4" source=static address=192.168.173.222 mask=255.255.255.0 gateway=192.168.0.1']' returned non-zero exit status 1
Mario Geuenich
  • 294
  • 1
  • 7
  • 17
  • are you on Windows? Why do you use single quotes? Does it work if you copy-paste the command *as is* into Windows console that runs `cmd.exe` (not Powershell)? How is `netsh` implemented -- is where `netsh.exe`? or is it an internal cmd.exe command (unlikely)? – jfs Feb 15 '15 at 22:09
  • @J.F. Sebastian, I'm on Windows 8.1, changed the single quotes(wasn't aware it didn't work in cmd that way). Yes it does work if i type exactly what I stated here into the cmd.exe(has to be run as admin)/Power Shell(also admin). netsh.exe is in C:/Windows/System32/. – Mario Geuenich Feb 16 '15 at 10:35
  • have you tried to run the suggested Python code as admin (for debugging)? `call(command)` or `call(command, shell=True)` – jfs Feb 16 '15 at 11:12
  • @J.F. Sebastian How do you run python code as admin ? With `'/user:Administrator'` – Mario Geuenich Feb 16 '15 at 12:35
  • run it (for debugging) in exactly the same way as you run netsh command that succeeds (open admin console and run Python script there. If it works; you could look for a proper way to escalate privileges). About the last error: Do not split netsh from the rest of the command. Pass the command as a single string exactly as you see it on the command line as my answer suggests. – jfs Feb 16 '15 at 12:52
  • @J.F. Sebastian, I popened admin cmd and ran the python script, this time with added print statements as a token. The output was just the print statements, but nothing else changed. – Mario Geuenich Feb 16 '15 at 13:25
  • my answer shows `subprocess.check_call(command)`. Why do you use `subprocess.check_call(["netsh.exe", command])` instead? – jfs Feb 17 '15 at 03:11

3 Answers3

0

If you use a string of args you need shell=True:

import subprocess
command="netsh interface ipv4 set address name='Local Area Connection* 4' source=static address=192.168.173.234 mask=255.255.255.0 gateway=192.168.0.1"
subprocess.call(command,shell=True)

You can do it without shell=True which I would recommend by passing a list of args:

import subprocess
command = ['netsh', 'interface', 'ipv4', 'set', 'address', 'name=Local Area Connection* 4', 'source=static', 'address=192.168.173.234', 'mask=255.255.255.0', 'gateway=192.168.0.1']


subprocess.call( command)

Or let shlex.split split the args for you:

import shlex

subprocess.call(shlex.split(command))

using check_call in place of call may also be preferable as call will not raise an error if there is a non-zero exit status where check_call will.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • @Mario. So what exactly happens? – Padraic Cunningham Feb 15 '15 at 18:13
  • Now that i have tried using check_call python returns a CalledProcessError: Command '['netsh', ...]' returned non-zero exit status 1 – Mario Geuenich Feb 15 '15 at 18:17
  • Yes, it works fine, but only as long as there is another computer connected to the network I have created on the machine that is trying to set a specific IP. – Mario Geuenich Feb 15 '15 at 18:35
  • and you run it exactly as posted from the cmd prompt? – Padraic Cunningham Feb 15 '15 at 18:36
  • it seems OP is on Windows. Unless `netsh` is an internal cmd.exe command (unlikely); you don't need `shell=True`. [Single quotes are used by `cmd.exe` only in specific cases](http://stackoverflow.com/q/24173825/4279). It seems if they are not erronious here then they should be preserved and passed to `netsh` as is and therefore `shlex.split()` should not be used here. – jfs Feb 15 '15 at 22:15
  • 1
    @J.F.Sebastian, I originally used the command as is, you can see it in the first example and the OP said it did not work . Would shell=True make it fail? – Padraic Cunningham Feb 15 '15 at 22:43
  • 1
    @PadraicCunningham: It shouldn't in this case unless there is some other conflicting `netsh` program ([different rules for searching the executable](http://stackoverflow.com/a/25167402/4279)). The escaping rules ([what is considered a metacharacter](http://stackoverflow.com/a/27867015/4279)) are also different but it shouldn't mattter for the given command. [The exit code](http://stackoverflow.com/q/27842166/4279) might be converted to its two's complement negative value. – jfs Feb 15 '15 at 23:18
0

If there is netsh.exe somewhere in the search path (assuming you are on Windows) then you could pass the command string as is:

import subprocess

subprocess.check_call(command)
Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
0

I will explain several things:

import subprocess
command='netsh interface ipv4 set address name="Local Area Connection* 4" source=static address=192.168.173.234 mask=255.255.255.0 gateway=192.168.0.1'
subprocess.call(["cmd.exe", command])

When you "call" cmd.exe or "netsh.exe", you are telling the module to open a CMD and run "cmd.exe" or "netsh.exe"

Whenever you need to do something with the system terminal just enter the arguments. If you need to run a program in that case you need to tell it the path and name of the .EXE.

If you are using a version lower than Python 3.5 then you can do this:

import subprocess
cmd='netsh interface ipv4 set address name="Ethernet 4" source=static address=192.168.173.234 mask=255.255.255.0 gateway=192.168.0.1'
sp = subprocess.call(cmd, shell=True)

This will work, however you don't know exactly what was executed in the terminal. Name "cmd" to the arguments, it is correct because the module will execute the cmd with those arguments but it can be any other name.

If you are using a version equal to or greater than Python 3.5 you can do this:

import subprocess
cmd='netsh interface ipv4 set address name="Ethernet 4" source=static address=192.168.173.234 mask=255.255.255.0 gateway=192.168.0.1'
sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
sp_string = sp.args
print('Command input in CMD is:',sp_string)
stdout, stderr = sp.communicate()
print('The CMD output is:',stdout)

The difference is that we change "call" to "Popen", this module allows us to know what string of characters or arguments were sent to the shell, it also allows us to know the response that the module gives and if there was an error or not. Call is not compatible with ".args".

Since "netsh" only returns a newline in response, you can omit the stdout and stderr from the code:

import subprocess
cmd='netsh interface ipv4 set address name="Local Area Connection* 4" source=static address=192.168.173.234 mask=255.255.255.0 gateway=192.168.0.1'
sp = subprocess.Popen(cmd, shell=True)
sp_string = sp.args
print('Command input in CMD is:',sp_string)

In the image below you can see the command that was entered in the CMD and the response of the netsh line break. In Visual Studio Code the CMD runs silently for me.

Command input in CMD