It is currently June 25th, 2024, 3:56 pm

How can I set a variable with a measure's value?

Get help with creating, editing & fixing problems with skins
teiji
Posts: 27
Joined: April 9th, 2021, 5:15 pm

How can I set a variable with a measure's value?

Post by teiji »

I have a Powershell script that gets data from the Event Viewer and saves it into a log.txt (see sample log below). What I'm trying to do: If there is a new error in the log, a meter will display "error" and the latest error timestamp.

My current logic is this:

Code: Select all

on first run:  
	get data from log and save data to var1 and var2.

on loop:
	get data from log and save to var1 ONLY.
	compare var1 with var2
		if same, do nothing.
		if different, set problem to "error", save var1 to var2, start counter.
My problem is I can't get the !SetVariable to work correctly. Maybe it's a syntax problem or a bigger problem I'm not realizing. When I check the Rainmeter's log, I can see the MeasureLog displays the correct value (ie. 05/10/2023 10:31), but var 1 and var 2 just don't get set to that value correctly. Can anyone help?

Sample log.txt:
TimeCreated: 05/10/2023 10:31:16
Message: The Software Monitor Service service terminated unexpectedly. It has done this 1 time(s).

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
OnRefreshAction=[!DisableMeasure MeasureCounter]

[Variables]
maxCount=300
var1=0
var2=0
problem=no

[MeasureCounter]
Measure=Calc
Formula=(MeasureCounter+1)%(#maxCount#+1)
IfCondition=MeasureCounter = 0
IfTrueAction=[!DisableMeasure MeasureCounter]

[MeasureLog]
Measure=WebParser
Url=file://#@#log.txt
RegExp="(?siU)(\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2})"
StringIndex=1
UpdateRate=30
IfCondition=#var2# = 0
IfTrueAction=[!SetVariable var1 [MeasureLog]][!SetVariable var2 [MeasureLog]]
IfFalseAction=[!SetVariable var1 [MeasureLog]]
IfCondition2=#var1# = #var2#
IfFalseAction2=[!SetVariable problem "error"][!SetVariable var2 var1][!EnableMeasure MeasureCounter]

[MeterLog]
Meter=String
MeasureName=MeasureLog
FontSize=30
FontWeight=400
FontColor=255,255,255,255
AntiAlias=1
Text=#problem# %1
X=0
Y=100

User avatar
balala
Rainmeter Sage
Posts: 16339
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: How can I set a variable with a measure's value?

Post by balala »

teiji wrote: May 10th, 2023, 8:13 pm My problem is I can't get the !SetVariable to work correctly. Maybe it's a syntax problem or a bigger problem I'm not realizing. When I check the Rainmeter's log, I can see the MeasureLog displays the correct value (ie. 05/10/2023 10:31), but var 1 and var 2 just don't get set to that value correctly. Can anyone help?
The simplest solution is to add an IfConditionMode=1 option to the [MeasureLog] measure.
teiji
Posts: 27
Joined: April 9th, 2021, 5:15 pm

Re: How can I set a variable with a measure's value?

Post by teiji »

balala wrote: May 10th, 2023, 8:34 pm The simplest solution is to add an IfConditionMode=1 option to the [MeasureLog] measure.
Thank you! Both var1 and var2 are finally updated. Now, I just need to wait for a new error to test if everything works like I wanted.
User avatar
balala
Rainmeter Sage
Posts: 16339
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: How can I set a variable with a measure's value?

Post by balala »

teiji wrote: May 10th, 2023, 8:48 pm Now, I just need to wait for a new error to test if everything works like I wanted.
Hope it does. If doesn't, come back with a description of what is going wrong.
teiji
Posts: 27
Joined: April 9th, 2021, 5:15 pm

Re: How can I set a variable with a measure's value?

Post by teiji »

I simulated a new event log by changing the log.txt directly while the skin is running. It seems this line

Code: Select all

IfCondition=#var2# = 0
keeps returning true on every update, even when var2 was already changed to "05/10/2023 10:31:16" value on its first run (which means subsequent update should be false). My IfFalseAction never gets run, so it never shows "error" in the meter.

Is it because variables in the [Variables] section can't be used dynamically (according to https://docs.rainmeter.net/manual/variables/)?
If so, then I don't get it because the Rainmeter's log shows that var2 did indeed changed to "05/10/2023 10:31:16" on the first run.

How can I fix this?
User avatar
balala
Rainmeter Sage
Posts: 16339
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: How can I set a variable with a measure's value?

Post by balala »

teiji wrote: May 10th, 2023, 9:46 pm I simulated a new event log by changing the log.txt directly while the skin is running. It seems this line

Code: Select all

IfCondition=#var2# = 0
keeps returning true on every update, even when var2 was already changed to "05/10/2023 10:31:16" value on its first run (which means subsequent update should be false). My IfFalseAction never gets run, so it never shows "error" in the meter.

Is it because variables in the [Variables] section can't be used dynamically (according to https://docs.rainmeter.net/manual/variables/)?
If so, then I don't get it because the Rainmeter's log shows that var2 did indeed changed to "05/10/2023 10:31:16" on the first run.
The IfCondition works ONLY with numeric values. This means that if the var1 and var2 variables are set to dates, these are not numeric and accordingly the IfCondition is not evaluated anymore. So, when refreshing the skin, the condition is true (var2 being set to 0 in the [Variables] section), this is why the condition is evaluated as being true. When the var2 is set to 05/10/2023 10:31:16 by the appropriate !SetVariable bang, the IfCondition loses its meaning, couldn1t be used to compare a string (a date) to a number.
Once again, IfCondition has to be entirely numeric. You can't use it to compare strings. For this you have to use IfMatch, which is meant to work with strings.
To be honest I can't follow exactly what are you doing there or what would you like to achieve. To can do this and if you want further help, please pack the whole config (containing the @Resources\log.txt file as well) and upload the package here, to can check exactly what is going on there.
teiji
Posts: 27
Joined: April 9th, 2021, 5:15 pm

Re: How can I set a variable with a measure's value?

Post by teiji »

I changed the code to use IfMatch, but it still doesn't work.

What I'm trying to do is this: (using examples for easier to understand)
Let's say the log.txt has an event at "05/10/2023 10:31". A meter will display "no: 05/10/2023 10:31" (or whatever because the first event is not important to me, only subsequent events are important). (My powershell script makes sure there is always a single latest event in log.txt.)

Then let's say, at "05/10/2023 20:07", a new event was created and changed in the log.txt. The meter will display "error: 05/10/2023 20:07", displays that for 10 sec (I'm using counter to start/stop but it doesn't seem to work either lol), then the meter will go back to display "no: 05/10/2023 20:07" until a new event is created in the log.

And then a new event was created at "05/10/2023 22:50", the meter will display "error: 05/10/2023 22:50" for 10 sec like before, then goes back to displaying "no: 05/10/2023 22:50" afterward. You get my point.

Maybe you can help me figure out what's wrong with my code or if my logic isn't correct, then can you help me come up with a better logic?
You do not have the required permissions to view the files attached to this post.
User avatar
balala
Rainmeter Sage
Posts: 16339
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: How can I set a variable with a measure's value?

Post by balala »

teiji wrote: May 11th, 2023, 5:13 pm Maybe you can help me figure out what's wrong with my code or if my logic isn't correct, then can you help me come up with a better logic?
There are some mistakes in your code, as well as are some things which are missing. Namely:
  • Same way as an IfCondition can't handle not-numeric condition, a Calc measure can't work with strings either. Accordingly the [MeasureTest2] measure doesn't work. It simply doesn't know what to do with a string, like a date and time. To handle these strings, you need a String measure. So rewrite the above measure to a string measure:

    Code: Select all

    [MeasureTest2]
    Measure=String
    String=[MeasureLog]
    IfMatch=#var1#
    IfMatchAction=[!EnableMeasure MeasureCounter][!SetVariable problem "error"]
    IfNotMatchAction=[!SetVariable problem "no"][!SetVariable var1 [MeasureLog]][!DisableMeasure MeasureCounter]
    DynamicVariables=1
    See that since the [MeasureLog] measure is in fact a section variable, I had to set on the dynamic variables, by adding a DynamicVariables=1 option as well. I also disabled this measure, not to execute any of the IfMatchAction or IfNotMatchAction option from the first moment when you refresh the skin.
  • Since the original [MeasureTest2] measure, as a Calc measure, couldn't work, there were no cases in which the [MeasureCounter] measure would have been enabled. This is why it has not been never started counting. When the [MeasureTest2] measure has been converted to a String measure (as described above), the condition in some cases has started to be true and in these cases the [MeasureCounter] measure has been enabled. But once enabled, it never has been "re-disabled" again. There simply is no condition to disable the measure. So, I added an IfCondition to the [MeasureCounter] measure, which can disable it when it gets the largest possible value (#maxCount#):

    Code: Select all

    [MeasureCounter]
    Measure=Calc
    Formula=(MeasureCounter+1)%(#maxCount#+1)
    IfCondition=(MeasureCounter=#maxCount#)
    ;IfCondition=(#CURRENTSECTION#=#maxCount#)
    IfTrueAction=[!SetVariable problem "no"][!DisableMeasure "#CURRENTSECTION#"][!UpdateMeter "MeterLog"][!Redraw]
    Disabled=1
    See that I also disabled the measure from the beginning (adding the Disabled=1 option), not to let it start counting when the skin is refreshed. This is not needed, it should being enabled only when the WebParser measure gets the value and this value is equal to #var1#. This enabling is done by the IfMatchaction option of the [MeasureTest2] measure (as described above).
  • The problem variable is changed dynamically. Any measure or meter using a dynamically altered variable has to have a DynamicVariable=1 option added, without it, the new value of the variable can't be used. This is why the [MeterLog] meter needs this option (add it).
  • The [MeasureCounter] measure has been disabled by the newly added Disabled=1 option, so the OnRefreshaction option loses its meaning. I removed it (even if keeping it, instead of adding the Disable=1 option to the measure itself is same way a good solution - it's only my bad not to like an OnRefreshAction instead of a simple option, added to a measure).
  • I added a BackgroundMode=2 and a SolidColor=0,0,0,1 option to the [Rainmeter] section, to create a not visible but not-completely transparent background either. This way the skin becomes much more easier clickable.
Taking into account all this, here is the rewritten code of your skin. Please try it out and let me know if it's working as expected.

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
BackgroundMode=2
SolidColor=0,0,0,120
DynamicWindowSize=1

[Variables]
maxCount=10
var1=0
problem=no

[MeasureCounter]
Measure=Calc
Formula=(( MeasureCounter + 1 ) % ( #maxCount# + 1 ))
IfCondition=(MeasureCounter=#maxCount#)
IfTrueAction=[!SetVariable problem "no"][!DisableMeasure "#CURRENTSECTION#"][!UpdateMeter "MeterLog"][!Redraw]
Disabled=1

[MeasureLog]
Measure=WebParser
Url=file://#@#log.txt
RegExp=(?siU)(\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2})
StringIndex=1
UpdateRate=30
FinishAction=[!EnableMeasure "MeasureTest2"]
IfMatch=05/10/2023 10:31
IfMatchAction=[!SetVariable var1 "[MeasureLog]"]
IfMatchMode=1

[MeasureTest2]
Measure=String
String=[MeasureLog]
DynamicVariables=1
IfMatch=#var1#
IfMatchAction=[!EnableMeasure MeasureCounter][!SetVariable problem "error"]
IfNotMatchAction=[!SetVariable problem "no"][!SetVariable var1 "[MeasureLog]"][!DisableMeasure MeasureCounter]
Disabled=1

[MeterLog]
Meter=String
MeasureName=MeasureLog
FontSize=30
FontWeight=400
FontColor=255,255,255,255
AntiAlias=1
Text=#problem# %1
X=0
Y=100
DynamicVariables=1

[MeterCounter]
Meter=String
MeasureName=MeasureCounter
FontSize=30
FontWeight=400
FontColor=255,255,255,255
AntiAlias=1
Text=%1
X=0
Y=0
User avatar
Yincognito
Rainmeter Sage
Posts: 7517
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: How can I set a variable with a measure's value?

Post by Yincognito »

teiji wrote: May 10th, 2023, 8:13 pm I have a Powershell script that gets data from the Event Viewer and saves it into a log.txt (see sample log below). What I'm trying to do: If there is a new error in the log, a meter will display "error" and the latest error timestamp.
Just chiming in a bit to say that if you want to create an Event Viewer monitoring skin, I think it's a great idea (and a relatively novell one, departing from the usual "weather, cpu, memory, etc.") and potentially VERY useful. Make sure you post it on the forum when it's fully done and if you remember to notify me to check it out, that would be nice. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
teiji
Posts: 27
Joined: April 9th, 2021, 5:15 pm

Re: How can I set a variable with a measure's value?

Post by teiji »

@balala

Thank you so much. It does work! I learned a lot from the errors you mentioned. I see one problem still remain though. Currently I hardcoded the first event from the log to the match condition to ensure it will always match on the first run to set the var1 correctly:

Code: Select all

IfMatch=05/10/2023 10:31
But if the log.txt doesn't have that time, then the skin breaks down because this will never be true:

Code: Select all

IfMatch=05/10/2023 10:31
IfMatchAction=[!SetVariable var1 "[MeasureLog]"]
Edit:
I have figured a way around this by adding an initialRun variable and everything works perfectly now. So far, I got the basic gist down now. I'll turn it into a full fledged skin and share with the community as Yincognito suggested. Thanks a lot again!

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
BackgroundMode=2
SolidColor=0,0,0,120
DynamicWindowSize=1

[Variables]
maxCount=10
var1=0
problem=no
initialRun=0

colorWhite=255,255,255,255
colorRed=255,87,87,255


[MeasureLog]
Measure=WebParser
Url=file://#@#log.txt
RegExp=(?siU)(\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2})
StringIndex=1
UpdateRate=30
FinishAction=[!EnableMeasure "MeasureTest2"]

[MeasureCounter]
Measure=Calc
Formula=(( MeasureCounter + 1 ) % ( #maxCount# + 1 ))
IfCondition=(MeasureCounter=#maxCount#)
IfTrueAction=[!SetVariable problem "No"][!DisableMeasure "#CURRENTSECTION#"][!SetOption MeterLog FontColor #colorWhite#][!UpdateMeter "MeterLog"][!Redraw]
IfCondition2=(#initialRun#=0)
IfTrueAction2=[!SetVariable var1 "[MeasureLog]"][!SetVariable initialRun 1]
Disabled=1

[MeasureTest2]
Measure=String
String=[MeasureLog]
DynamicVariables=1
IfMatch=#var1#
IfMatchAction=[!EnableMeasure MeasureCounter][!SetVariable problem "ERROR"][!SetOption MeterLog FontColor #colorRed#]
IfNotMatchAction=[!SetVariable problem "No"][!SetVariable var1 "[MeasureLog]"][!DisableMeasure MeasureCounter]
Disabled=1

[MeterLog]
Meter=String
MeasureName=MeasureLog
FontSize=30
FontWeight=400
FontColor=255,255,255,255
AntiAlias=1
Text=#problem#: %1
X=0
Y=100
DynamicVariables=1

[MeterCounter]
Meter=String
MeasureName=MeasureCounter
FontSize=30
FontWeight=400
FontColor=255,255,255,255
AntiAlias=1
Text=%1
X=0
Y=0