It is currently September 23rd, 2020, 9:36 am

Non-terminating Powershell script in OnRefreshAction is not running

Get help with installing and using Rainmeter.
jn_meter
Posts: 59
Joined: December 27th, 2016, 12:04 pm

Non-terminating Powershell script in OnRefreshAction is not running

Post by jn_meter »

Solved.

Dear all

I've a Powershell script that runs in an infinite loop. I am trying to start it when Rainmeter starts or refreshes. but it does not seem to run at all. If I run the script manually in a Powershell terminal, all works as it should. (I would find this easier to debug, were it Linux and Bash . .)

Here are the most relevant parts of the code.

Code: Select all

path_script_dir="C:\Scripts\rainmeter\"

Code: Select all

OnRefreshAction=[!CommandMeasure measure_command_camStatus "Kill"] [!CommandMeasure measure_command_camStatus "Run"]

Code: Select all

[measure_command_camStatus]
Measure=Plugin
Plugin=RunCommand
Program=powershell
Parameter=-NoProfile -NoExit #path_script_dir#checkCam.ps1
State=Hide
Things that did not help:
  • replacing `#path_script_dir#` with a literal string;
  • removing the 'kill' line (which is there to stop multiple instances of the script from running) from OnRefreshAction;
  • removing the 'NoHide' option from the RunCommand;
  • removing, from the RunCommand, the 'NoProfile' or 'NoExit' options.
I note finally that I put an 'echo' in the Powershell script but I don't see that output in the Rainmeter log.

Also, I suppose I should give the Powershell script. So, here it is. (And I use it, er, in conjunction with a Lua script . .).

Code: Select all

$LogEngineLifeCycleEvent=$false;
$LogEngineHealthEvent=$false;
$LogProviderLifeCycleEvent=$false;
$LogProviderHealthEvent=$false;


# ----
# VARS
# ----

$path_drive="R:\"
$path_sub1="Rainmeter\"
$path_sub2="powershell\"
$path_leaf="checkCam.txt"
$path_outputFile="$path_drive$path_sub1$path_sub2$path_leaf"

# echo path_outputFile is $path_outputFile

# ----
# MAIN
# ----

#Import-Module Microsoft.PowerShell.Management

if ( ! ( Test-Path -Path $path_drive -PathType Container ) ) {
	echo "ERROR: drive $path_drive does not exist."
	exit 1
}

while($true) {
	# PATHS

	if ( ! ( Test-Path -Path "$path_drive$path_sub1" -PathType Container ) ) {
		New-Item -Path "$path_drive$path_sub1" -ItemType Directory | Out-Null
		if ( ! ($?) ) {
			echo "ERROR: failed to create $path_drive$path_sub1."
			exit 1
		}
	}

	if ( ! ( Test-Path -Path "$path_drive$path_sub1$path_sub2" -PathType Container ) ) {
		New-Item -Path "$path_drive$path_sub1$path_sub2" -ItemType Directory | Out-Null
		if ( ! ($?) ) {
			echo "ERROR: failed to create $path_drive$path_sub1$path_sub2."
			exit 1
		}
	}

	# GENERATE OUTPUT

	(get-pnpdevice).Where{ $_.Caption -eq 'USB2.0 PC Camera' }.Status | Out-File -FilePath $path_outputFile -Encoding ASCII
		
	# SLEEP

	Start-Sleep -s 10
}

I would appreciate some help! Thanks.

EDITED.
Last edited by eclectic-tech on May 22nd, 2020, 2:00 am, edited 3 times in total.
Reason: Updated Topic Icon to show as solved.
jn_meter
Posts: 59
Joined: December 27th, 2016, 12:04 pm

Re: Non-terminaing Powershell script in OnRefreshAction is not running

Post by jn_meter »

Thanks, but it turned out that the syntax of invoking the powershell script was not quite the problem. The problem was that this does not work, at all:

Code: Select all

OnRefreshAction=[!CommandMeasure measure_command_camStatus "Run"]
Why not? The following does work.

Code: Select all

[measure_startCam_Ps]
Measure=String
UpdateDivider=-1
OnUpdateAction=[!CommandMeasure measure_command_camStatus "Run"]
jn_meter
Posts: 59
Joined: December 27th, 2016, 12:04 pm

Re: Non-terminaing Powershell script in OnRefreshAction is not running

Post by jn_meter »

Here is some information, it can it helps anybody.

One problem is indeed getting Powershell to run reliably from Rainmeter and knowing what syntax to use for that (to use within Rainmeter).

Another problem is one needs to write lua scripts to get Rainmeter to read from a file. It would be much easier were Rainmeter able to do that reading natively. As things stand, I've ended up having to do all of the following. It is the only way I have found to repeatedly get output from Powershell scripts, without repeatedly loading and unloading those scripts. For that loading and unloading causes CPU spikes.

* Have Rainmeter run, when and only when it 'refreshes', several Powershell scripts - scripts that loop continuously in the background and write values to files (files on a ramdisk).
* Have Rainmeter run lua scripts, periodically, to read those files.
* Have Rainmeter have measures and meters to do things with those values.

Here is the Rainmeter skin (which includes a lot of irrelevant stuff, I'm afraid).
Here is one of the Powershell scripts.
Here is one of the Lua scripts.

Those materials will be there (on PasteBin) for one year.
User avatar
Yincognito
Posts: 2584
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Non-terminaing Powershell script in OnRefreshAction is not running

Post by Yincognito »

jn_meter wrote: May 18th, 2020, 2:33 am Dear all

I've a Powershell script that runs in an infinite loop. I am trying to start it when Rainmeter starts or refreshes. but it does not seem to run at all. If I run the script manually in a Powershell terminal, all works as it should. (I would find this easier to debug, were it Linux and Bash . .)

Here are the most relevant parts of the code.
[...]
Also, I suppose I should give the Powershell script. So, here it is. (And I use it, er, in conjunction with a Lua script . .).
[...]
I would appreciate some help! Thanks.
[...]
Well, I don't know about the script being endless or not, but it worked for me: PowerShell and the checkCam.ps1 script were running without exiting as confirmed by Task Manager, the checkCam.txt file was created and had an OK text inside, just as when running the (get-pnpdevice).Where{ $_.Caption -eq 'whatevercameranameyouhave' }.Status command directly from PowerShell.

However:
- you should check if you're allowed to run PS scripts on the computer, google "enable running scripts on windows 10 powershell" for more info (I said "no" out of instinct the first time, but then I had to re-enable it by running Set-ExecutionPolicy RemoteSigned from administrator level PowerShell and choose "yes" just this time)
- I made some small modifications in your original script, like changing the .txt file output path to the same as the .ps1 script path (i.e. C:\Scripts\Rainmeter\) since I don't have an R: drive
- another modification I had to make was to change the camera to my own and to change Caption to FriendlyName (the latter is, I suppose, optional, since it appears to work with Caption as well)

Skin:

Code: Select all

[Variables]
path_script_dir="C:\Scripts\rainmeter\"

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255
OnRefreshAction=[!CommandMeasure measure_command_camStatus "Kill"] [!CommandMeasure measure_command_camStatus "Run"]

---Measures---

[measure_command_camStatus]
Measure=Plugin
Plugin=RunCommand
Program=powershell
Parameter=-NoProfile -NoExit #path_script_dir#checkCam.ps1
State=Hide

---Meters---

[MeterTest]
Meter=STRING
X=0
Y=0
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
MeasureName=MeasureTest
Text="Test = %1"
DynamicVariables=1
Script:

Code: Select all

$LogEngineLifeCycleEvent=$false;
$LogEngineHealthEvent=$false;
$LogProviderLifeCycleEvent=$false;
$LogProviderHealthEvent=$false;


# ----
# VARS
# ----

$path_drive="C:\"
$path_sub1="Scripts\"
$path_sub2="Rainmeter\"
$path_leaf="checkCam.txt"
$path_outputFile="$path_drive$path_sub1$path_sub2$path_leaf"

# echo path_outputFile is $path_outputFile

# ----
# MAIN
# ----

#Import-Module Microsoft.PowerShell.Management

if ( ! ( Test-Path -Path $path_drive -PathType Container ) ) {
	echo "ERROR: drive $path_drive does not exist."
	exit 1
}

while($true) {
	# PATHS

	if ( ! ( Test-Path -Path "$path_drive$path_sub1" -PathType Container ) ) {
		New-Item -Path "$path_drive$path_sub1" -ItemType Directory | Out-Null
		if ( ! ($?) ) {
			echo "ERROR: failed to create $path_drive$path_sub1."
			exit 1
		}
	}

	if ( ! ( Test-Path -Path "$path_drive$path_sub1$path_sub2" -PathType Container ) ) {
		New-Item -Path "$path_drive$path_sub1$path_sub2" -ItemType Directory | Out-Null
		if ( ! ($?) ) {
			echo "ERROR: failed to create $path_drive$path_sub1$path_sub2."
			exit 1
		}
	}

	# GENERATE OUTPUT

	(get-pnpdevice).Where{ $_.FriendlyName -eq 'TOSHIBA Web Camera - HD' }.Status | Out-File -FilePath $path_outputFile -Encoding ASCII
		
	# SLEEP

	Start-Sleep -s 10
}
Result (C:\Scripts\Rainmeter\checkCam.txt):

Code: Select all

OK
That being said, I'm not sure I understand the need for such a complicated process involving PS, Lua and all that just to periodically read from files created by another process (PowerShell in this case). Rainmeter can "natively" read and write to files, but you have to consider a few things beforehand:
- reading from files is easy, no major drawback here, just use WebParser and regex to parse a local file
- writing to a file is where a few minor "inconvenients" are present, since while writing is again easily done using the !WriteKeyValue bang, the file must exist, must be located in certain paths for the process to work, (possibly, not sure about this one, the extension could be unrestricted after all) be an .ini or an .inc file, and the result will have a .ini syntax of [Section]...Key=Value (the latter can be to some extent avoided by using a "fake" or commented Section Name and Key and putting all the contents in the Value "field" - this method also has some drawbacks if you want to replace the same contents later on, since line feeds separate various the elements in an .ini formatted file, but if you don't need to replace the same things afterwards or you're OK with an .ini formatted file, it works fine)
jn_meter
Posts: 59
Joined: December 27th, 2016, 12:04 pm

Re: Non-terminating Powershell script in OnRefreshAction is not running

Post by jn_meter »

Well, thank you for all that! There is some interesting stuff there. For one thing, I will look into replacing my Lua scripts - which read files - with native Rainmeter functionality (know that I know that such functionality exists).

However, I did try to mark the thread as solved (and I've done so more clearly now). I mean: I do have everything working. (Still, the scripts I posted were a bit rough - I've tidied them up).
User avatar
Yincognito
Posts: 2584
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Non-terminating Powershell script in OnRefreshAction is not running

Post by Yincognito »

jn_meter wrote: May 21st, 2020, 4:29 pmHowever, I did try to mark the thread as solved (and I've done so more clearly now). I mean: I do have everything working. (Still, the scripts I posted were a bit rough - I've tidied them up).
Oh, I see - I didn't know you got it working in the meantime. Well done! ;-)
And yeah, the file reading part is easy with Rainmeter. The writing file part has those minor (or not?) inconvenients.
jn_meter
Posts: 59
Joined: December 27th, 2016, 12:04 pm

Re: Non-terminating Powershell script in OnRefreshAction is not running

Post by jn_meter »

Thanks.

Actually, I think I'll stick with the Lua scripts for the file reading - unless the native function is much faster. For, (1) I know Lua better than Rainmeter, (2) Lua is a more procedural language than Rainmeter, so using Lua make it easier (for me anyway) to see what will happen when, (3) Lua is a more flexible languate than Rainmeter, and so if I need to build in more complexity to my file reading, then I can do fairly easily.
User avatar
Yincognito
Posts: 2584
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Non-terminating Powershell script in OnRefreshAction is not running

Post by Yincognito »

jn_meter wrote: May 21st, 2020, 4:48 pm Thanks.

Actually, I think I'll stick with the Lua scripts for the file reading - unless the native function is much faster. For, (1) I know Lua better than Rainmeter, (2) Lua is a more procedural language than Rainmeter, so using Lua make it easier (for me anyway) to see what will happen when, (3) Lua is a more flexible languate than Rainmeter, and so if I need to build in more complexity to my file reading, then I can do fairly easily.
Yes, that's fine. And yes, Lua is faster than Rainmeter at file reading / writing, especially if you have loops / recursion involved.
User avatar
jsmorley
Developer
Posts: 21386
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Non-terminating Powershell script in OnRefreshAction is not running

Post by jsmorley »

jn_meter wrote: May 21st, 2020, 4:48 pm Thanks.

Actually, I think I'll stick with the Lua scripts for the file reading - unless the native function is much faster. For, (1) I know Lua better than Rainmeter, (2) Lua is a more procedural language than Rainmeter, so using Lua make it easier (for me anyway) to see what will happen when, (3) Lua is a more flexible languate than Rainmeter, and so if I need to build in more complexity to my file reading, then I can do fairly easily.
Just be careful about how you handle Unicode UTF-16 file encoding, as Lua won't deal with it particularly well. You can "write" UTF-16 by creating a brand-new file and preceding any text you write with the BOM for UTF-16 LE, which is Hex FF FE, Decimal 255 254, or Character ÿþ, but be aware that you simply cannot "read" UTF-16 with Lua. Lua is perfectly fine with reading and writing either UTF-8 with or without BOM, or ANSI (ASCII / Extended ASCII).

https://docs.rainmeter.net/tips/unicode-in-rainmeter/

To read UTF-16 with Lua, you need to do a bit of a shell-game, where you use WebParser in Rainmeter proper to read the file, using CodePage=1200 on the parent WebParser measure, and then get the value of that measure in Lua to take action on / with it.

One last bit of advice is that when you do deal with Unicode in Lua, no matter UTF-8 that you "read" from a file, or UTF-16 that you manually paste in or read from a WebParser measure, Lua will have measurement issues with any Unicode that is "multi-byte" characters, like Chinese or Japanese. Lua is pretty old-school, and only understands single-byte characters. It can certainly read and display and search and do matches and replacements on multi-byte characters, but it can't "measure" them properly. Stay away from string.len() or any other functions that are dependent on numeric "position" in the string value. I think this will mostly come up if you use "pictograph" languages like Chinese or Japanese or Koren and such, and probably with a lot of Unicode "symbol" characters.
jn_meter
Posts: 59
Joined: December 27th, 2016, 12:04 pm

Re: Non-terminating Powershell script in OnRefreshAction is not running

Post by jn_meter »

Blimey, computers - Windows especially, as against my beloved Linux - are fiddly, aren't they? [EDIT: But I use Lua on Linux too . .] I did encounter a version of the problem, in that Powershell was outputting text that Lua (I think it was Lua rather than Rainmeter itself) was garbling, even though the text comprised simple English words. I solved the problem by making the lines in Powershell that wrote to files have this format:

Code: Select all

<command that generates some output> | Out-File -FilePath $path_outputFile -Encoding ASCII
i.e. by specifying an ASCII 'encoding' (which isn't the Powershell default for the 'Out-File' command, I think).

I am sure that the post to which I reply will be a useful resource for people.