The thing is, I get a syntax error in the log at the line using IfCondition option, and obviously, the skin does not produce the desired results as a consequence. Narrowing the error source, I found out that it relates to the (#b#>0) test - that is, Rainmeter does not recognize the b variable.
Further narrowing the problem, I found out that if I replace (#b#>0) with (#a#>0), everything works as expected (e.g. no error in the log), so basically the root cause of this is that the b variable is not "declared" (aka is not a section variable, but an ad-hoc one) so it's not recognized, as oposed to the a variable, which, as you see, is "declared" in the [Variables] section at the start of the code.
Now of course I can easily solve the problem by just "declaring" b too, but I didn't for a reason : there will be many of them bs...
What I want to know is : is this suppose to happen? is it normal that Rainmeter reacts like that? or has this anything to do with the fact that I've used both IfMatch and IfCondition in the same measure? maybe these options need to "finish" executing before the code recognises the new created variable b?
From what I've checked in the manual, I didn't seem to cross any "red line" :
- the IfCondition option help states that IfConditions are similar in functionality to IfActions, with a few important and powerful differences : The formula is not based on the value of the measure the IfCondition is in, but can reference any measures, variables or section variables.
- the !SetVariable bang help states that !SetVariable can create a new variable in memory, even if it is not pre-defined in the [Variables] section.
What I get from this is that IfCondition can manipulate not only variables "declared" in the [Variables] section (aka section variables), but also "normal"/"common" variables (aka ad-hoc variables, like my b, which is not pre-defined).
Or...am I wrong and I misunderstood it? Can you point me to how I could make my b variable "visible" to Rainmeter? What am I doing wrong (if any)?
The problem has nothing to do really with "declared" or not.
That is what is causing the error in the log, however the real problem is that the !SetVariable bang on the IfMatch which is setting #b#, and the IfCondition which is testing the value of #b#, are both happening in the same context, that single measure.
The issue is that the IfCondition is being evaluated before the IfMatch. The order that things are in the measure doesn't mean a thing. There is a defined order that that things are measured, #Variables# and [Section Variables] resolved, actions taken, and some options applied in the context of a single measure. IfConditon comes before IfMatch.
What I'm getting at is that when the IfCondition "test" is done, Rainmeter has not yet reacted to that !SetVariable, and so #b# is undefined and generates an error.
Now, on the very next update of the measure, all will be well, as #b# will be properly defined, and everything will work. However, since you have UpdateDivider=3600 on the measure, that won't be for an hour...
Simply "declaring" the variable in [Variables] won't help in this case, other than to eliminate the error in the log. The value of #b# will still be whatever you set it to initially in [Variables] when you "test" it with IfCondition, so while it won't be an "error", it will be "wrong" for one update.
The way to fix this is to have that IfCondition "test" be in a separate measure that happens "after" the variable is set. Like this for instance:
!SetVariable bang on the IfMatch which is setting #b#, and the IfCondition which is testing the value of #b#, are both happening in the same context, that single measure.
Yep, that's what I thought to be one of the possibilities, too. Thank you for making it clear.
However, since you have UpdateDivider=3600 on the measure, that won't be for an hour...
I LOLed a little on that...
the IfCondition is being evaluated before the IfMatch.
Well, Rainmeter is full of surprises, at least on the coding side. Can be stubborn sometimes, but still fun to play with. Thanks for letting me know the order in which things are evaluated.
I hoped that splitting the measure in two will be avoidable, but I guess it's the only way.
I'd be tempted to really look at the logic of what you are doing and see if you can't have all the actions take place in the IFMatch, rather than having the IfMatch set some "number" that you then test with IfCondition. Feels like there should be some way to roll this up a bit.
Maybe not since you are apparently looking to test the values of other measures in your IfCondtion as well, which IfMatch can't do. IfCondtion can be about any measure(s), IfMatch is strictly about the measure it is on.
LOL, well, it's not THAT hard...just stubborn and full of surprises. Like a ... present that won't open on Christmass
Mmm... the logic. You wouldn't want to know... I'm having trouble myself in keeping it as simple as possible. As I said before, there will be lots of "b"s in the skin, so making it both clumsy and big is something to be avoided. Luckily, I'm only building the "prototype" now (that is, the part that will be copy/pasted/modified a lot), so the "problem" doesn't take more than a few pages.
In essence, what I'm doing is rebuilding the network skin (the one on which I asked you regarding WebParser reset, if you remember), but this time with the aim of making it AUTOMATICALLY detect the number of networks and display the network cards' activity. I already done that for the processors (aka CPU core threads), GPUs, logical disks, etc and the networks are last on the "skin rebuilding list".Compared to the other skins online, this one gets separate network cards activity (therefore accurately displaying NetIn/NetOut) while not needing the user to manually edit variables to set the names of the NICs. I'm getting the data using PerfMon, not Net option, as I can easily "tweak" some registry values to make them "PerfMon ready".
The thing is, to make the "network adapters discovery" (and their number) automatic, I need to check around 100 existing (or non-existing) registry values, as Windows has a weird numbering system for them. Those "potential" network adapters (actually the registry values) are stored in [MS_Registry_NetworkCard<N>Description] measures, where N will range from 1 to 100 (in the code below there is only the "1" prototype). As I parse through those potential network adapter names, I use a "validation" test - the one I simplified earlier - which checks :
a) if the registry contains a usable value (aka IfMatch<>^$ condition)
b) if that usable value is not "invalidated" by the user setting the maximum download/upload speed to 0 in the Variables.inc (which I will use as a way to let the user "exclude" the valid network cards that he/she doesn't want to be displayed) - that's the IfCondition thingy.
If both a) and b) are true (aka IfMatch and IfCondition are true), I let the meter group for that particular network card to be displayed and I assign a ordered number (ranging from 1 to 20, aka NetworkCard<N>Index variable) to it. Otherwise, I hide the meter group and I don't increment NetworkCardIndexCounter variable, so that the next "shown" meter group doesn't skip numbers when assigning them to be displayed as NetworkCard<N>Index in the [MT_PerfMon_NetworkCard1_Title] meter.
If by some impossible computer "features" no network adapter is found, a proper NoNetworkCardGroup meter group will be displayed, notifying the user.
Notes:
1) [MS_Calc_NetworkCardMaxDLSpeed] and [MS_Calc_NetworkCardMaxULSpeed] take their values from the NetworkCard<N>MaxDLSpeed / NetworkCard<N>MaxULSpeed variables from Variables.inc, where N is the "ordered" "index" that's displayed in the network card title meter below (that number ranging from 1 to 20 I mentioned earlier - those numbers represent in fact the "REAL" network adapters, the 1 to 100 which will be further "made" by copy/pasting/modifying representing the strings from the registry values).
2) [MS_Calc_NetworkCardTitleYRelativePosition] measure controls the relative position compared to the previous line of text. The text is displayed after a "margin" (aka the skin border) for the first line.
Pretty much else is pretty self explanatory (a little hard to understand though if you don't have the Variables.inc file). I'm also displaying some nice tinted LEDs (light bulbs) to signal network card activity, too.
But for the logic that we were talking about, I should note that NetworkCardIndexCounter is the a variable in my simplified piece of code and NetworkCard1Index is the b.
I don't know if I was clear enough, but I guess you'll have no trouble understanding the "basics" - after all you've given a lot of useful advices on this forum, and some of them helped me too in building these little automated skins.
I guess this predefined order has to do with the fact that it's more likely that the strings in the IfMatch option use the numbers from the IfAction/IfCondition than the other way around? Or maybe some more technical considerations?...
Yincognito wrote:
I guess this predefined order has to do with the fact that it's more likely that the strings in the IfMatch option use the numbers from the IfAction/IfCondition than the other way around? Or maybe some more technical considerations?...
I think it is mostly that when both are on the same measure, it has to do them in some order. I suspect it is a simple matter that IfCondition was added to the code before IfMatch was. Since you very seldom use both IfCondtion (number based) and IfMatch (string based) on the same measure, I'm not sure there was any real consideration that one order was any better than the other.
One thing to keep in mind is that you can have as many IfConditions on a measure as you want.
What I'm suggesting is that you won't need a separate Calc measure as a "host" for the IfConditions for each test you want to make. Just stack them all up on one measure. Just put it at the end of all the measures, before you start the meters.
Maybe not since you are apparently looking to test the values of other measures in your IfCondtion as well, which IfMatch can't do. IfCondtion can be about any measure(s), IfMatch is strictly about the measure it is on.
Mmm...yes...and no. Actually I've initially started with all the tests done in the IfMatch option UNTIL I wanted to give the user a way to exclude NICs from displaying their data, which brought me to the IfCondition test and subsequently "broke" the "unity" of IfMatch conditions set.
Without the exclude options given to the user, I would have no problem gathering all things in the IfMatch option. But on the other hand, I saw images of 5 or 6 available NICs in the registry, so I bet one would want to display only those NICs that are actually used in networking activity (myself included).
In my case, it's not that big of an issue. I have the LAN and the Wireless NICs and I want them both displayed, even if one is not actively transferring data. But in my case, we talk about only 2 NICs. If there were 5 or 6, I wouldn't want the network skin to stretch over half of my laptop screen to show only empty bars and zeroes.... That's why I thought the exclude possibility is a must.