Hi guys,
I just started getting into EG scripting/Python and have come across a few hurdles I was hoping you guys could help me out with.
First my pet project if anyone is interested. I thought it would be neat to be able to receive status updates from the computers on my network. ie. I WOL a computer so I can VNC into it, instead of guessing when to connect I now get an online notice from that computer. So I've been hacking the NetworkSender to fit my needs. Let me know if anyone would be interested in this and I'll post it when it's not all hard coded.
Features so far:
- Polls a list of computers for NetworkReceiver, keeps a list of active computers
- Sends out startup, shutdown and crash recovery notices to active computers on the network
- Polls the router to check for network connectivity (so I can time the startup notice)
- displays MIA message if a poll fails without receiving a shutdown notice from that computer
On to the questions:
1. Is there a way to dynamically set eg.globals variables? ie. globals()['test'] but for eg.globals... eg.globals() gives a "TypeError: 'Bunch' object is not callable"
2. Is there a EG exit or system.shutdown event?
3. Is there a way for a plugin to hook into events? Or can you only assign them via EG?
4. I'm syncing my EG configurations/plugins across my network, is there any call I can make to reload the configuration/plugins or restart EG?
Thanks for any help
computer status plugin, eg.globals and more
Re: computer status plugin, eg.globals and more
It sounds like you are working on some cool stuff, I'd like to see the code when you're done.
As for the questions....
In the PyCrust Shell, you can look for particular variables as eg.globals.eg.<whatever> to see what is listed.
I think that answers the question you asked. But before you start changing globals - which could easily impact other's code - make sure that's what you really need. You can easily create and store your own variables within your plugin object and access the globals as read only, so there are other options.
Good luck,
Brett
As for the questions....
When you have EG running, you should try running help->Python Shell. That runs a shell that can access EG's variables and see live changes. Very helpful if you want to figure out what EG is doing.... I pulled up a shell and typed eg.globals, and it said it was an object of type eg.Utils.Bunch. That class is in EventGhost\Event\eg\Utils.py, with these comments:1. Is there a way to dynamically set eg.globals variables? ie. globals()['test'] but for eg.globals... eg.globals() gives a "TypeError: 'Bunch' object is not callable"
Code: Select all
"""
Universal collection of a bunch of named stuff.
Often we want to just collect a bunch of stuff together, naming each
item of the bunch. A dictionary is OK for that; however, when names are
constants and to be used just like variables, the dictionary-access syntax
("if bunch['squared'] > threshold", etc) is not maximally clear. It takes
very little effort to build a little class, as in this 'Bunch', that will
both ease the initialisation task and provide elegant attribute-access
syntax ("if bunch.squared > threshold", etc).
Usage is simple::
point = eg.Bunch(x=100, y=200)
# and of course you can read/write the named
# attributes you just created, add others, del
# some of them, etc, etc:
point.squared = point.x * point.y
if point.squared > threshold:
point.isok = True
"""
I think that answers the question you asked. But before you start changing globals - which could easily impact other's code - make sure that's what you really need. You can easily create and store your own variables within your plugin object and access the globals as read only, so there are other options.
There is a Main.OnClose event that you can add to a macro (I just tested with an OSD action).2. Is there a EG exit or system.shutdown event?
I'm not sure I understand. If you add an action to your plugin, you can add that action to a macro to call your plugins actions. That's so common, I think you mean something else, but I'm not sure what.3. Is there a way for a plugin to hook into events? Or can you only assign them via EG?
I don't think there is a way to reload plugins without restarting EG. As for restarting, I also don't think there is a way to restart EG from within EG. The best I can think of would be to a .bat file that starts EG, after maybe a 1 sec pause. Then call that .bat file (using a System->Start Application action).4. I'm syncing my EG configurations/plugins across my network, is there any call I can make to reload the configuration/plugins or restart EG?
Good luck,
Brett
Re: computer status plugin, eg.globals and more
Thanks for the wealth of information stottle, python shell is definitely going to be handy.
1. I'm throwing away all globals, that's obviously the wrong way to do it, and now that I know more about Python I can do it the right way.
3. I'm thinking of a way for the plugin to capture/detect events on it's own. ie. I get a computer online event from another computer on the network, I'd rather have my plugin automated enough to catch that event on it's own rather than have to create an EG event and tell my plugin that an event occured. More streamlining the user experience than anything I guess
4. I'll just whip something up myself that will restart EG, time to brush up on the windows API
1. I'm throwing away all globals, that's obviously the wrong way to do it, and now that I know more about Python I can do it the right way.
3. I'm thinking of a way for the plugin to capture/detect events on it's own. ie. I get a computer online event from another computer on the network, I'd rather have my plugin automated enough to catch that event on it's own rather than have to create an EG event and tell my plugin that an event occured. More streamlining the user experience than anything I guess
4. I'll just whip something up myself that will restart EG, time to brush up on the windows API
Re: computer status plugin, eg.globals and more
I've been looking at ways to streamline the user experience myself. The short answer is that without changing the core of EG, it isn't possible to get events without a macro. I've reworked the EventGhostEvent code to force certain events to a certain plugin, as well as a few other techniques. For right now though, I decided to just add the macro. At some point it may be necessary to change the core event handling, but it is a lot easier to prototype without changing the guts of EG. To make it easier on the end-user, you manually set up one computer and push the config or (even easier) pass along an xml config file with that macro included.Koke wrote:3. I'm thinking of a way for the plugin to capture/detect events on it's own. ie. I get a computer online event from another computer on the network, I'd rather have my plugin automated enough to catch that event on it's own rather than have to create an EG event and tell my plugin that an event occured. More streamlining the user experience than anything I guess
BTW, changing configs remotely is something I want to do as well, so I'm definitely interested in your progress. Also, you may be interested in my efforts to make configuration easier. I will post details in this thread when I have it working.
Brett
Re: computer status plugin, eg.globals and more
I got EG restarting after some work. I was hoping to create a eg.app.Restart() method but EG has issues when a copy of itself is starting while another is exiting. I also tried a batch as well which would work but EG doesn't always exit fast for me and didn't want to stick a long delay in there. In the end I just ended up just writing my own program that would restart it when the process ends.
Fake Service.exe:
Fake Service.exe [Path to exe] [optional - Create fake service 'bool' (default false)] [optional - poll timer in seconds 'int' (default 1)]
All it does is find the process for the exe given and wait for it to exit, then restart it. if you set the second option to true it will stay running and always restart the program when it exits, 3rd option is how often to check to see if the process is running. So DirectoryWatcher and EG restart:
autostart script:
DirectoryWatcher macro:
DirectoryWatcher.Deleted
DirectoryWatcher.Updated
script:
A couple notes with script: watchList needs a full xml name not just .xml. That's because EG creates a temp xml when saving and that will trigger the bug below. Also we have to handle the Deleted event which EG also does on save so that EG won't be restarted when we click save.
Bug: EG will crash if eg.document.CheckFileNeedsSave() is called twice in a row, most likely an issue trying to handle a second dialog box Unfortunately I couldn't figure out how to check if the dialog box was already open and exit to see if that would work.
Fake Service.exe:
Fake Service.exe [Path to exe] [optional - Create fake service 'bool' (default false)] [optional - poll timer in seconds 'int' (default 1)]
All it does is find the process for the exe given and wait for it to exit, then restart it. if you set the second option to true it will stay running and always restart the program when it exits, 3rd option is how often to check to see if the process is running. So DirectoryWatcher and EG restart:
autostart script:
Code: Select all
import time
eg.globals.LastFileOperation = time.time()
DirectoryWatcher.Deleted
DirectoryWatcher.Updated
script:
Code: Select all
import sys
import time
watchList = ('slave.xml', '.py')
if eg.event.string == 'DirectoryWatcher.Deleted' and eg.event.payload[0].lower().endswith(watchList):
eg.globals.LastFileOperation = time.time()
elif eg.event.string == 'DirectoryWatcher.Updated' and eg.event.payload[0].lower().endswith(watchList) and time.time() - eg.globals.LastFileOperation > 1:
eg.globals.LastFileOperation = time.time()
eg.plugins.System.Execute('Fake Service.exe', ''.join(['"', sys.argv[0], '"']), 3, False, 2, '')
eg.app.Exit()
Bug: EG will crash if eg.document.CheckFileNeedsSave() is called twice in a row, most likely an issue trying to handle a second dialog box Unfortunately I couldn't figure out how to check if the dialog box was already open and exit to see if that would work.
Re: computer status plugin, eg.globals and more
Here's the end result if anyone is interested, it's still rough, I didn't bother turning it into a real plugin with a config window since there's not much interest in it.
Required plugins:
Show Status Report:
Get a popup message for all online and responding computers:
All messages are prepended with the name of the computer that is sending the message
Required plugins:
- Network Event Receiver
Network Messaging
- System.Resume
System.Suspend
Main.OnClose
Network Messaging: EventHandler
- self.pollTime = 30 -- How often to query other computers in seconds (roughly)
self.timeout = 65 -- how long to wait before a MIA message is displayed for none responding computers
self.networkRouter = '1.1.1.1' -- Router IP, LAN for this plugin to work in
self.statusFileName = '!Status.txt' -- Name of the file to keep the computer status in (for crash/update checks)
- eg.plugins.FileOperations.Write(3, 'Info.EG updated', '!Status.txt', 0, 0, False, False, False, 'ascii')
Show Status Report:
Code: Select all
statusList = eg.plugins.NetworkMessaging.GetStatus()
hostlist = statusList.keys()
hostlist.sort()
for host in hostlist:
print ''.join([host, ' - ', statusList[host]])
All messages are prepended with the name of the computer that is sending the message
- eg.plugins.NetworkMessaging.SendMessage('RequestsStatus')
- eg.plugins.NetworkMessaging.SendMessage('event name', 'Computer')
- eg.plugins.NetworkMessaging.SendMessage('Info.Message to send', 'ToComputer')
- eg.plugins.NetworkMessaging.SendMessage('ToComputer.Standby', 'ToComputer')
- 1. Sporadically on system resume on the 3rd or 4th failed attempt to connect to a computer the call "sock.connect((host, self.port))" (line 110) bombs even though it is inside a try statement
2. Sporadically on system standby when calling "eg.scheduler.CancelTask(self.PollTask)" (line 250) the call bombs, my guess is because the task is being called at the same time this is happening. I stuck the line in a try statement and haven't seen it pop up again