How to access wmi in python? - python

So I am trying to access the data from here
in Python. As you can see, it uses wmi. I have tried to use wmi in python before but I am having trouble interpreting the data they are giving me. Please be patient with me as I am a noob to how wmi works. It says that the wmi data is stored in root/OpenHardwareMontor and that it uses two different wmi classes(Hardware and Sensor). But all this information is going over my head.
could someone please give me some sample code to read some data from this?
For example, the code to check cpu core 1 frequency.
EDIT: i have sort of got it working. i run this code:
for Temperature in c.sensor():
print Temperature.identifier
print Temperature.value
and i get this:
/hdd/0/load/0
37.6608924866
/intelcpu/0/temperature/1
53.0
/intelcpu/0/temperature/0
42.0
/ram/data/1
2.88324356079
/intelcpu/0/load/2
1.53846144676
/hdd/0/temperature/0
43.0
/intelcpu/0/load/0
2.30768918991
/intelcpu/0/clock/1
1463.29663086
/intelcpu/0/clock/0
133.02696228
/intelcpu/0/clock/2
1463.29663086
/ram/load/0
49.224521637
/ram/data/0
2.79517364502
/intelcpu/0/load/1
3.07692289352
how can i request only the value associated with the identifier /intelcpu/0/temperature/1 ignoring all other values?

The most simple example to use WMI:
c = wmi.WMI()
wql = "Select * From Win32_SerialPort"
for item in c.query(wql):
print item
Output Example:
instance of Win32_SerialPort
{
Availability = 2;
Binary = TRUE;
Caption = "SpectrumAnalyzer1 (COM15)";
ConfigManagerErrorCode = 0;
ConfigManagerUserConfig = FALSE;
CreationClassName = "Win32_SerialPort";
Description = "SpectrumAnalyzer1";
DeviceID = "COM15";
MaxBaudRate = 128000;
MaximumInputBufferSize = 0;
MaximumOutputBufferSize = 0;
Name = "SpectrumAnalyzer1 (COM15)";
OSAutoDiscovered = TRUE;
PNPDeviceID = "USB\\VID_10C4&PID_ED00\\1269376";
PowerManagementCapabilities = {1};
PowerManagementSupported = FALSE;
ProviderType = "RS232 Serial Port";
SettableBaudRate = TRUE;
SettableDataBits = TRUE;
SettableFlowControl = TRUE;
SettableParity = TRUE;
SettableParityCheck = TRUE;
SettableRLSD = TRUE;
SettableStopBits = TRUE;
Status = "OK";
StatusInfo = 3;
Supports16BitMode = FALSE;
SupportsDTRDSR = TRUE;
SupportsElapsedTimeouts = TRUE;
SupportsIntTimeouts = TRUE;
SupportsParityCheck = TRUE;
SupportsRLSD = TRUE;
SupportsRTSCTS = TRUE;
SupportsSpecialCharacters = TRUE;
SupportsXOnXOff = TRUE;
SupportsXOnXOffSet = TRUE;
SystemCreationClassName = "Win32_ComputerSystem";
SystemName = ".......";
};
You can access each item by:
myQuery = c.query(wql)
myQuery.Availability
Output:
2
For more information, try the WMI cookbook.
Edit #1:
Using if statements and in you can do what you want.
for Temperature in c.sensor():
if "/intelcpu/0/temperature/1" in Temperature.identifier:
print Temperature.identifier
print Temperature.value

Related

How to do cryptographic signature in Rust to avoid Python call

Why in the bottom section of this code, do I need to use the following pattern:
let a = urlpath.to_string();
let b = nonce.to_string();
let c = ordertype.to_string();
let d = pair.to_string();
let e = price.to_string();
let f = type_.to_string();
let g = volume.to_string();
let h = api_sec.to_string();
let kwargs = vec![("cmd", "account_balance"), ("urlpath", &a), ("nonce", &b), ("ordertype", &c), ("pair", &d), ("price", &e), ("type", &f), ("volume", &g), ("secret", &h)];
If I replace the variable &a in the vec! with &urlpath.to_string() then it fails saying a temporary value is being dropped and it's later used.
But doesn't that expression evaluate to the same thing, regardless if I add the additional let statements? How can I make this more Rust idiomatic?
use std::{time::{SystemTime, UNIX_EPOCH}};
use pyo3::types::IntoPyDict;
fn main() -> PyResult<()> {
let urlpath = "/0/private/Balance";
println!("{}", urlpath);
let api_sec = "<REPLACE>";
println!("{}", api_sec);
let nonce = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis();
println!("{}", nonce);
let ordertype = "limit";
println!("{}", ordertype);
let pair = "XBTUSD";
println!("{}", pair);
let price: i32 = 37500;
println!("{}", price);
let type_ = "buy";
println!("{}", type_);
let volume = 1.25;
println!("{}", volume);
Python::with_gil(|py| {
let fun: Py<PyAny> = PyModule::from_code(
py,
"
import urllib.parse
import hashlib
import hmac
import base64
def get_kraken_signature(*args, **kwargs):
if args != ():
print('called with args', args)
if kwargs != {}:
print('called with kwargs', kwargs)
if args == () and kwargs == {}:
print('called with no arguments')
if kwargs[\"cmd\"] == \"account_balance\":
urlpath = kwargs[\"urlpath\"]
data = {
\"nonce\": kwargs[\"nonce\"],
}
secret = kwargs[\"secret\"]
elif kwargs[\"cmd\"] == \"send_order\":
urlpath = kwargs[\"urlpath\"]
data = {
\"nonce\": kwargs[\"nonce\"],
\"ordertype\": kwargs[\"ordertype\"],
\"pair\": kwargs[\"pair\"],
\"price\": kwargs[\"price\"],
\"type\": kwargs[\"type\"],
\"volume\": kwargs[\"volume\"],
}
secret = kwargs[\"secret\"]
else:
exit(0)
postdata = urllib.parse.urlencode(data)
encoded = (str(data['nonce']) + postdata).encode()
message = urlpath.encode() + hashlib.sha256(encoded).digest()
mac = hmac.new(base64.b64decode(secret), message, hashlib.sha512)
sigdigest = base64.b64encode(mac.digest())
print(\"API-Sign: {}\".format(sigdigest.decode()))
return sigdigest.decode()
",
"",
"",
)?.getattr("get_kraken_signature")?.into();
let a = urlpath.to_string();
let b = nonce.to_string();
let c = ordertype.to_string();
let d = pair.to_string();
let e = price.to_string();
let f = type_.to_string();
let g = volume.to_string();
let h = api_sec.to_string();
let kwargs = vec![("cmd", "account_balance"), ("urlpath", &a), ("nonce", &b), ("ordertype", &c), ("pair", &d), ("price", &e), ("type", &f), ("volume", &g), ("secret", &h)];
let result = fun.call(py, (), Some(kwargs.into_py_dict(py)))?;
println!("{}", result);
Ok(())
})
}
BONUS: Second part of the question, is how can I rewrite the Python portion in idiomatic Rust? I have tried and failed, so would be helpful if any crypto experts can assist.
First Part: (Explanation)
Since a is the owner of the value and you are passing reference using the owner which will remain in scope even after execution but in the case when you directly pass &urlpath.to_string() there isn't any owner and as soon the execution ends the value would be dropped and there will be a dangling reference which is the cause for the message.
Second Part: (Python to rust conversion)
I am not a crypto expert but I tried to convert the same script you provided without the condition part and matched the output in python and rust.
extern crate url;
extern crate base64;
// use std::time::{SystemTime, UNIX_EPOCH};
use url::form_urlencoded;
use sha2::{Sha256, Digest};
extern crate ring;
extern crate data_encoding;
use ring::hmac;
use data_encoding::BASE64;
use std::collections::HashMap;
fn main() {
let urlpath = String::from("/0/private/Balance");
// let nonce = SystemTime::now()
// .duration_since(UNIX_EPOCH)
// .expect("Time went backwards")
// .as_millis();
let nonce: &str = &(1645371362680 as i64).to_string();
let mut data = HashMap::new();
data.insert("nonce", nonce);
let postdata: String = form_urlencoded::Serializer::new(String::new())
.extend_pairs(data.iter())
.finish();
let encoded = format!("{}{}", nonce, postdata);
let message: Vec<u8> = [urlpath.as_bytes(), Sha256::digest(encoded.as_bytes()).as_ref()].concat();
let secret_key = String::from("secret");
let signed_key = hmac::Key::new(hmac::HMAC_SHA512, secret_key.as_bytes());
let signature = hmac::sign(&signed_key, &message);
let b64_encoded_sig = BASE64.encode(signature.as_ref());
println!("Output: {}", b64_encoded_sig);
}
Playground

Python InDesign scripting: Get overflowing textbox from preflight for automatic resizing

Thanks to this great answer I was able to figure out how to run a preflight check for my documents using Python and the InDesign script API. Now I wanted to work on automatically adjusting the text size of the overflowing text boxes, but was unable to figure out how to retrieve a TextBox object from the Preflight object.
I referred to the API specification, but all the properties only seem to yield strings which do not uniquely define the TextBoxes, like in this example:
Errors Found (1):
Text Frame (R=2)
Is there any way to retrieve the violating objects from the Preflight, in order to operate on them later on? I'd be very thankful for additional input on this matter, as I am stuck!
If all you need is to find and to fix the overset errors I'd propose this solution:
Here is the simple Extendscript to fix the text overset error. It decreases the font size in the all overflowed text frames in active document:
var doc = app.activeDocument;
var frames = doc.textFrames.everyItem().getElements();
var f = frames.length
while(f--) {
var frame = frames[f];
if (frame.overflows) resize_font(frame)
}
function resize_font(frame) {
app.scriptPreferences.enableRedraw = false;
while (frame.overflows) {
var texts = frame.parentStory.texts.everyItem().getElements();
var t = texts.length;
while(t--) {
var characters = texts[t].characters.everyItem().getElements();
var c = characters.length;
while (c--) characters[c].pointSize = characters[c].pointSize * .99;
}
}
app.scriptPreferences.enableRedraw = true;
}
You can save it in any folder and run it by the Python script:
import win32com.client
app = win32com.client.Dispatch('InDesign.Application.CS6')
doc = app.Open(r'd:\temp\test.indd')
profile = app.PreflightProfiles.Item('Stackoverflow Profile')
print('Profile name:', profile.name)
process = app.PreflightProcesses.Add(doc, profile)
process.WaitForProcess()
errors = process.processResults
print('Errors:', errors)
if errors[:4] != 'None':
script = r'd:\temp\fix_overset.jsx' # <-- here is the script to fix overset
print('Run script', script)
app.DoScript(script, 1246973031) # run the jsx script
# 1246973031 --> ScriptLanguage.JAVASCRIPT
# https://www.indesignjs.de/extendscriptAPI/indesign-latest/#ScriptLanguage.html
process = app.PreflightProcesses.Add(doc, profile)
process.WaitForProcess()
errors = process.processResults
print('Errors:', errors) # it should print 'None'
if errors[:4] == 'None':
doc.Save()
doc.Close()
input('\nDone... Press <ENTER> to close the window')
Thanks to the exellent answer of Yuri I was able solve my problem, although there are still some shortcomings.
In Python, I load my documents and check if there are any problems detected during the preflight. If so, I move on to adjusting the text frames.
myDoc = app.Open(input_file_path)
profile = app.PreflightProfiles.Item(1)
process = app.PreflightProcesses.Add(myDoc, profile)
process.WaitForProcess()
results = process.processResults
if "None" not in results:
# Fix errors
script = open("data/script.jsx")
app.DoScript(script.read(), 1246973031, variables.resize_array)
process.WaitForProcess()
results = process.processResults
# Check if problems were resolved
if "None" not in results:
info_fail(card.name, "Error while running preflight")
myDoc.Close(1852776480)
return FLAG_PREFLIGHT_FAIL
I load the JavaScript file stored in script.jsx, that consists of several components. I start by extracting the arguments and loading all the pages, since I want to handle them individually. I then collect all text frames on the page in an array.
var doc = app.activeDocument;
var pages = doc.pages;
var resizeGroup = arguments[0];
var condenseGroup = arguments[1];
// Loop over all available pages separately
for (var pageIndex = 0; pageIndex < pages.length; pageIndex++) {
var page = pages[pageIndex];
var pageItems = page.allPageItems;
var textFrames = [];
// Collect all TextFrames in an array
for (var pageItemIndex = 0; pageItemIndex < pageItems.length; pageItemIndex++) {
var candidate = pageItems[pageItemIndex];
if (candidate instanceof TextFrame) {
textFrames.push(candidate);
}
}
What I wanted to achieve was a setting where if one of a group of text frames was overflowing, the text size of all the text frames in this group are adjusted as well. E.g. text frame 1 overflows when set to size 8, no longer when set to size 6. Since text frame 1 is in the same group as text frame 2, both of them will be adjusted to size 6 (assuming the second frame does not overflow at this size).
In order to handle this, I pass an array containing the groups. I now check if the text frame is contained in one of these groups (which is rather tedious, I had to write my own methods since InDesign does not support modern functions like filter() as far as I am concerned...).
// Check if TextFrame overflows, if so add all TextFrames that should be the same size
for (var textFrameIndex = 0; textFrameIndex < textFrames.length; textFrameIndex++) {
var textFrame = textFrames[textFrameIndex];
// If text frame overflows, adjust it and all the frames that are supposed to be of the same size
if (textFrame.overflows) {
var foundResizeGroup = filterArrayWithString(resizeGroup, textFrame.name);
var foundCondenseGroup = filterArrayWithString(condenseGroup, textFrame.name);
var process = false;
var chosenGroup, type;
if (foundResizeGroup.length > 0) {
chosenGroup = foundResizeGroup;
type = "resize";
process = true;
} else if (foundCondenseGroup.length > 0) {
chosenGroup = foundCondenseGroup;
type = "condense";
process = true;
}
if (process) {
var foundFrames = findTextFramesFromNames(textFrames, chosenGroup);
adjustTextFrameGroup(foundFrames, type);
}
}
}
If this is the case, I adjust either the text size or the second axis of the text (which condenses the text for my variable font). This is done using the following functions:
function adjustTextFrameGroup(resizeGroup, type) {
// Check if some overflowing textboxes
if (!someOverflowing(resizeGroup)) {
return;
}
app.scriptPreferences.enableRedraw = false;
while (someOverflowing(resizeGroup)) {
for (var textFrameIndex = 0; textFrameIndex < resizeGroup.length; textFrameIndex++) {
var textFrame = resizeGroup[textFrameIndex];
if (type === "resize") decreaseFontSize(textFrame);
else if (type === "condense") condenseFont(textFrame);
else alert("Unknown operation");
}
}
app.scriptPreferences.enableRedraw = true;
}
function someOverflowing(textFrames) {
for (var textFrameIndex = 0; textFrameIndex < textFrames.length; textFrameIndex++) {
var textFrame = textFrames[textFrameIndex];
if (textFrame.overflows) {
return true;
}
}
return false;
}
function decreaseFontSize(frame) {
var texts = frame.parentStory.texts.everyItem().getElements();
for (var textIndex = 0; textIndex < texts.length; textIndex++) {
var characters = texts[textIndex].characters.everyItem().getElements();
for (var characterIndex = 0; characterIndex < characters.length; characterIndex++) {
characters[characterIndex].pointSize = characters[characterIndex].pointSize - 0.25;
}
}
}
function condenseFont(frame) {
var texts = frame.parentStory.texts.everyItem().getElements();
for (var textIndex = 0; textIndex < texts.length; textIndex++) {
var characters = texts[textIndex].characters.everyItem().getElements();
for (var characterIndex = 0; characterIndex < characters.length; characterIndex++) {
characters[characterIndex].setNthDesignAxis(1, characters[characterIndex].designAxes[1] - 5)
}
}
}
I know that this code can be improved upon (and am open to feedback), for example if a group consists of multiple text frames, the procedure will run for all of them, even though it need only be run once. I was getting pretty frustrated with the old JavaScript, and the impact is negligible. The rest of the functions are also only helper functions, which I'd like to replace with more modern version. Sadly and as already stated, I think that they are simply not available.
Thanks once again to Yuri, who helped me immensely!

How do I access fields in an active Revit schedule via RevitPythonShell/IronPython?

I'm working on an IronPython script for Revit 2016. For starters, I'm trying to access values (as text) in an active Revit schedule, and load them into a variable. This works well enough for non-calculated values.
However, some of my schedule fields are calculated. Here's a sample schedule (all values here are calculated):
Schedule Snippet
The Revit API shows 2 methods, called TableView.GetCalculatedValueName()and TableView.GetCalculatedValueText(), which I'd like to use, but don't seem to work as advertised.
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
schedule = doc.ActiveView
tableData = schedule.GetTableData()
print(tableData)
tableName = schedule.GetCellText(SectionType.Header,0,0)
qty = schedule.GetCalculatedValueText(SectionType.Body,4,1)
calcValName = schedule.GetCalculatedValueName(SectionType.Body,4,1)
print(tableName)
print("Calculated Qty is: " + qty)
print("Calculated Value Name is: " + calcValName)
Running this code (in Revit) produces the following output:
88-06134-01
Calculated Qty is:
Calculated Value Name is:
I'd like to point out that using TableView.GetCellText() actually works on calculated values, but it's the GetCalculatedValueName() that I'd really like to make work here.
I have done the same thing but in c# for Revit 2019. I hope you will understand it.
You can access the values of schedule data without exporting. Firstly, get all the schedules and read the data cell by cell. Secondly, create dictionary and store data in form of key, value pairs. Now you can use the schedule data as you want. I have tried this in Revit 2019.
Here is the implementation.
public void getScheduleData(Document doc)
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
IList<Element> collection = collector.OfClass(typeof(ViewSchedule)).ToElements();
foreach (Element e in collection)
{
ViewSchedule viewSchedule = e as ViewSchedule;
TableData table = viewSchedule.GetTableData();
TableSectionData section = table.GetSectionData(SectionType.Body);
int nRows = section.NumberOfRows;
int nColumns = section.NumberOfColumns;
if (nRows > 1)
{
List<List<string>> scheduleData = new List<List<string>>();
for (int i = 0; i < nRows; i++)
{
List<string> rowData = new List<string>();
for (int j = 0; j < nColumns; j++)
{
rowData.Add(viewSchedule.GetCellText(SectionType.Body, i, j));
}
scheduleData.Add(rowData);
}
List<string> columnData = scheduleData[0];
scheduleData.RemoveAt(0);
DataMapping(columnData, scheduleData);
}
}
}
public static void DataMapping(List<string> keyData, List<List<string>>valueData)
{
List<Dictionary<string, string>> items= new List<Dictionary<string, string>>();
string prompt = "Key/Value";
prompt += Environment.NewLine;
foreach (List<string> list in valueData)
{
for (int key=0, value =0 ; key< keyData.Count && value< list.Count; key++,value++)
{
Dictionary<string, string> newItem = new Dictionary<string, string>();
string k = keyData[key];
string v = list[value];
newItem.Add(k, v);
items.Add(newItem);
}
}
foreach (Dictionary<string, string> item in items)
{
foreach (KeyValuePair<string, string> kvp in item)
{
prompt += "Key: " + kvp.Key + ",Value: " + kvp.Value;
prompt += Environment.NewLine;
}
}
Autodesk.Revit.UI.TaskDialog.Show("Revit", prompt);
}

Searching of strings in a single string in python

In this code, how can I check multiple strings in a single string in single statement?
line = '{ AutoLogin = 0; Captive = 0; Closed = 0; Disabled = 0; LastConnected = "2013-11-27 08:38:10 +0000"; Passpoint = 0; PossiblyHiddenNetwork = 0; SPRoaming = 0; SSID = <534253>; SSIDString = SBS; SecurityType = "WPA/WPA2 Personal"; SystemMode = 1; TemporarilyDisabled = 0; })'
for token in line.split( ';' ):
if 'RecentNetworks' in token:
start = True
if 'LastConnected' in token:
start = True
Try this:
for token in line.split(';'):
start = any(s in token for s in ["RecentNetworks", "LastConnected"])
You can use regular expressions for this:
if re.search(r'RecentNetworks|LastConnected', token):
start = True
I'm not sure if this is faster than the any solution, but I assume it.

Retrieve User Entry IDs from MAPI

I extended the win32comext MAPI with the Interface IExchangeModifyTable to edit ACLs via the MAPI. I can modify existing ACL entries, but I stuck in adding new entries. I need the users entry ID to add it, according this C example
(Example Source from MSDN)
STDMETHODIMP AddUserPermission(
LPSTR szUserAlias,
LPMAPISESSION lpSession,
LPEXCHANGEMODIFYTABLE lpExchModTbl,
ACLRIGHTS frights)
{
HRESULT hr = S_OK;
LPADRBOOK lpAdrBook;
ULONG cbEid;
LPENTRYID lpEid = NULL;
SPropValue prop[2] = {0};
ROWLIST rowList = {0};
char szExName[MAX_PATH];
// Replace with "/o=OrganizationName/ou=SiteName/cn=Recipients/cn="
char* szServerDN = "/o=org/ou=site/cn=Recipients/cn=";
strcpy(szExName, szServerDN);
strcat(szExName, szUserAlias);
// Open the address book.
hr = lpSession->OpenAddressBook(0,
0,
MAPI_ACCESS_MODIFY,
&lpAdrBook );
if ( FAILED( hr ) ) goto cleanup;
// Obtain the entry ID for the recipient.
hr = HrCreateDirEntryIdEx(lpAdrBook,
szExName,
&cbEid,
&lpEid);
if ( FAILED( hr ) ) goto cleanup;
prop[0].ulPropTag = PR_MEMBER_ENTRYID;
prop[0].Value.bin.cb = cbEid;
prop[0].Value.bin.lpb = (BYTE*)lpEid;
prop[1].ulPropTag = PR_MEMBER_RIGHTS;
prop[1].Value.l = frights;
rowList.cEntries = 1;
rowList.aEntries->ulRowFlags = ROW_ADD;
rowList.aEntries->cValues = 2;
rowList.aEntries->rgPropVals = &prop[0];
hr = lpExchModTbl->ModifyTable(0, &rowList);
if(FAILED(hr)) goto cleanup;
printf("Added user permission. \n");
cleanup:
if (lpAdrBook)
lpAdrBook->Release();
return hr;
}
I can open the Address Book, but HrCreateDirEntryIdEx is not provided in the pywin32 mapi. I found it in the exchange extension, which does not compile on my system, the missing library problem. Do you have any idea to retrieve the users entry ID?
Thank.
Patrick
I got this piece of code and it works fine
from binascii import b2a_hex, a2b_hex
import active_directory as ad
# entry_type, see http://msdn.microsoft.com/en-us/library/cc840018.aspx
# + AB_DT_CONTAINER 0x000000100
# + AB_DT_TEMPLATE 0x000000101
# + AB_DT_OOUSER 0x000000102
# + AB_DT_SEARCH 0x000000200
# ab_flags, maybe see here: https://svn.openchange.org/openchange/trunk/libmapi/mapidefs.h
def gen_exchange_entry_id(user_id, ab_flags=0, entry_type = 0):
muidEMSAB = "DCA740C8C042101AB4B908002B2FE182"
version = 1
# Find user and bail out if it's not there
ad_obj = ad.find_user(user_id)
if not ad_obj:
return None
return "%08X%s%08X%08X%s00" % (
ab_flags,
muidEMSAB,
version,
entry_type,
b2a_hex(ad_obj.legacyExchangeDN.upper()).upper(),
)
data = gen_exchange_entry_id("myusername")
print data
print len(a2b_hex(data))

Categories