Get battery status using wmi in python? - python

I know how to use wmi, I have used it before, however, the wmi class it seems i need to call is GetSystemPowerStatus. but i am having trouble finding and documentation on it. to be able to access it, i need to know the namespace, and the format of the data inside the class. could someone help me? Also some sample code would be nice.

Using ctypes, you can call win32 api:
from ctypes import *
class PowerClass(Structure):
_fields_ = [('ACLineStatus', c_byte),
('BatteryFlag', c_byte),
('BatteryLifePercent', c_byte),
('Reserved1',c_byte),
('BatteryLifeTime',c_ulong),
('BatteryFullLifeTime',c_ulong)]
powerclass = PowerClass()
result = windll.kernel32.GetSystemPowerStatus(byref(powerclass))
print(powerclass.BatteryLifePercent)
Above code comes from here.
Using Win32_Battery class (You need to install pywin32):
from win32com.client import GetObject
WMI = GetObject('winmgmts:')
for battery in WMI.InstancesOf('Win32_Battery'):
print(battery.EstimatedChargeRemaining)
Alternative that use wmi package:
import wmi
w = wmi.WMI()
for battery in w.query('select * from Win32_Battery'):
print battery.EstimatedChargeRemaining

```
import subprocess
wmic = subprocess.getoutput("wmic path win32_battery get EstimatedChargeRemaining")
print(wmic)
```
output:
EstimatedChargeRemaining
96

Related

Python 3: import dll with ctypes or numpy.ctypeslib

I want to work with the APIs of the program of structural analysis (civil engineering) Autodesk Robot Structural Analysis.
With IronPython I initialize the variables as follows:
import clr
clr.AddReferenceToFileAndPath(‘mypfad\Interop.RobotOM.dll’)
from RobotOM import *
robapp = RobotApplicationClass()
robproj = robapp.Project
robstruct = robproj.Structure
With robstruct I can call the API functions and continue working.
Now I’d like to do the same with Python 3. I have tried with ctypes and with numpy.ctypeslib without success:
import ctypes
lib_ctypes = ctypes.cdll[‘mypfad\Interop.RobotOM.dll']
print(lib_ctypes)
<CDLL 'mypfad \Interop.RobotOM.dll', handle 1a1ff900000 at 0x1a1e8e22710>
import numpy
lib_numpy = numpy.ctypeslib.load_library('Interop.RobotOM.dll', 'mypfad’)
print(lib_ numpy)
<CDLL 'mypfad\Interop.RobotOM.dll', handle 1a1ffb40000 at 0x1a1ffb194e0>
And I don’t how to continue.
My questions are: is this the right way and how shall I continue?
Edited 05.10.2018
Original code with IronPython:
import clr
# Add Robot Structural Analysis API reference
clr.AddReferenceToFileAndPath(
'C:\Program Files\Common Files\Autodesk Shared\Extensions 2018\Framework\Interop\Interop.RobotOM.dll'
)
# Add needed import to be able to use Robot Structural Analysis objects
from RobotOM import *
# Connect to the running instance of Robot Structural Analysis
robapp = RobotApplicationClass()
# Get a reference of the current project
robproj = robapp.Project
# Get a reference of the current model
robstruct = robproj.Structure
An attempt according to the comment of The Machine:
import ctypes
my_dll = ctypes.cdll.LoadLibrary(
'C:\Program Files\Common Files\Autodesk Shared\Extensions 2018\Framework\Interop\Interop.RobotOM.dll'
)
robapp = my_dll.RobotApplicationClass()
robproj = robapp.Project
robstruct = robproj.Structure
Result:
AttributeError: function 'RobotApplicationClass' not found
Edited 16.10.2018
Third attempt:
from ctypes import cdll
my_dll = cdll.LoadLibrary(
'C:\Program Files\Common Files\Autodesk Shared\Extensions 2019\Framework\Interop\Interop.RobotOM.dll'
)
my_dll.RobotApplicationClass()
Result:
AttributeError: function 'RobotApplicationClass' not found
Try this:
from ctypes import*
your_dll = cdll.LoadLibrary(‘mypfad\Interop.RobotOM.dll ')
If it is succesfully loaded than you can aces to all of classes and function in that dll file . You can call theme with your_dll.nameofclass .

What is the path of the loaded dll?

I am loading a dll with ctypes under Cygwin with the following:
import ctypes
ctypes.cdll.LoadLibrary('foo.dll')
How can I get the absolute path of my dll?
The problem is that I have absolutely no clues where the dll is located. Can I relate on the following to get this information?
subprocess.Popen(["which", lib], stdout=subprocess.PIPE).stdout.read().strip()
In Unix, the path of a loaded shared library can be determined by calling dladdr with the address of a symbol in the library, such as a function.
Example:
import ctypes
import ctypes.util
libdl = ctypes.CDLL(ctypes.util.find_library('dl'))
class Dl_info(ctypes.Structure):
_fields_ = (('dli_fname', ctypes.c_char_p),
('dli_fbase', ctypes.c_void_p),
('dli_sname', ctypes.c_char_p),
('dli_saddr', ctypes.c_void_p))
libdl.dladdr.argtypes = (ctypes.c_void_p, ctypes.POINTER(Dl_info))
if __name__ == '__main__':
import sys
info = Dl_info()
result = libdl.dladdr(libdl.dladdr, ctypes.byref(info))
if result and info.dli_fname:
libdl_path = info.dli_fname.decode(sys.getfilesystemencoding())
else:
libdl_path = u'Not Found'
print(u'libdl path: %s' % libdl_path)
Output:
libdl path: /lib/x86_64-linux-gnu/libdl.so.2
If you are on Windows and do not need a programmatical solution for instance if you are debugging something, you can use Process Explorer to look which DLLs python.exe has loaded.

Get all available printers in OS X using Python

Currently I am doing some tests with printers in Python, what I am trying to do is to list all the printers available.
Right now I am using PyCups library which exposes several useful APIs in the Connection class. Among these there's also getPrinters():
Here's a snippet that I use and works:
>>> import cups
>>> conn = cups.Connection ()
>>> printers = conn.getPrinters ()
>>> for printer in printers:
... print printer, printers[printer]["device-uri"]
Brother_MFC_1910W_series
Photosmart_6520_series
I was wondering if there's any method to write the above code without using any external library. I am quite sure this can't be done without using C.
Any suggestion or reference to docs would be very appreciated. Thanks
I am using Python 3
It is possible to use C libraries from Python with standard modules only. References: CUPS API, ctypes. Translating CUPS structures and calls into ctypes syntax, we get a code that works under both standard OS X Python and Python 3:
from __future__ import print_function
from ctypes import *
class cups_option_t(Structure):
_fields_ = [
('name', c_char_p),
('value', c_char_p)
]
class cups_dest_t(Structure):
_fields_ = [
('name', c_char_p),
('instance', c_char_p),
('is_default', c_int),
('num_options', c_int),
('cups_option_t', POINTER(cups_option_t))
]
cups_lib = cdll.LoadLibrary('/usr/lib/libcups.dylib')
if __name__ == '__main__':
dests = cups_dest_t()
dests_p = pointer(dests)
num_dests = cups_lib.cupsGetDests(byref(dests_p))
for i in range(num_dests):
dest = dests_p[i]
print(dest.is_default, dest.name)
for j in range(dest.num_options):
option = dest.cups_option_t[j]
print('', option.name, option.value, sep='\t')
cups_lib.cupsFreeDests(num_dests, dests_p)
Be especially careful when using ctypes, most of errors would produce a segmentation fault.
You can perform a similar query using the terminal command lpstat (man for OSX). Python's builtin subprocess module would allow you to run that command and store the output. Some text parsing should provide the printer name.
from subprocess import Popen, PIPE
# "lpstat -a" prints info on printers that can accept print requests
p = Popen(['lpstat', '-a'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, errors = p.communicate()
lines = output.split('\n')
# check before you implement this parsing
printers = map(lambda x: x.split(' ')[0], lines)

Start multiprocessing.process in namespace

I'm trying to start a new process from within an already created namespace (named 'test').
I've looked into a few methods including nsenter:
import subprocess
from nsenter import Namespace
with Namespace(mypid, 'net'):
# output network interfaces as seen from within the mypid's net NS:
subprocess.check_output(['ip', 'a'])
But I cant seem to find a reference of where to find the var, mypid...!
Ideally I'd like to keep dependancies like nsenter to a minimum (for portability) so i'd probably like to go down the ctypes route, something like (although there is no syscall for netns...):
nsname = 'test'
netnspath = '%s%s' % ('/run/netns/', nsname)
netnspath = netnspath.encode('ascii')
libc = ctypes.CDLL('libc.so.6')
printdir(libc)
fd = open(netnspath)
print libc.syscall(???, fd.fileno())
OR (taken from http://tech.zalando.com/posts/entering-kernel-namespaces-with-python.html)
import ctypes
libc = ctypes.CDLL('libc.so.6')
# replace MYPID with the container's PID
fd = open('/proc/<MYPID>/ns/net')
libc.setns(fd.fileno(), 0)
# we are now inside MYPID's network namespace
However, I still have to know the PID, plus my libc does not have setns!
Any thoughts on how I could obtain the PID would be great!
TIA!
The problem with the nsenter module is that you need to provide it with the PID of a process that is already running inside your target namespace. This means that you can't actually use this module to make use of a network namespace that you have created using something like ip netns add.
The kernel's setns() system call takes a file descriptor rather than a PID. If you're willing to solve it with ctypes, you can do something like this:
from ctypes import cdll
libc = cdll.LoadLibrary('libc.so.6')
_setns = libc.setns
CLONE_NEWIPC = 0x08000000
CLONE_NEWNET = 0x40000000
CLONE_NEWUTS = 0x04000000
def setns(fd, nstype):
if hasattr(fd, 'fileno'):
fd = fd.fileno()
_setns(fd, nstype)
def get_netns_path(nspath=None, nsname=None, nspid=None):
'''Generate a filesystem path from a namespace name or pid,
and return a filesystem path to the appropriate file. Returns
the nspath argument if both nsname and nspid are None.'''
if nsname:
nspath = '/var/run/netns/%s' % nsname
elif nspid:
nspath = '/proc/%d/ns/net' % nspid
return nspath
If your libc doesn't have the setns() call, you may be out of luck
(although where are you running that you have a kernel recent enough
to support network namespaces but a libc that doesn't?).
Assuming you have a namespace named "blue" available (ip netns add
blue) you can run:
with open(get_netns_path(nsname="blue")) as fd:
setns(fd, CLONE_NEWNET)
subprocess.check_call(['ip', 'a'])
Note that you must run this code as root.
This works, however I'm unsure at what the 0 does as part of the syscall. So if someone could enlighten me that would be great!
import ctypes
nsname = 'test'
netnspath = '%s%s' % ('/run/netns/', nsname)
netnspath = netnspath.encode('ascii')
libc = ctypes.CDLL('libc.so.6')
fd = open(netnspath)
print libc.syscall(308, fd.fileno(), 0)
After finding this question we've updated python-nsenter so it is now able to enter namespaces via an arbitrary path in addition to providing the pid.
For example if you wanted to enter a namespace created by ip netns add you can now do something like:
with Namespace('/var/run/netns/foo', 'net'):
# do something in the namespace
pass
Version 0.2 is now available via PyPi with this update.

How to create Excel or Windows Msg Box using COM in Python?

Is there a way to get pywin32 to generate a VBA-style MsgBox in Excel, if not, perhaps the Windows equivalent?
I tried:
from win32com.client import Dispatch
excel = Dispatch('Excel.Application')
excel.MsgBox('foo')
but it gives the error below:
AttributeError: Excel.Application.MsgBox
Hi you can use win32api:
import win32api
from win32con import MB_SYSTEMMODAL
response = win32api.MessageBox(0, "Did you hear the Buzzer?", "Buzzer Test", 4, MB_SYSTEMMODAL)
MB_SYSTEMMODAL is used for telling the system to show a message above all other applications.

Categories