Set string systemvaribale in CANoe from python - python

I am trying to set a system varibale in CANoe from python over COM.
I have managed to set a integer system varibale from python like this
When setting the integer system varibale I am doing this ( which works)
self.Application = win32com.client.dynamic.Dispatch("CANoe.Application")
Ver = self.Application.Version
self.Namespaces = self.Application.System.Namespaces
self.Namespace = self.Namespaces('BOT')
Machine = self.Namespace.Variables('Machine')
Machine.value = 8
But if the system varibale in CANoe is a string (in CANoe)
Machine = self.Namespace.Variables('Machine')
Machine.value = getText() // will return "8"
My python script just crash
File "C:\Python39\lib\site-packages\win32com\client\dynamic.py", line 707, in __setattr__
raise AttributeError(
AttributeError: Property '<unknown>.value' can not be set.
How can i set the string system varibale from python over COM to CANoe?
Edit;
I solved it.
The Machine.value needs to be set like this
Machine = self.Namespace.Variables('Machine')
var = getText() // will return "8"
Machine.value = var
For some reason i need to save the value in a variable before setting the system varibale

Related

How to wait for a variable change when using Pyads library?

I am working on a project with TwinCat and AMR. I'm using Python as a communication medium between the two systems. I have an issue with waiting for the variable to change value. I have a variable of type BOOL and want to perform a certain action when the variable changes. Can someone help me with this?
P.S. I have notified for change in variable as well.
import pyads
PLC = pyads.Connection('127.0.0.1.1.1', pyads.PORT_SPS1)
PLC.open()
StnF = PLC.read_by_name('GVL.AGVgotoStnF', pyads.PLCTYPE_BOOL)
print(StnF)
if StnF == 'TRUE' :
ArrStnF = PLC.write_by_name('GVL.iPosAGV',3,pyads.PLCTYPE_INT)
print(ArrStnF)
Your looking for notifications. The documentation of pyads gives and example how to do this:
import pyads
from ctypes import sizeof
# define the callback which extracts the value of the variable
def callback(notification, data):
contents = notification.contents
var = next(map(int, bytearray(contents.data)[0:contents.cbSampleSize]))
plc = pyads.Connection('127.0.0.1.1.1', pyads.PORT_SPS1)
plc.open()
attr = pyads.NotificationAttrib(sizeof(pyads.PLCTYPE_INT))
# add_device_notification returns a tuple of notification_handle and
# user_handle which we just store in handles
handles = plc.add_device_notification('GVL.integer_value', attr, callback)
# To remove the device notification just use the del_device_notication
# function.
plc.del_device_notification(*handles)

Release Installer Object after using comtypes.client.CreateObject()

I wrote a function in python using the comtypes.client module, the function should supposedly open the database from a .msi file and write a special (key, value) pair. My issue so far is once the function is called with no problems, I try to use os.rename() to rename the .msi file afterwards and get a permission error:
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process
what I understand is that my COM object is still in use and so I cannot access the file, The function and function calls look like (obviously this is very simplified but should look work as such):
import comtypes.client
import os, shutil
def setInstallerAttribute(installer_path, attribute_key, attribute_value):
installerCOM = comtypes.client.CreateObject("WindowsInstaller.Installer")
installerDatabase = installerCOM.OpenDatabase (installer_path, 1)
view = installerDatabase.OpenView ("INSERT INTO Property (Property, Value) VALUES ('{0}', '{1}')".format(attribute_key, attribute_value))
view.Execute
installerDatabase.Commit
view = None
installerDatabase = None
installerCOM = None
if __name__ == "__main__":
input = '{}'.format(msi_fullapth)
key = "Build"
value = "test_value"
if os.path.exists(input):
setInstallerAttribute(input, key, value)
os.rename(input, {some other path})
The function is written because previously I was using a VBScript to set this (key, value) pair:
Option Explicit
Dim installer, database, view, myproperty, stdout, key
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (WScript.Arguments.Item(0), 1)
' Update Property'
'Set view = database.OpenView ("UPDATE Property SET Value = '" & myproperty & "' WHERE Property = 'MYPROPERTY'")'
myproperty = WScript.Arguments.Item(2)
key = WScript.Arguments.Item(1)
' Add/Insert Property'
Set view = database.OpenView ("INSERT INTO Property (Property, Value) VALUES ('" & key & "', '" & myproperty & "')")
view.Execute
database.Commit
Set database = Nothing
Set installer = Nothing
Set view = Nothing
I would call this in my python code with os.system(cscript {VBScript} {path} {Key} {Value}), however I want minimal external dependencies as possible with my python code. I was looking around for some answers, I looked into the comtypes documentation to see if I can explicitly release or "uncouple" my COM object. I tried using installerCOM.Quit() and installerCOM.Exit() which seem not be options for WindowsInstaller.Installer Objects.
Finally, I read in several previous non-python (C# mainly) answers on StackOverflow stating that setting the COM object variables to null would solve this, this is also clear from the VBScript but this does not seem to work in python with None
Maybe:
import gc
def setInstallerAttribute(installer_path, attribute_key, attribute_value):
installerCOM = comtypes.client.CreateObject("WindowsInstaller.Installer")
installerDatabase = installerCOM.OpenDatabase (installer_path, 1)
view = installerDatabase.OpenView ("INSERT INTO Property (Property, Value) VALUES ('{0}', '{1}')".format(attribute_key, attribute_value))
view.Execute
installerDatabase.Commit
del view
del installerDatabase
del installerCOM
gc.collect()

Running VBScript inside Python : Error Microsoft VBScript runtime error: ActiveX component can't create object

Well I am calling a VBScript inside a python code. I get error "ActiveX component can't create object"
But it is fine When I call Seperate (When I double click that or run using cmd).
This is part of python code. I tried csript, wscript. changed the path to system32 / SYSVOW64.. But nothing is working
for i in range(printInput):
print("range")
print(i)
os.system(r"C:\Windows\system32\cmd.exe /k c:\windows\SysWOW64\cscript.exe C:\Users\muneeb.kalathil\PycharmProjects\moodledownload\vcconverter\labelprint\new.vbs")
#subprocess.call("run.bat")
And this is VBSscript
'<SCRIPT LANGUAGE="VBScript">
' Data Folder
Const sDataFolder = "C:\Users\muneeb.kalathil\PycharmProjects\moodledownload\vcconverter\labelprint\"
DoPrint(sDataFolder & "label.lbx")
'*******************************************************************
' Print Module
'*******************************************************************
Sub DoPrint(strFilePath)
Set ObjDoc = CreateObject("bpac.Document")
bRet = ObjDoc.Open(strFilePath)
If (bRet <> False) Then
ObjDoc.GetObject("AssetName").Text = "text"
ObjDoc.GetObject("AssetTag").Text = "text"
ObjDoc.GetObject("company").Text = "text"
Call ObjDoc.SetBarcodeData(ObjDoc.GetBarcodeIndex("QR"), "link")
' ObjDoc.SetMediaByName ObjDoc.Printer.GetMediaName(), True
ObjDoc.StartPrint "", 0
ObjDoc.PrintOut 1, 0
ObjDoc.EndPrint
ObjDoc.Close
End If
Set ObjDoc = Nothing
End Sub
It shows the error in
Set ObjDoc = CreateObject("bpac.Document")
So after lot of tries, I converted vbscript to exe file and then executed. Now it is working.
os.system("run.exe")
I have used this software as some converters are not really converting to exe. This software has some limitations. But works well for me.
https://www.battoexeconverter.com/

How can I resolve an error in Targetpath?

I am developing a small script that creates a chrome shortcut.
I want to have Facebook as homepage when this shortcut is used so I thought I could just append "www.facebook.com" to the target variable that is fed to shortcut.Targetpath, but I get an error. Here is my code snippet
desktop = winshell.desktop()
path = os.path.join(desktop, "Chrome.lnk")
target = r'C:\Program Files\Google\Chrome\Application\chrome.exe ' '"www.facebook.com'
wDir = r"%ProgramFiles%\Google\Chrome\Application"
icon = r"%ProgramFiles%\Google\Chrome\Application\chrome.exe"
shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(path)
shortcut.Targetpath = target
shortcut.WorkingDirectory = wDir
shortcut.IconLocation = icon
shortcut.save()
and the IDE shows the following error:
File "C:\Python34\lib\site-packages\win32com\client\dynamic.py", line 581, in __setattr__
raise AttributeError("Property '%s.%s' can not be set." % (self._username_, attr))
AttributeError: Property '<unknown>.Targetpath' can not be set.
How can I fix that?
First of all, Targetpath should contain an executable path, you shouldn't add the default homepage to that variable.
To have Chrome open a default webpage you should use the shortcut.Arguments which is what you're actually missing and you should fix shortcut.TargetPath.
So you should modify your code along the following lines:
target = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
arguments = r'https://www.facebook.com'
and then
shortcut.Targetpath = target
shortcut.Arguments = arguments
In my answer, I assume all the rest is correct. Maybe you will need to modify a bit target and wDir.

Changes not written to file correctly in Python 2.7

For a few days now, I have been struggling with a problem, namely that the settings written by my settings class for a parser are not persistent when the program gets restarted. This problem occurs only on Windows, but in both Python x86 and x64 environments and when compiled using PyInstaller. It also does not matter whether the program is run as Administrator or not.
When the program first runs, write_def(self) is called by the constructor. This function writers teh defaults correctly to the file specified. After this, read_set(self) is called so the class variables are set.These class variables then do match the default values.
In another file, namely frames.py, write_set(self) is called, and all settings are passed as arguments. Using print statements I have asserted that the write_set(self) function receives the correct values. No errors occur when writing the settings to the file, and when running read_set(self) again, the new settings are read correctly and this is also shown in the GUI.
However, when closing the program and running it again, the default settings are again shown. This is not behaviour I expected.
Below I have added the settings class implementing a cPickle. When using pickle the behaviour is the same. When using shelve as in this file, the behaviour is the same. When using dill, the behaviour is the same. When implementing a ConfigParser.RawConfigParser (in the configparser branch of the GitHub repository linked to earlier), the behaviour is the same, and additionally when viewing the settings file in a text editor it is visible that the settings in the file are not updated.
When running the same code on Linux (Ubuntu 16.04.1 LTS with Python 2.7), everything works as expected with pickle and shelve versions. The settings are correctly saved and loaded from the file. Am I doing something wrong? Is it a Windows-specific issue with Python?
Thank you in advance for any help!
RedFantom.
# Written by RedFantom, Wing Commander of Thranta Squadron and Daethyra, Squadron Leader of Thranta Squadron
# Thranta Squadron GSF CombatLog Parser, Copyright (C) 2016 by RedFantom and Daethyra
# For license see LICENSE
# UI imports
import tkMessageBox
# General imports
import getpass
import os
import cPickle
# Own modules
import vars
# Class with default settings for in the settings file
class defaults:
# Version to display in settings tab
version = "2.0.0_alpha"
# Path to get the CombatLogs from
cl_path = 'C:/Users/' + getpass.getuser() + "/Documents/Star Wars - The Old Republic/CombatLogs"
# Automatically send and retrieve names and hashes of ID numbers from the remote server
auto_ident = str(False)
# Address and port of the remote server
server = ("thrantasquadron.tk", 83)
# Automatically upload CombatLogs as they are parsed to the remote server
auto_upl = str(False)
# Enable the overlay
overlay = str(True)
# Set the overlay opacity, or transparency
opacity = str(1.0)
# Set the overlay size
size = "big"
# Set the corner the overlay will be displayed in
pos = "TL"
# Set the defaults style
style = "plastik"
# Class that loads, stores and saves settings
class settings:
# Set the file_name for use by other functions
def __init__(self, file_name = "settings.ini"):
self.file_name = file_name
# Set the install path in the vars module
vars.install_path = os.getcwd()
# Check for the existence of the specified settings_file
if self.file_name not in os.listdir(vars.install_path):
print "[DEBUG] Settings file could not be found. Creating a new file with default settings"
self.write_def()
self.read_set()
else:
try:
self.read_set()
except:
tkMessageBox.showerror("Error", "Settings file available, but it could not be read. Writing defaults.")
self.write_def()
vars.path = self.cl_path
# Read the settings from a file containing a pickle and store them as class variables
def read_set(self):
with open(self.file_name, "r") as settings_file_object:
settings_dict = cPickle.load(settings_file_object)
self.version = settings_dict["version"]
self.cl_path = settings_dict["cl_path"]
self.auto_ident = settings_dict["auto_ident"]
self.server = settings_dict["server"]
self.auto_upl = settings_dict["auto_upl"]
self.overlay = settings_dict["overlay"]
self.opacity = settings_dict["opacity"]
self.size = settings_dict["size"]
self.pos = settings_dict["pos"]
self.style = settings_dict["style"]
# Write the defaults settings found in the class defaults to a pickle in a file
def write_def(self):
settings_dict = {"version":defaults.version,
"cl_path":defaults.cl_path,
"auto_ident":bool(defaults.auto_ident),
"server":defaults.server,
"auto_upl":bool(defaults.auto_upl),
"overlay":bool(defaults.overlay),
"opacity":float(defaults.opacity),
"size":defaults.size,
"pos":defaults.pos,
"style":defaults.style
}
with open(self.file_name, "w") as settings_file:
cPickle.dump(settings_dict, settings_file)
# Write the settings passed as arguments to a pickle in a file
# Setting defaults to default if not specified, so all settings are always written
def write_set(self, version=defaults.version, cl_path=defaults.cl_path,
auto_ident=defaults.auto_ident, server=defaults.server,
auto_upl=defaults.auto_upl, overlay=defaults.overlay,
opacity=defaults.opacity, size=defaults.size, pos=defaults.pos,
style=defaults.style):
settings_dict = {"version":version,
"cl_path":cl_path,
"auto_ident":bool(auto_ident),
"server":server,
"auto_upl":bool(auto_upl),
"overlay":bool(overlay),
"opacity":float(opacity),
"size":str(size),
"pos":pos,
"style":style
}
with open(self.file_name, "w") as settings_file_object:
cPickle.dump(settings_dict, settings_file_object)
self.read_set()
Sometimes it takes a while to get to an answer, and I just thought of this: What doesn't happen on Linux that does happen on Windows? The answer to that question is: Changing the directory to the directory of the files being parsed. And then it becomes obvious: the settings are stored correctly, but the folder where the settings file is created is changed during the program, so the settings don't get written to the original settings file, but a new settings file is created in another location.

Categories