It is currently October 22nd, 2021, 5:38 am

Skin Packager improvement

Report bugs with the Rainmeter application and suggest features.
User avatar
Active Colors
Moderator
Posts: 870
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Re: Skin Packager improvement

Post by Active Colors »

Yincognito wrote: January 17th, 2021, 7:33 pm Just curious, when you say "import", what do you mean by it? Copying the contents of the backed-up file to the new file, reading it with WebParser, @Include it, or some other technique I'm not aware of?

Since we're at it, this is a good idea, cause I'm thinking one doesn't even need a command to run on the first skin activation - it can be done much easier (not that the already available soutions are complicated, of course), by simply @Including both the "new" (presumably, empty) variables file AND the "old" (i.e. backed-up) variables file in the skin ... but in this order, so that the backed-up variable values would overwrite the possible values in the new file. Like:

Code: Select all

[Variables]
@IncludeVariables=#@#Variables.inc
@IncludeBackedUpVariables=#SKINSPATH#@Backup\#ROOTCONFIG#\@Resources\Variables.inc
Obviously, #ROOTCONFIG#\@Resources can be replaced by, say, #CURRENTCONFIG#\@Resources, or whatever your actual relative path to the variables file is. So, in the above code, the "old" variables file's values would overwrite similar values from the "new" variables file since the former's inclusion comes after the latter's one, in effect preserving old existing variable values. Unless there is some same section name conflict (since all section names must be unique in the INI format, and I didn't test the approach to see if it works) that would prevent this from happening, this could be enough... :???:

P.S. I'm not sure whether the backed-up file's inclusion would fail silently if that file doesn't exist or would generate a Log error, but in any case, I believe this wouldn't prevent the functionality. The only question is regarding same section name, but even that can probably be easily avoided.
Via @include.

In fact I had the exact same question raised as balala's in my mind before. And I decided that I would try including a file with variables from @backup folder and then with bunch of !WriteKeyValues write the values back.

But this implies you know which keys you are "importing". This depends on your case as you can change the key names overtime after several updates. It would be easier for anyone just to keep your variable names same as before. Or prepare some "legacy" keys to import if you completely overhaul your skin and change all the key names. So you need to be careful about your scenarios and keep in mind peculiarities about your skin and how the "import" works for you.

For myself I wanted to make sort of a "module" (separate .inc file) which would:
1. Run once after my skin is installed.
2. @include the file(s) in question from @backup.
3. !WriteKeyValue your keys into my main place with variables.
4. Remove itself with !WriteKeyValue from loading itself (@include=import_module.inc –> @include=).
User avatar
Yincognito
Rainmeter Sage
Posts: 4070
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Skin Packager improvement

Post by Yincognito »

balala wrote: January 17th, 2021, 8:44 pmTo be honest as far as I can tell your example doesn't exactly fits my needs. I should have an empty .inc file included into the skin installer and when installing the skin the file shouldn't overwrite the existing similar file, because this last one includes the variables which have been created after the skin has been installed. If the skin is installed for the first time, the included file doesn't exist yet, that's why ther installer has to include the empty file.
I suppose in your example I should install first the Test_1.0.0.rmskin package and when I get it running I should install over it the Test_1.0.1.rmskin package. Is this correct? If it is, as said, it's not exactly what I want, because the included Variables.inc overwrites the existing one. My need would be to get the file copied (installed) empty when the skin is installed for the first time, but never get it overwritten when a later package (update / upgrade of the existing skin) is installed over the existing package.
Well, technically, it doesn't overwrite any file, since the existing similar file would be backed up in the @Backup folder. That was the whole point of ActiveColors' reply, as far as I can tell. In other words, you'd have 2 variables files:
- one that is backed up along with the previous version of the skin, in the @Backup folder in the Rainmeter's skin folder
- the "current" one, aka the variables file that is copied when the current version of the skin is installed
My approach here takes advantage of the fact that both these 2 files exist (or should exist, on a skin "upgrade", unless the user unchecked the "Back Up Skin" option - I believe this is how it's called - in the skin installer). So I used both files when @Including them in the skin. Other than that, it doesn't really matter if you install Test 1.0.1 over Test 1.0.0 or viceversa, it works both ways, according to my tests. It doesn't matter if one of the files is "empty" or doesn't exist either (unless, as I said, the user chooses not to back up the previous version of the skin), thus no need to change your original approach. So, I still think it could work for you, unless I missed something from your explanation.

Regarding the encoding, it appears you're unlucky, since the command line (CMD.EXE) doesn't play so well with the modern encodings, especially 65001 (UTF-8), but also 1200 (I might be wrong, but this should be the UTF-16 LE). So, neither of these:

Code: Select all

>>"Variables.inc" chcp 1200 | type nul
>>"Variables.inc" chcp 1200 & type nul
>>"Variables.inc" chcp 65001 | type nul
>>"Variables.inc" chcp 65001 & type nul
IF not EXIST "Variables.inc" (chcp 1200 | type nul>"Variables.inc")
IF not EXIST "Variables.inc" (chcp 1200 & type nul>"Variables.inc")
IF not EXIST "Variables.inc" (chcp 65001 | type nul>"Variables.inc")
IF not EXIST "Variables.inc" (chcp 65001 & type nul>"Variables.inc")
will produce the desired result. CHCP stands for "change code page". I used both & and | here because I couldn't remember which one of them means "run this AND this sequentially".

Anyway, as always, PowerShell can do it (a bit slower than CMD.EXE, but this seems to be the only working choice for this variant of a solution):

Code: Select all

if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
Adjust the path or the value as you wish. If you're working in the current folder, I believe .\Variables.inc would do. This does produce a UCS-2 LE BOM in Notepad++ in my tests, so all good. Make sure you write things properly in the RunCommand measure, as the quotes might need some escaping (i.e. \"), not sure if in all cases though:

Code: Select all

Program=powershell
Parameter=-command if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
Last edited by Yincognito on January 17th, 2021, 10:51 pm, edited 4 times in total.
User avatar
Yincognito
Rainmeter Sage
Posts: 4070
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Skin Packager improvement

Post by Yincognito »

Active Colors wrote: January 17th, 2021, 9:58 pm Via @include.

In fact I had the exact same question raised as balala's in my mind before. And I decided that I would try including a file with variables from @backup folder and then with bunch of !WriteKeyValues write the values back.

But this implies you know which keys you are "importing". This depends on your case as you can change the key names overtime after several updates. It would be easier for anyone just to keep your variable names same as before. Or prepare some "legacy" keys to import if you completely overhaul your skin and change all the key names. So you need to be careful about your scenarios and keep in mind peculiarities about your skin and how the "import" works for you.

For myself I wanted to make sort of a "module" (separate .inc file) which would:
1. Run once after my skin is installed.
2. @include the file(s) in question from @backup.
3. !WriteKeyValue your keys into my main place with variables.
4. Remove itself with !WriteKeyValue from loading itself (@include=import_module.inc –> @include=).
Ah, I see. So instead of getting all the old variables via @Include-ing the old variables file after the current one, you chose to selectively "pick" the old variables you wanted to keep, by using !WriteKeyValue to "update" your current variables file. I'm not missing anything, right?
User avatar
Yincognito
Rainmeter Sage
Posts: 4070
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Skin Packager improvement

Post by Yincognito »

balala wrote: January 17th, 2021, 8:44 pmMy need would be to get the file copied (installed) empty when the skin is installed for the first time, but never get it overwritten when a later package (update / upgrade of the existing skin) is installed over the existing package.
In the interest of being clear and synthesize things, apart from ActiveColors' slightly "customized" approach, these are the solutions I see - and both produce the same result:

1. Not use an empty variables file, but create it in a RunCommand measure executed on the first run of the skin, through this adjustable PowerShell command, which creates an empty UCS-2 LE BOM file in Notepad++ if that file doesn't yet exist and does nothing - thus preserving the existing file content - if the file already exists:

Code: Select all

if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
2. Keep using an empty variables file like in your original approach, but @Include both the backed-up variables file from the previous version of the skin and the variables file from the current version of the skin, in this order, so that already created variable values from the previous version of the skin would persist across skin upgrades:

Code: Select all

[Variables]
@IncludeVariables=#@#Variables.inc
@IncludeBackedUpVariables=#SKINSPATH#@Backup\#CURRENTCONFIG#\@Resources\Variables.inc
Question: How comes the 2-nd variant produces the same result as the 1st (assuming, of course, that the user keeps the "Backup skins" option in the Skin Installer checked)?
Answer: Simple. Let's see what happens, step by step:
- version 1 of the skin is installed; this contains the "empty" variables file, so only the 1st of the @includes above would be valid (since the backup of the skin isn't yet created), thus no variable values would exist; of course, when dynamically creating variables, writing them in the variables file and refreshing the skin, the values would be correctly included
- version 2 of the skin is installed; this also contains the "empty" variables file, but unlike before, this time the backup of version 1 of the skin is moved/created in the @Backup folder from the Rainmeter skins folder, thus both @includes above are valid, as both the v.2 and the v.1 variables files exist; however, because of the order of @includes above, the v.1 variables (now backed up) "superseed" and "overwrite" any potential/hypothetical v.2 variables, in effect preserving the variable values from v.1, aka the previous version; of course, there isn't much to superseed or overwrite since the v.2 variables file is the default "empty" one, but it would anyway, if by any chance the v.2 variables file would be populated; yet again, when dynamically creating variables, writing them in the (current, aka v.2) variables file and refreshing the skin, the values would be correctly included, as long as their names differ from the "persisting" variables from v.1
- versions 3 to infinity of the skin are installed; the same things happen as for version 2, but obviously now the main "actors" are v.3 and v.2 (and following) versions, instead of v.2 and v.1 as before
Conclusion: The goal of preserving the variables' values across skin upgrades is achieved in the 2nd variant of a solution as well (encoding is not an issue in that variant, assuming you already encode the default "empty" variables files as UCS-2 LE BOM in Notepad++).

Hopefully it's clearer now why I said that both options are suited for your case. The only thing that would tip the balance for one or the other is whether the user would uncheck the "Backup skins" option in the Skin Installer, which would invalidate the 2nd solution. And, of course, there is the small inconvenient error Log message if the @Backup variables file doesn't exist yet, since the developers insinst that users shouldn't be able to selectively "hide" such Log messages, even in cases when those "errors" are part of the intentional and normal functioning of the skin.

EDIT: As I said, things happen properly if the written variables have different names from the already existing ones (from previous versions). If you need to give a new value to an already existing variable, the 2nd solution won't work (unless you write the variable to the @Backup variables file, i.e. the "master" file in this scheme). But then, as per your words:
balala wrote: January 13th, 2021, 5:08 pmThen after the skin is installed and get starting using, variables are created regularly and written to this file (for instance one new variable each day). Over time, more and more such variables are added into this file.
so it seems you're talking about entirely new variables that you dynamically add/write over the course of the functioning of the skin, thus it's all good.
User avatar
balala
Rainmeter Sage
Posts: 13337
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Skin Packager improvement

Post by balala »

Yincognito wrote: January 17th, 2021, 10:03 pm Anyway, as always, PowerShell can do it (a bit slower than CMD.EXE, but this seems to be the only working choice for this variant of a solution):

Code: Select all

if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
Adjust the path or the value as you wish. If you're working in the current folder, I believe .\Variables.inc would do. This does produce a UCS-2 LE BOM in Notepad++ in my tests, so all good. Make sure you write things properly in the RunCommand measure, as the quotes might need some escaping (i.e. \"), not sure if in all cases though:

Code: Select all

Program=powershell
Parameter=-command if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
Very good idea, as always. Definitely has to be taken into account. Will take a deeper look, to see how can I get it to properly work.
Thanky ou for the help. :great:
User avatar
balala
Rainmeter Sage
Posts: 13337
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Skin Packager improvement

Post by balala »

Yincognito wrote: January 17th, 2021, 11:55 pm EDIT: As I said, things happen properly if the written variables have different names from the already existing ones (from previous versions). If you need to give a new value to an already existing variable, the 2nd solution won't work (unless you write the variable to the @Backup variables file, i.e. the "master" file in this scheme). But then, as per your words:

so it seems you're talking about entirely new variables that you dynamically add/write over the course of the functioning of the skin, thus it's all good.
Me personally would prefer the method in which I don't use the backed-up config. Not entirely sure yet why (except what have you written about the case when the user uncheks the Backup checkbox), but I feel something there is not the best with this solution (however when I'm gonna dig deeper, it might proofe a good solution, that's why I don't exclude it, just saying have to study it).
To precisely tell what is my intention: I have a skin (SunMoon of my Mirage suite) which writes the length of each daylight into a file (namely @Resources\SunMoon\DayLength.inc, but this is less important, I suppose). When upgrading my package, I'd like to keep stored the already written day lengths.
Thanks again for all the help.
User avatar
Yincognito
Rainmeter Sage
Posts: 4070
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Skin Packager improvement

Post by Yincognito »

balala wrote: January 18th, 2021, 7:58 am Me personally would prefer the method in which I don't use the backed-up config. Not entirely sure yet why (except what have you written about the case when the user uncheks the Backup checkbox), but I feel something there is not the best with this solution (however when I'm gonna dig deeper, it might proofe a good solution, that's why I don't exclude it, just saying have to study it).
To precisely tell what is my intention: I have a skin (SunMoon of my Mirage suite) which writes the length of each daylight into a file (namely @Resources\SunMoon\DayLength.inc, but this is less important, I suppose). When upgrading my package, I'd like to keep stored the already written day lengths.
Thanks again for all the help.
I understand completely - the other method is less dependent on things that are not under your control. I just wanted to demonstrate that both solutions would work, because you didn't seem convinced by it, that's all.

Since we're at it, here's another way of achieving the same - this time using the built-in Variables File from the Skin Packager (i.e. sort of how you initially wanted to do it):
Test_1.0.0.rmskin
Test_1.0.1.rmskin
These two "versions" are basically the same, and both have the Variables File set in the Skin Packager options (you add a new variable by left clicking, you navigate between them by mouse scrolling). The difference compared to your original attempt is that only a single variable that's always there is used (i.e. Daylights), instead of a ton of similar but volatile variables like Daylight1, Daylight 2 and so on. Individual daylight values are then easily extracted from the Daylights variable using regex quantifiers (e.g. {[SomeIndex]}).

The reason why your original attempt didn't work was that you didn't have any variables in the variables file, so the Skin Packager didn't have any variables whose values it would keep unchanged. Obviously, in your original approach it made sense, since you didn't knew how many of variables there would be and so on. In this approach, it simply doesn't matter, since they are "aggregated" into an always existing single entry, with new values appended at the end of it. I'm sure you'll understand the principle here, but if by any chance it's still unclear, don't hesitate to ask for clarifications. ;-)

P.S. I simulated the values using Time measures - so that part isn't really important.
EDIT: By "daylight" I meant "daylength", of course.
You do not have the required permissions to view the files attached to this post.
User avatar
balala
Rainmeter Sage
Posts: 13337
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Skin Packager improvement

Post by balala »

Yincognito wrote: January 17th, 2021, 10:03 pm Anyway, as always, PowerShell can do it (a bit slower than CMD.EXE, but this seems to be the only working choice for this variant of a solution):

Code: Select all

if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
Adjust the path or the value as you wish. If you're working in the current folder, I believe .\Variables.inc would do. This does produce a UCS-2 LE BOM in Notepad++ in my tests, so all good. Make sure you write things properly in the RunCommand measure, as the quotes might need some escaping (i.e. \"), not sure if in all cases though:

Code: Select all

Program=powershell
Parameter=-command if (!(Test-Path "F:\Wireless\Variables.inc")) {Set-Content -path F:\Wireless\Variables.inc -encoding unicode -value ""}
:jawdrop Perfect solution so far. :jawdrop
Many - many thanks for the help. This seems to be the perfect solution, even if so far I didn't integrate it to the skin. But on a test skin this seems to be working, so if something unforeseen doesn't go on, I'm gonna use this.
Thanks again. :rosegift:
User avatar
Yincognito
Rainmeter Sage
Posts: 4070
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Skin Packager improvement

Post by Yincognito »

balala wrote: January 18th, 2021, 8:32 pm :jawdrop Perfect solution so far. :jawdrop
Many - many thanks for the help. This seems to be the perfect solution, even if so far I didn't integrate it to the skin. But on a test skin this seems to be working, so if something unforeseen doesn't go on, I'm gonna use this.
Thanks again. :rosegift:
No problem - it was my pleasure to help. Good luck with the future development of the actual skin(s). ;-)
User avatar
Brian
Developer
Posts: 2272
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: Skin Packager improvement

Post by Brian »

Sorry for taking so long to respond, I have been a busy with some family medical problems.

When installing an rmskin, the "Variables files" option works like this:
  • If the skin of the same name has already been installed AND the Advanced > Backup Skins is checked, the entire existing skin (the one previously installed, not the new one) is moved to the @Backup folder.
  • For each file in the "Variables files" field, the file must exist in both the rmskin AND the existing skin (now placed in the @Backups folder).
  • If both files exist, then only the variables that exist in both files will be copied from an existing skin to the newly installed skin.
Here is the code:
https://github.com/rainmeter/rainmeter/blob/master/Library/DialogInstall.cpp#L984-L1007

Basically, the actual variable needs to exist in both the old file and new file in order for it to be "saved" when installing a new skin. It is worth noting that the user can select to NOT backup the skins, which will prevent this option from working as well (although I doubt many use this option).

We don't have any plans on changing this, and I am not sure of any compatibility issues this might cause with older skins if we did decide to change (or add) this. But it looks like you have a work around for now, so that will probably be the best solution for now.

-Brian