It is currently May 3rd, 2024, 1:10 pm

Rainmeter, .lua and io.popen (Scanning folder for shortcuts)

Get help with creating, editing & fixing problems with skins
nuskatev
Posts: 4
Joined: November 6th, 2012, 11:44 pm

Rainmeter, .lua and io.popen (Scanning folder for shortcuts)

Post by nuskatev »

Hello, I'm Nuskatev and I've been using Rainmeter for some time now.

With all previous installations, I've used an io.popen function in a .lua script attached to my Rainmeter, this allowed me to scan a folder of my computer, and get back a list like this:

Code: Select all

D:\Games\A Game of Dwarves.lnk
D:\Games\Anno 2070.url
D:\Games\Audiosurf.url
D:\Games\Battlefield 3.lnk
My first obstacle was overcoming the .url and .lnk differences (.lnk being a normal shortcut, and .url being a Steam / browser shortcut) - This however was fixed in .lua

Now, with Rainmeter 2.4 I've reached a rather large problem.

Whenever I call an io.popen function I am met with this error in my error log.

Code: Select all

ERRO (00:09:30.090) Script: Rarity.lua:7: attempt to call field 'popen' (a nil value)
If anyone has any idea how to fix it, that'd be much appreciated. I'll attach a picturs of what I've used it for earlier (Lots of MLP related stuff, so if you don't like ponies, don't click)
There'll also be the snippet of code I used, please, I need your help people! :D

Picture
In particular, look at the games list on the right hand side and the top left corner, these are all automatically generated, and is what I'd like to do again.
Image
Code
Entire initialize() function

Code: Select all

function Initialize()
	gPath = {}
	iPath = {}
	Name = {}
	nCount = 0
	for i in io.popen('DIR D:\Games /B /S'):lines() do
		if string.find(i,"%.url$") or string.find(i,"%lnk$") then
			nCount = nCount +1
			gPath[nCount] = string.gsub(i, [[.lnk]], "")
			Name[nCount] = string.gsub(gPath[nCount], [[D:\Games\]], "")
			Name[nCount] = string.gsub(Name[nCount], [[.url]], "")
			iPath[nCount] = [[E:\Dropbox\Photos\Icons\Convert\59x59\]]..Name[nCount]..[[.png]]
		end
	end
	if nCount <= 39 then
		n=1
		while n<=nCount+1 do
			if n >=27 then
				SKIN:GetMeter("meterImage"..n):SetY(155)
				SKIN:GetMeter("meterImage"..n):SetX(1021+65*(n-27))
			elseif n >=14 then
				SKIN:GetMeter("meterImage"..n):SetY(90)
				SKIN:GetMeter("meterImage"..n):SetX(1021+65*(n-14))
			else
				SKIN:GetMeter("meterImage"..n):SetY(25)
				SKIN:GetMeter("meterImage"..n):SetX(1021+65*n-65)
			end
			SKIN:Bang('!setOption meterImage'..n..' ImageName '..[["""]]..iPath[n]..[["""]])
			SKIN:Bang('!setOption meterImage'..n..' MeterStyle styleImage')
			SKIN:Bang('!setOption meterImage'..n..' LeftMouseUpAction '..[[""""]]..gPath[n]..[[""""]])
			n = n+1
		end
	end
end
To anyone trying to help, thank you, and good luck! :D
nuskatev
Posts: 4
Joined: November 6th, 2012, 11:44 pm

Re: Rainmeter, .lua and io.popen (Scanning folder for shortc

Post by nuskatev »

Alright, after some research, I may have found the cause for this no longer working. It seems that LUA has been updated since the last Rainmeter release, and io.popen is no longer available...

So..

Anyone with any ideas as to how I can get Rainmeter to execute it instead ([cmd.exe /C DIR D:\Games /B /S] ?) and send the value to my LUA script?
nuskatev
Posts: 4
Joined: November 6th, 2012, 11:44 pm

Re: Rainmeter, .lua and io.popen (Scanning folder for shortc

Post by nuskatev »

Through another thread (Executing a command, Having trouble! I have found a solution (Albeit somewhat shabby) that is as follows:

This is added to a meter I'd like to use when updating the database. This is where the .lua script reads its information from.

Code: Select all

MiddleMouseUpAction=[cmd.exe /C DEL D:\Games\Games.txt][cmd.exe /C DIR D:\Games /B /S >> D:\Games\Games.txt]

The .lua script is then editted to use io.lines instead of io.popen so it can read from the .txt file created from the command prompt.

Code: Select all

function Initialize()
	gPath = {}
	iPath = {}
	Name = {}
	nCount = 0
	i = {}
	for i in io.lines([[D:\Games\Games.txt]]) do
		if string.find(i,"%.url$") or string.find(i,"%lnk$") then
			nCount = nCount +1
			gPath[nCount] = string.gsub(i, [[.lnk]], "")
			Name[nCount] = string.gsub(gPath[nCount], [[D:\Games\]], "")
			Name[nCount] = string.gsub(Name[nCount], [[.url]], "")
			iPath[nCount] = [[E:\Dropbox\Photos\Icons\Convert\96x96\]]..Name[nCount]..[[.png]]
		end
	end

	if nCount <= 44 then
		n=1
		while n<=nCount+1 do
			if n<=22 then
				SKIN:Bang('!setOption LeftShortcut'..n..' ImageName '..[["""]]..iPath[n]..[["""]])
				SKIN:Bang('!setOption LeftShortcut'..n..' LeftMouseUpAction '..[[""""]]..gPath[n]..[[""""]])
			else
				m=n-22
				SKIN:Bang('!setOption RightShortcut'..m..' ImageName '..[["""]]..iPath[n]..[["""]])
				SKIN:Bang('!setOption RightShortcut'..m..' LeftMouseUpAction '..[[""""]]..gPath[n]..[[""""]])
			end
			n = n+1
		end
	end
end
Only drawback is the flashing cmd boxes, but I had those with io.popen anyways.

Thank you to everyone. - This forum, and the ability to get off with some anxiety through text, has been quite useful!
User avatar
Zerrick
Posts: 5
Joined: June 21st, 2011, 10:28 am
Location: Belgium

Re: Rainmeter, .lua and io.popen (Scanning folder for shortc

Post by Zerrick »

I had the same issue as you, I used io.popen to search for covers.
I found a solution through this skin (CMD output rainmeter skin) and later this guide: Parsing Output of Command Line Programs.

It's basically your solution but to get rid of the flashing window you call the commands in a .vbs or .js script.

Here's my code stripped of the unrelated statements. I call the script in Lua on update and wait for the output to have been written to the temp file.

Code: Select all

function Initialize()
	sPathTempFile = SELF:GetOption('CoverPathTempFile')
	msFile = SKIN:GetMeasure(SELF:GetOption('FileMeasure'))
	bOpeningTempFile = false
end
function Update()
	if not bOpeningTempFile then
		--Remove previous temp file.
		os.remove(sPathTempFile)
		local sPathToSearchIn = msFile:GetStringValue():match('^(.+)\\') --only get the folders
		-- wscript script.js "Path to temp file" "commands and arguments to run" //e:jscript
		SKIN:Bang('wscript #CURRENTPATH#scriptWhere.js "'..sPathTempFile..
			'" "/'..sPathToSearchIn..'/:*cover.jpg /'..sPathToSearchIn..'/:*front.png" //e:jscript')
		
		local bSuccess, sCoverPath = OpenAndReadFile(sPathTempFile)
		if not bSuccess then
			-- Temp file not yet created. Try opening file on next update.
			bOpeningTempFile = true
		elseif sCoverPath and sCoverPath:len() ~= 0 then
			-- Path found. We can now use it or return it.
		end
	else
		local bSuccess, sCoverPath = OpenAndReadFile(sPathTempFile)
		if bSuccess then
			-- Temp file has been read.
			if sCoverPath and sCoverPath:len() ~= 0 then
				-- Path has been found here.
			end
			bOpeningTempFile = false
			os.remove(sPathTempFile)
			SELF:Disable()
		end
	end
end
function OpenAndReadFile()
	local sCmdLine = ''
	local bSuccess, fOpenedTemp = pcall(function ()
			return io.input(sPathTempFile)
		end)
	if bSuccess then
		sCmdLine = io.read()
		io.close(fOpenedTemp)
	end
	return bSuccess, sCmdLine
end
scriptWhere.js

Code: Select all

var pathTempFile=WScript.Arguments(0)
var arguments=WScript.Arguments(1)
//Replace / with " because WScript would have removed the double quotes.
arguments=arguments.replace(/\//g,'\"')
WindowVisible = 0
WScript.Echo('cmd /C WHERE '+arguments+' > \"'+pathTempFile+'\"')//Test
WScript.CreateObject("WScript.Shell").Run('cmd /C WHERE '+arguments+' > \"'+pathTempFile+'\"',WindowVisible)