Why is this lua script unable to open a Windows subdirectory? - windows

I'm trying to determine if one of several directories are present from within a lua script. It works on OSX, but not on Windows (linux is currently untested, but I expect that one to work). When the following code runs, I get an error:
failed with this C:\Program Files (x86)\VideoLAN\VLC\lua\playlist\: No such file or directory
I can confirm that that directory exists. I've escaped the slashes, I'm not sure what else could be the issue.
local oses = { "/Applications/VLC.app/Contents/MacOS/share/lua/playlist/"; "C:\\Program Files\\VideoLAN\\VLC\\lua\\playlist\\"; "C:\\Program Files (x86)\\VideoLAN\\VLC\\lua\\playlist\\"; "/usr/lib/vlc/lua/playlist" }
-- Determine which OS this is (and where to find share/lua).
local f,err = io.open( oses[1], "r")
if not err then
opsys = "OSX"
scriptpath = oses[1] .. script
f:close()
else
f,err = io.open( oses[2], "r")
if not err then
opsys = "Win32"
scriptpath = oses[2] .. script
f:close()
else
f,err = io.open( oses[3], "r")
vlc.msg.dbg( dhead .. 'failed with this ' .. err .. dtail )
if not err then
opsys = "Win64"
scriptpath = oses[3] .. script
f:close()
else
f,err = io.open( oses[4], "r")
if not err then
opsys = "Linux/Unix"
scriptpath = oses[4] .. script
f:close()
else
return false
end
end
end
end

The file "C:\Program Files\VideoLAN\VLC\lua\playlist\" does not exist. If you were to remove the trailing slash, you'd be trying to open a directory and probably get a permissions error. It's not going to work either way. If you're going to use this method of determining OS, you should be trying to open files.
For instance, build your script path, try to open that file, and use that to determine pass/fail.
Side note, the structure of your code could be vastly improved. Any time you have a bunch of duplicate code that differs by an index, you should be using a loop. For instance, we can replace your code with this:
local oses = {
["OSX"] = "/Applications/VLC.app/Contents/MacOS/share/lua/playlist/",
["Win32"] = "C:\\Program Files\\VideoLAN\\VLC\\lua\\playlist\\",
["Win64"] = "C:\\Program Files (x86)\\VideoLAN\\VLC\\lua\\playlist\\",
["Linux/Unix"] = "/usr/lib/vlc/lua/playlist",
}
for osname, directory in pairs(oses) do
local scriptpath = directory..script
local f,err = io.open( scriptpath, "r")
if not err then
f:close()
return scriptpath, osname
end
end

Related

VLC rename current item with lua script

I am using this script as a template to rename a file in VLC: https://github.com/surrim/vlc-delete/
The Script works as intended.
My code looks like this:
function descriptor()
return {
title = "VLC Rename";
version = "0.1";
author = "I";
shortdesc = "Rename current file";
description = [[
<h1>vlc-rename</h1>"
When you're playing a file, use VLC Rename
to rename the current file]];
}
end
function removeItem()
local id = vlc.playlist.current()
vlc.playlist.delete(id)
vlc.playlist.gotoitem(id + 1)
vlc.deactivate()
end
function activate()
local item = vlc.input.item()
local uri = item:uri()
oldFile = vlc.strings.decode_uri(string.gsub(uri, "^file:///", ""))
d = vlc.dialog( "Rename Dialog" )
d:add_label("Filename")
w = d:add_text_input(oldFile, 1, 5,200 ,30)
d:add_button("OK", click_ok)
d:show()
end
function click_ok()
local newFile = w:get_text()
vlc.msg.info("[vlc-rename] renaming: " .. oldFile .. " with " .. newFile)
if newFile ~= oldFile then
removeItem()
retval, err = os.rename(oldFile,newFile)
vlc.msg.info("[vlc-rename] end rename")
if (retval == nil) then
vlc.msg.err("[vlc-rename] fail: " .. err)
end
end
d:delete()
vlc.deactivate()
end
function deactivate()
vlc.deactivate()
end
function close()
deactivate()
end
function meta_changed()
end
This code outputs an error from the os.rename() function:
lua error: [vlc-rename] fail: [my filename] Permission denied
Regardless of elevation level.
I am using windows 10 64bit and VLC 3.03.
Since this is my first lua script I welcome any input.
I might be wrong, but maybe the file you are trying to rename is already opened elsewhere or by VLC (you said you want to rename the "current file").

Check if paths from file are physically located in hard drive

Hello I have a file named files.txt in that file there are paths to files for example:
/home/ojom/123.jpg
/home/ojom/oaksdokwijeqijwqe.jpg
There is million of those paths in this file I need to see if the files in that file are physically located (exists) on my hard drive (if they don't write those paths to another file) how do I do that? What can I use?
You could parse that file using PHP and then go through the results and check them with file_exists.
The example below works if every file path is on a new line.
<?php
$files = array();
$handle = fopen("files.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
if(!file_exits($line)) {
continue; // file does not exist, skip
} else {
$files[] = $line;
}
}
} else {
die('Error opening the file');
}
fclose($handle);
echo "These files exist:";
echo "<pre>" . print_r($files, true) . "</pre>"; // prints them as an array
You could also use the array for further processing.
Here is the Python solution:
import os.path
files = 'c:\\test\\files.txt'
output = 'c:\\test\\filesNotExist.txt'
with open(files) as f:
for file in f:
if not os.path.isfile(file):
f = open(output, 'w')
f.write(file)
f.close()
f.close()
This script scans your text file and writes list of non-existed files to the output text file.

Navigate Shell command not working when the path includes an hash

I'm having problem using the Navigate Shell command when the path include an # sign.
; this will create 2 folders at the root of your C: drive
myPath1 := "C:\delete_me\"
myPath2 := "C:\delete#me\"
if !FileExist(myPath1)
FileCreateDir, %myPath1%
if !FileExist(myPath2)
FileCreateDir, %myPath2%
; make an Explorer active and press Alt-1 and Alt-2
return
!1::
strWinId := WinExist("A")
TrayTip, %myPath1%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
if (pExp.hwnd = strWinId)
try pExp.Navigate(myPath1)
return
!2::
strWinId := WinExist("A")
TrayTip, %myPath2%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
if (pExp.hwnd = strWinId)
try pExp.Navigate(myPath2)
return
Alt-1 works well. But, with Alt-2, the Navigate command returns "file:///C:/delete#me/ » not found.".
If there is no "/" after the "#" (eg myPath := "C:\delete#me"), it works. But this cannot be a solution because the destination path can be deeper in a subfolder (eg. "C:\delete#me\xyz").
I tried to encode the "#", replacing it with "%23", without success. Found nothing on the web or MSDN about that. Any idea?
[keywords: haskmark, hashtag, number sign or pound]
I have what looks to be a working solution for this, which I've also posted here:
4 options to change the current folder in Windows Explorer - Page 3 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=526&p=153676#p153676
;links:
;Explorer Windows Manipulations - Page 5 - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/19039-explorer-windows-manipulations/page-5#entry297581
;Navigate2 Method (IWebBrowser2)
;https://msdn.microsoft.com/en-us/library/aa752134(v=vs.85).aspx
;4 options to change the current folder in Windows Explorer - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=526
;windows - Navigate Shell command not working when the path includes an hash - Stack Overflow
;https://stackoverflow.com/questions/22868546/navigate-shell-command-not-working-when-the-path-includes-an-hash
;an AutoHotkey v1.1 script
;note: will create folder: %A_Desktop%\abc#def\abc#def
;q:: ;explorer - navigate to folder (tested on Windows 7)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, % "ahk_id " hWnd
if !(vWinClass = "CabinetWClass") && !(vWinClass = "ExploreWClass")
return
vDir = %A_Desktop%\abc#def\abc#def
;vDir = %A_Desktop%\abc def\abc def
if !FileExist(vDir)
FileCreateDir, % vDir
DllCall("shell32\SHParseDisplayName", WStr,vDir, Ptr,0, PtrP,vPIDL, UInt,0, Ptr,0)
for oWin in ComObjCreate("Shell.Application").Windows
if (oWin.HWND = hWnd)
{
if !InStr(vDir, "#")
oWin.Navigate(vDir)
else
{
VarSetCapacity(SAFEARRAY, A_PtrSize=8?32:24, 0)
NumPut(1, SAFEARRAY, 0, "UShort")
NumPut(1, SAFEARRAY, 4, "UShort")
NumPut(vPIDL, SAFEARRAY, A_PtrSize=8?16:12, "Ptr")
NumPut(DllCall("shell32\ILGetSize", Ptr,vPIDL, UInt), SAFEARRAY, A_PtrSize=8?24:16, "Int")
oWin.Navigate2(ComObject(0x2011,&SAFEARRAY))
DllCall("shell32\ILFree", Ptr,vPIDL)
}
break
}
return
If you want to open a new window, there's no need for COM or unreliable workarounds: just run the folder.
Run C:\delete#me
If you want to open the path in an existing window which is already active, the simplest and most effective workaround is this:
SendInput {F4}{Esc}{Raw}C:\delete#me`n
So in the context of your script, you could use the following function to work around the # when it is present:
Navigate(pExp, myPath2)
;...
Navigate(Exp, Path)
{
if RegExMatch(Path, "#.*\\")
SendInput {F4}{Esc}{Raw}%Path%`n
else
Exp.Navigate(Path)
}
Unfortunately, there does not seem to be a solution to this. Shell.Application Navigate command fails if the path includes a hash (# as in C:\C#Projects).
Using AutoHotkey, the workaround would be to rely on the "second best" approach as identified by the tests in this thread: http://ahkscript.org/boards/viewtopic.php?f=5&t=526.
run, Explorer.exe
Sleep, 500
strFolder := A_ScriptDir
Send, {F4}{Esc}
Sleep, 500
ControlSetText, Edit1, C:\delete#me, A
ControlSend, Edit1, {Enter}, A
When I saw that Navigate couldn't handle hash, I was shocked,
but sure enough I replicated the error.
I thought I'd try the short form path just in case. It works!
if vDir contains #
Loop, %vDir%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
vDir := A_LoopFileShortPath
The following approach doesn't require a visible address bar, or SendInput,
also the previous navigation history is maintained.
In the worst-case scenario of a hash in the short-form path of the dir above the target dir,
a go-between folder is used which is navigated to.
A link is created there, invoked, and deleted.
Below, the workaround code is indented, to separate it from the standard code.
A hotkey of ctrl+q, when an Explorer window is active, launches the script.
-
^q:: ;explorer - navigate to directory (use go-between dir if short-form path of dir above target contains #)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass not in CabinetWClass,ExploreWClass
Return
vDir2 = %A_Desktop%\Go-Between ;go-between dir
vDir3 = C:\delete#me ;target dir
if (SubStr(vDir3, 1-1) = "\")
vDir3 := SubStr(vDir3, 1, -1)
if !InStr(FileExist(vDir3), "D")
Return
vPathLnk := ""
if vDir3 contains #
Loop, %vDir3%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
vDir3 := A_LoopFileShortPath
;vDir4 is the short-form path of the dir above the target
;paths of problem target dirs are of the form: *#*\*
;where there is at least one hash with a backslash to its right
SplitPath, vDir3, , vDir4
if vDir4 contains #
{
if !InStr(FileExist(vDir2), "D")
FileCreateDir, %vDir2%
if !InStr(FileExist(vDir2), "D")
{
MsgBox error`, go-between dir not found:`r`n%vDir2%
Return
}
vNameLnk = Go-Between.lnk
vPathLnk = %vDir2%\%vNameLnk%
FileCreateShortcut, %vDir3%, %vPathLnk%
}
for oWin in ComObjCreate("Shell.Application").Windows
if (hWnd = oWin.Hwnd)
{
vDir1 := oWin.Document.Folder.Self.Path
if (vDir1 = vDir3)
break
if vDir3 contains #
{
if !(vDir1 = vDir2)
oWin.Navigate(vDir2)
while !(oWin.ReadyState = 4)
Sleep 10
oItem := oWin.Document.Folder.Items.Item(vNameLnk)
oItem.InvokeVerbEx("open")
break
}
oWin.Navigate(vDir3)
break
}
oWin := ""
if !(vPathLnk = "")
FileRecycle, %vPathLnk% ;send to recycle bin
;if !(vPathLnk = "")
;FileDelete, %vPathLnk% ;delete
Return

Script Works on Win 7, Not on Server 2003

I have a script that is rather simple, it boots up WinSCP and checks the directory for a file that starts with "TSA". If the file exists, it exits, if it does not exist, it transfers over a new file.
Its up and running on my Windows 7 machine, that is where i created it - but when i transfer it over to my server [windows server 2003] it never finds the file.
My script:
var FILEPATH = "../zfinance/TSA";
// Session to connect to
var SESSION = "someplace#somewhere.com";
// Path to winscp.com
var WINSCP = "c:\\program files\\winscp\\winscp.com";
var filesys = WScript.CreateObject("Scripting.FileSystemObject");
var shell = WScript.CreateObject("WScript.Shell");
var logfilepath = filesys.GetSpecialFolder(2) + "\\" + filesys.GetTempName() + ".xml";
var p = FILEPATH.lastIndexOf('/');
var path = FILEPATH.substring(0, p);
var filename = FILEPATH.substring(p + 1);
var exec;
// run winscp to check for file existence
exec = shell.Exec("\"" + WINSCP + "\" /log=\"" + logfilepath + "\"");
exec.StdIn.Write(
"option batch abort\n" +
"open \"" + SESSION + "\"\n" +
"ls \"" + path + "\"\n" +
"exit\n");
// wait until the script finishes
while (exec.Status == 0)
{
WScript.Sleep(100);
WScript.Echo(exec.StdOut.ReadAll());
}
if (exec.ExitCode != 0)
{
WScript.Echo("Error checking for file existence");
WScript.Quit(1);
}
// look for log file
var logfile = filesys.GetFile(logfilepath);
if (logfile == null)
{
WScript.Echo("Cannot find log file");
WScript.Quit(1);
}
// parse XML log file
var doc = new ActiveXObject("MSXML2.DOMDocument");
doc.async = false;
doc.load(logfilepath);
doc.setProperty("SelectionNamespaces",
"xmlns:w='http://winscp.net/schema/session/1.0'");
doc.setProperty("SelectionLanguage", "XPath");
var nodes = doc.selectNodes("//w:file/w:filename[starts-with(#value, '" + filename + "')]");
if (nodes.length > 0)
{
WScript.Echo("File found");
WScript.Quit(0);
}
else
{
WScript.Echo("File not found");
WScript.Quit(1);
}
After much investigation, i think i've found the piece of code that does not function properly:
// parse XML log file
var doc = new ActiveXObject("MSXML2.DOMDocument.6.0");
doc.async = false;
doc.load(logfilepath);
doc.setProperty("SelectionNamespaces",
"xmlns:w='http://winscp.net/schema/session/1.0'");
The only problem is, i have no idea why. The log file at this point should be written over with the xml code, but this does not happen.
Thanks in advance for any help.
And the answer is........... WinSCP on Windows Server 2003 was WAY out of date. So out of date that the log was completely different from one version to the next. Updated and VIOLA! Problem solved. Thanks for your help.
Maybe you need to install MSXML2.DOMDocument.6.0
http://msdn.microsoft.com/en-us/library/windows/desktop/cc507436%28v=vs.85%29.aspx
If you open up regedit and look for "MSXML2.DOMDocument.6.0" does it find it? If so maybe security settings for the script need to be set in order to be able to create an activeX object.
What can you see when you put some stuff in try catch?
try{
//stuff
}catch(e){
WScript.Echo(e.message);
}

Ruby file locking when deploying Windows service

I'm deploying a Windows service with a Ruby script. After copying files to the server using FileUtils.cp, I run sc \\MYSERVER start MyService via Ruby's cmd syntax. This command returns the following error for each of 20 consecutive attempts, at five second intervals:
[SC] StartService FAILED 32:
The process cannot access the file because it is being used by another process.
If I run the command manually immediately after my Ruby script ends, it works fine:
SERVICE_NAME: MyService
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
PID : 21736
FLAGS :
Is FileUtils.cp possibly putting a lock on the copied EXE? If not, what else in my script could possibly be holding this lock?
Here's pretty much what my script looks like, without all the automatic retry code and configuration:
srcRoot = Pathname.new 'c:\\MyService'
destRoot = Pathname.new '\\\\MYSERVER\\services\\MyService'
destRoot.each_entry() {|item|
if not %w(. ..).include?( item.to_s )
FileUtils.rm_r destRoot.to_s + "\\" + item.to_s, :force => true
end
}
destRoot.mkdir unless destRoot.exist?
for dir in %w(Release)
copy(src_root + dir + ".", destRoot) { destRoot + dir }
end
`sc \\\\MYSERVER start MyService`
Here's the copy function, which recursively copies directories and files:
# recursively copies the given source file or directory to the given destination directory.
def copy( src, destDir )
src = Pathname.new src
destDir = Pathname.new destDir
destDir.mkdir unless destDir.exist?
exclusions = %w(. .. .svn _svn Thumbs.db)
for item in Dir.glob( src + "*" )
itemPath = Pathname.new item
if not %w(. .. .svn _svn Thumbs.db).include?( itemPath.basename.to_s )
if itemPath.directory?
copy( itemPath, destDir + itemPath.basename ) {destDir + itemPath.basename}
elsif exclusions.select {|k,v| extension? k}.select {|k,v| item.include? k}.empty?
begin
FileUtils.cp( itemPath, destDir, {:verbose => true, :preserve => true} )
rescue
puts "Warning! " + $!
end
end
end
end
end
I found the issue. The MyService.exe.config file was being copied out in a separate method, which did some manipulation of the source file content before creating a new file on the server. The new file was not being closed, so attempting to start the service failed when it couldn't get a lock on the config file.

Resources