I am trying to create an XML file that represents the hierarchical directory structure with an unknown amount of nested directories and files. This question relates to a previous one asked by myself, How to loop through nested directories in Foxpro given the initial start directory, so the code I have so far (see below) is based on the structure from the answer here.
*********************************
**** Variable initialization ****
*********************************
set asserts on
set date ymd
public loXml as MSXML2.DOMDocument60
public loRoot as MSXML2.IXMLDOMElement
public loNode as MSXML2.IXMLDOMElement
public loFile as MSXML2.IXMLDOMElement
public loFolder as MSXML2.IXMLDOMElement
public loSubFolder as MSXML2.IXMLDOMElement
public lcRootDir as String
public lcManifestNS as String
lcRootDir = "C:\LoopTest" && user defined root directory
lcManifestNS = "http://www.randomnamespace.com/ServerManifest/1.1" && namespace which all elements int his document reside
***********************************
**** Creating the XML Document ****
***********************************
loXml = createobject("MSXML2.DOMDocument.6.0")
loRoot = loXml.createNode("Element", "au:Manifest", lcManifestNS) && root element
loRoot.setAttribute("Path", lcRootDir) && path attrubute of root element
GetFilesRecursively(lcRootDir) && builds all folder and file child nodes under the root element
loXml.appendChild(loRoot) && append everything within the root node to the document
*********************
** same xml output **
*********************
loXml.save('C:\results\ex2_manifest_test.xml') && save the xml file to desired location
***************
** Functions **
***************
procedure getfilesrecursively(tcfolder)
assert ( vartype(m.tcfolder) = 'C' )
local lnfile, lafiles[1], lcfileorfolder, datemod && create local variables
for lnfile = 1 to adir(lafiles, addbs(m.tcfolder) + '*', 'd') && loop that will go through all direct items within initial directory
lcfileorfolder = lower(lafiles[m.lnfile, 1]) && this variable is the name of the item inside directory
if empty( strtran(m.lcfileorfolder,'.') ) && some items have names which are just . or .. etc, so ignore these items by restarting the loop
loop
endif
datemod = strtran(dtoc(lafiles[lnfile, 3]), '/', '-') + "T" + lafiles[lnfile, 4] && creating the datetime last modified value
if directory( addbs(m.tcfolder)+m.lcfileorfolder, 1 ) && if there is a subdirectory, re-run the main loop with updated file path
loFolder = loRoot.appendChild(loXml.createNode("Element", "au:Folder", lcManifestNS)) && folder node under root node
loFolder.setAttribute("Name", lcfileorfolder) && attrubutes for folder node
loFolder.setAttribute("Date", datemod)
getfilesrecursively(addbs(m.tcfolder)+m.lcfileorfolder)
else && if no further subdirectory, then insert the item into table
loFile = loFolder.appendChild(loXml.createNode("Element", "au:File", lcManifestNS)) && file node under folder node
loFile.setAttribute("Name", lcfileorfolder) && attributes for file node
loFile.setAttribute("Date", datemod)
endif
endfor
endproc
The main problem I am running into with this code is that all the folder directories are getting put under the root node and are not nesting properly. I understand why, but I do not clearly see how I can change this. Would it be to essentially create a new node every iteration and then append to that? I am just getting used to the syntax around FoxPro XML so some help fixing this issue would be much appreciated. In addition, it seems that any files under the root directory get put inside one of the nested directories in the XML output. You can probably see why as per my code. So ultimately, I am just looking to correct these things to get the XML output nodes to be properly nested. Maybe there is a different approach at solving this, so feel free to answer this question with an entirely new code outline if you wish.
You could do it using ADIR() as follows (please read comments following code):
Local lcOutputFile, lcRoot
lcOutputFile = 'C:\temp\nestedDirs.xml'
lcRoot = Home()
GetTreeXML(m.lcRoot, m.lcOutputFile)
Procedure GetTreeXML(tcRootPath, tcOutput)
Local lcXML
Set Textmerge On To (m.tcOutput) Noshow
\<au:Manifest xmlns:au="http://www.randomnamespace.com/ServerManifest/1.1" Path="<< ADDBS(m.tcRootPath) >>">
GetTree(m.tcRootPath,'myDirectories',0)
*!* Select * From myDirectories &&ORDER BY Filepath
*!* Use In 'myDirectories'
\</au:Manifest>
Set Textmerge Off
Set Textmerge To
Return m.lcXML
Endproc
Procedure GetTree(tcPath, tcCursorName, tnLevel)
Local lcCurDir, ix, lcPath
Local Array laDirs[1]
lcCurDir = Addbs(m.tcPath)
If m.tnLevel = 0
Create Cursor (m.tcCursorName) (FilePath c(250), Level i)
Endif
Insert Into (m.tcCursorName) (FilePath,Level) Values (m.lcCurDir, m.tnLevel)
For ix = 1 To Adir(laDirs,m.lcCurDir+"*.*","DHS")
lcPath = m.lcCurDir+laDirs[m.ix,1]
If laDirs[m.ix,1]#"." And "D"$laDirs[m.ix,5]
GetTree(m.lcPath, m.tcCursorName, m.tnLevel+1)
Else
If laDirs[m.ix,1] != '..'
ProcessPath( m.lcPath, m.tnLevel, laDirs[m.ix,3], laDirs[m.ix, 4] )
Endif
Endif
Endfor
\<< SPACE(2 * m.tnLevel) >></au:Folder>
Endproc
Procedure ProcessPath(tcPath, tnLevel, tdFileDate, tcFileTime)
Local lcName, lcDate
lcDate = Ttoc( Cast(m.tdFileDate As Datetime) + (Ctot(m.tcFileTime)-Ctot('0')), 3)
If Right(m.tcPath,2) == '\.' && Directory
If m.tnLevel > 0 && Skip root
lcName = Justfname(Left(m.tcPath, Len(m.tcPath)-2))
\<< SPACE(2 * m.tnLevel) >><au:Folder Name="<< m.lcName >>" Date="<< m.lcDate >>">
Endif
Else
lcName = Justfname(m.tcPath)
\<< SPACE(2 * (m.tnLevel+1)) >><au:File Name="<< m.lcName >>" Date="<< m.lcDate >>"/>
Endif
Endproc
I'am not sure about the resulting XML. I followed the format of yours. To me it looks a liitle awkward but if that is the format of your manifest then it is fine (I couldn't browse the schema).
Unrelated, in your code there were variables declared as public, please forget that there is a 'public' in VFP. Almost all of us use it only for the specific 'oApp' object created at the start of an application if any. Believe me it is dangerous to use.
Note: VFP ships a DLL called Filer.dll. It contains an activex 'Filer.FileUtil'. It can collect folder and files with some filters applied (has more than simple *.*' file skeleton filter). And it returns the results with original casing, unlike adir() result which uppercases all. Also, you can get file creation, modification and last access times.
Another one is Scripting.FileSystemObject. However, due to security it might not be installed.
If Adir() is fine for you then it is simple and fast.
EDIT: I later noticed above code would add an extra au:Folder at the end plus it wouldn't handle characters that are not allowed in XML. DOM processing would take care of both. So here is the version with DOM:
Local lcOutputFile, lcRoot
lcOutputFile = 'C:\temp\nestedDirs.xml'
lcRoot = Home()
GetTreeXML(m.lcRoot, m.lcOutputFile)
Procedure GetTreeXML(tcRootPath, tcOutput)
Local loXML As "MSXML2.DOMDocument.6.0", loRoot As "MSXML2.IXMLDOMElement"
loXML = Createobject("MSXML2.DOMDocument.6.0")
loRoot = m.loXML.createNode("Element", "au:Manifest", "http://www.randomnamespace.com/ServerManifest/1.1")
loRoot.setAttribute("Path", m.tcRootPath)
GetTree(m.tcRootPath,'myDirectories',0, m.loXML, m.loRoot)
m.loXML.appendChild(m.loRoot)
m.loXML.Save(m.tcOutput)
Endproc
Procedure GetTree(tcPath, tcCursorName, tnLevel, toDOM, toParent)
Local lcCurDir, ix, lcPath, lcName, lcDate, loElement
Local Array laDirs[1]
lcCurDir = Addbs(m.tcPath)
For ix = 1 To Adir(laDirs,m.lcCurDir+"*.*","DHS")
lcName = laDirs[m.ix,1]
lcDate = Ttoc( Cast(laDirs[m.ix,3] As Datetime) + (Ctot(laDirs[m.ix,4])-Ctot('0')), 3)
If laDirs[m.ix,1]#"." And "D"$laDirs[m.ix,5]
lcPath = m.lcCurDir + laDirs[m.ix,1]
loElement = m.toDOM.createElement("au:Folder")
m.loElement.setAttribute("Name", m.lcName)
m.loElement.setAttribute("Date", m.lcDate)
m.toParent.appendChild(m.loElement)
GetTree(m.lcPath, m.tcCursorName, m.tnLevel+1, m.toDOM, m.loElement)
Else
If laDirs[m.ix,1] != '.' And laDirs[m.ix,1] != '..'
loElement = m.toDOM.createElement("au:File")
m.loElement.setAttribute("Name", m.lcName)
m.loElement.setAttribute("Date", m.lcDate)
m.toParent.appendChild(m.loElement)
Endif
Endif
Endfor
Endproc
As I stated in Q-title, I am trying to utilize an existing VLC extension developed in LUA programming language.
The Lua extension can be referred from here, when I correctly place this extension in %ProgramFiles%\VideoLAN\VLC\lua\extensions path and then open any video/audio file and run it and then when I select View > Remove current file from playlist and disk option, it closes the currently playing media file & throws this error: lua info: [vlc-delete] error: File does not exist.
Not sure but I suspect this is due to Windows quotes issue when FileName and/or FilePath contains spaces in them. And also from the error, it seems that io.popen("if exist " .. file .. " (echo 1)") : read "*l" == "1" isn't reliable for correctly detecting whether file actually exists or not.
I am relatively new to Lua programming, so can anyone assist about any better methods for checking whether file exists or not that works in latest VLC versions like 3.x+(cause I am using VLC 3.0.17.4 64Bit in Windows 10/11 64Bit), or just assist fix this mentioned issue ?
Note that when the script calls fileExists method, it does takes care of quotes properly: if not fileExists("\"" .. file .. "\"") then return nil, "File does not exist" end
After hours of troubleshooting, I was able to fix the issue, which was due to the way the quoted(space-containing) file path was passed to another function and the Lua library method of os.remove not working on the passed parameter.
So I just had an idea, I am mainly using Windows OS only, then why not convert the script to rely on Windows OS core(batch/cmd) functions only and do the safe checking of whether file exists and then delete with those core Windows functions too.
And so I just did that and got the plugin to actually check whether the file exists and delete the file, if it does then delete it. Here's the working code:
-- Copy this file to %ProgramFiles%\VideoLAN\VLC\lua\extensions\ and restart VLC Media player.
function descriptor()
return {
title = "VLC Delete Media File(Windows only)";
version = "1.0";
author = "Vicky Dev";
shortdesc = "&Remove current file from playlist and disk";
description = [[
<h1>VLC Delete Media File(Windows only)</h1>"
When you're playing a file, use this to easily
delete the current file from your <b>playlist</b> and <b>disk</b> with one click.<br>
Disclaimer: The author is not responsible for damage caused by this extension.
]];
}
end
function sleep(seconds)
local t0 = os.clock()
local tOriginal = t0
while os.clock() - t0 <= seconds and os.clock() >= tOriginal do end
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()
uri = string.gsub(uri, "^file:///", "")
uri = vlc.strings.decode_uri(uri)
path = string.gsub(uri, "/", "\\")
vlc.msg.info("[VLC Delete Media File(Windows only)] removing: "..uri.." : "..path)
removeItem()
retval, err = os.execute("if exist ".."\""..path.."\"".." #(call )")
if (type(retval) == 'number' and retval == 0) then
os.execute("del /f /a /q ".."\""..path.."\"")
end
end
function click_ok()
d:delete()
vlc.deactivate()
end
function deactivate()
vlc.deactivate()
end
function close()
deactivate()
end
function meta_changed()
end
Hope this helps anyone who wants this cool feature of deleting the media files from player itself, instead of going to the location and doing it.
I have xlsm file which I need to edit. However, macros there block my script from editing. My code is following:
xlsm_file_name = "webADI_template_Bankbuchungen_GL.xlsm"
'opening xlsm file and setting readonly to false
set xlobj = createobject("Excel.Application")
set excel_file = xlobj.workbooks.open("C:\Users\oleynikov nikolay\Desktop\VBS Automation Scripts\processed_data\Excel Datei\"&xlsm_file_name, readonly=false)
'making changes invisible for the user
excel_file.application.enableevents = false
xlobj.Visible = false
'defining the sheet where we will be inserting our data into
set excel_sheet = excel_file.worksheets(1)
excel_sheet.cells(13,4).value = "EUR"
excel_file.application.enableevents = TRUE
xlobj.DisplayAlerts = FALSE
excel_file.save
At the end of the day, no values are added. This happens because double clicking on the cell runs the macro. I need to disable this macro, insert necessary values and then enable the macros again.
Is there a possibility to do it?
Thank you.
Try this (it seems it should work):
Returns or sets an MsoAutomationSecurity constant that represents the security mode that Microsoft Excel uses when programmatically opening files. Read/write.
MsoAutomationSecurity can be one of these MsoAutomationSecurity constants:
msoAutomationSecurityByUI. Uses the security setting specified in the Security dialog box.
msoAutomationSecurityForceDisable. Disables all macros in all files opened programmatically without showing any security alerts.
VB
Sub Security()
Dim secAutomation As MsoAutomationSecurity
secAutomation = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityForceDisable
Application.FileDialog(msoFileDialogOpen).Show
Application.AutomationSecurity = secAutomation
End Sub
https://learn.microsoft.com/en-us/office/vba/api/excel.application.automationsecurity
I need to import multiple images (10.000) in Matlab (2013b) from a subdirectory of the predefined directory of Matlab.
I don't know the exact names of the images.
I tried this:
file = dir('C:\Users\user\Documents\MATLAB\train');
NF = length(file);
for k = 1 : NF
img = imread(fullfile('C:\Users\user\Documents\MATLAB\train', file(k).name));
end
But it throws this error though I ran it with the Admin privileges:
Error using imread (line 347)
Can't open file "C:\Users\user\Documents\MATLAB\train\." for reading;
you may not have read permission.
The "dir" command returns the virtual directory elements "." (self directory) and ".." parent, as your error message shows.
A simple fix is to use a more specific dir call, based on your image types, perhaps:
file = dir('C:\Users\user\Documents\MATLAB\train\*.jpg');
Check the output of dir. The first two "files" are . and .., which is similar to the behaviour of the windows dir command.
file = dir('C:\Users\user\Documents\MATLAB\train');
NF = length(file);
for k = 3 : NF
img = imread(fullfile('C:\Users\user\Documents\MATLAB\train', file(k).name));
end
In R2013b you would have to do
file = dir('C:\Users\user\Documents\MATLAB\train\*.jpg');
If you have R2014b with the Computer Vision System Toolbox then you can use imageSet:
images = imageSet('C:\Users\user\Documents\MATLAB\train\');
This will create an object containing paths to all image files in the train directory, regardless of format. Then you can read the i-th image like this:
im = read(images, i);
I am having a problem in matlab and the problem is described as follows:
When i try to read an image ( I have several images) and write them to a specific folder, the matlab triggers an error saying
Error using ==> imwrite at 394
Can't open file "\Temp\\inim735282.4716703009300000.jpg" for writing.
You may not have write permission.
May I know why this is happening?
this is the code where the problem occurs
mkdir('.\Temp');
temp_name = sprintf('%.16f',now);
corner_file = ['\Temp\corners', temp_name,'.in'];
image_file = ['\Temp\inim', temp_name,'.jpg'];
out_file = ['\Temp\out', temp_name,'.desc'];
out_imname = ['\Temp\out', temp_name,'.desc.jpg'];
I tried to change it by omitting
mkdir('.\Temp');
moreoever, i direct the path in the folder to the folder by doing this
binary_path = 'C:\Users\cool\Documents\MATLAB\Experment\experiments\bag_of_words\Temp';
to read and and write in and out of the folder.
Can someone please help me figure out this problem?
Thank you guys
Open MatLAB with admin privileges.
A few suggestions:
To generate a temporary output name use the command tempname.
temp_name = tempname();
To concatenate paths and file names use fullfile.
conrner_file = fullfile( '\', 'Temp', 'corners', [temp_name, '.in'] );
You should be careful not to mix '\Temp' and '.\Temp': as the first is an absolute path, while the second is a relative path to cwd.
EDIT:
How about:
temp_name = tempname(); % temp name + folder name in TEMP
corner_file = [ temp_name,'.in'];
image_file = [ temp_name,'.jpg'];
out_file = [temp_name,'.desc'];
out_imname = [temp_name,'.desc.jpg'];
Is it working now?