View Full Version : find a file
zawadi
03-03-2006, 08:15 AM
Hi all, could someone please help.
I have been asked to create a setup file that needs to find the directory that a product is in and set it in %AppFolder%, but I cant seem to get it sorted.:huh
This should get you started. I haven't included any logging, nor have I run it as I don't have SF7 on this machine. Let me know how it tests out.
Here's what I'm trying to do:
1. Find all the fixed drives on the system (in case the user installed to d:\ or something). I stop at fixed drives because otherwise your installer will crawl out on mapped network drives too.
2. Search each fixed drive for your program name and build a list of all locations (there could be multiples).
3. Set the %AppFolder% variable to the first instance found.
-- Define the name of the file you want to search for
g_YourProductName = "product.exe";
-- Setup the empty tables needed to hold your search results
t_AllDrives = {};
t_FixedDrives = {};
t_FileFolders = {};
-- Search for all drives on the system
t_AllDrives = Drive.Enumerate();
-- Check if the drives found are "fixed" and if so add them to a separtate table
local index;
local driveLetter;
for index, driveLetter in t_AllDrives do
if Drive.GetInformation(driveLetter) == 3 then
Table.Insert(t_FixedDrives, (Table.Count(t_FixedDrives)+1), driveLetter);
end
end
-- Searching for the file on each drive will return a table containing the paths to all locations of your file on that drive
if t_FixedDrives then
for index, driveLetter in t_FixedDrives do
local filePath;
t_FilePaths = {};
t_FilePaths = File.Find(driveLetter, g_YourProductName, true, false);
if t_FilePaths then
for index, filePath in t_FilePaths do
Table.Insert(t_FileFolders, (Table.Count(t_FileFolders)+1), (String.SplitPath(filePath).Drive .. String.SplitPath(filePath).folder));
end
end
end
end
-- Now you have a table containing all the folders where your program was found.
-- TO DO -- If more than one folder was found, you'll need to decide whether you want to default to the first folder on the list or prompt the user to make a choice... I've gone the default route here...
if t_FileFolders then
SessionVar.set("%AppFolder%", t_FileFolder[1]);
end
zawadi
03-06-2006, 02:58 AM
I get an error on line 40, that t_FileFolder[1] is a nil value
Sorry... line 40 should be:
SessionVar.set("%AppFolder%", t_FileFolders[1]);
zawadi
03-07-2006, 02:48 AM
I get line 40, attempt to call field `set`(a nil value) :huh
SessionVar.Set("%AppFolder%", t_FileFolders[1]);
Lua Script is case sensitive...
zawadi
03-07-2006, 07:10 AM
it now get "argument 2 must be of type string :huh
I doubt this is the problem, but one thing I noticed that looks wierd is that I used local index variable twice inside the same routine... lets change those:
-- Searching for the file on each drive will return a table containing the paths to all locations of your file on that drive
if t_FixedDrives then
for indexA, driveLetter in t_FixedDrives do
local filePath;
t_FilePaths = {};
t_FilePaths = File.Find(driveLetter, g_YourProductName, true, false);
if t_FilePaths then
for indexB, filePath in t_FilePaths do
Table.Insert(t_FileFolders, (Table.Count(t_FileFolders)+1), (String.SplitPath(filePath).Drive .. String.SplitPath(filePath).folder));
end
end
end
end
The "Argument 2 must be of type string" means that when we passed the t_FileFolders[1] variable to the SessionVar.Set() action, it contained something other than a string value. We can assume that it did not contain a nil value otherwise the error would have said so. This means that somewhere in our script, the t_FileFolder[1] variable was actually populated with a value of another type... likely a boolean (or maybe a number but lua is usually pretty good at converting those on the fly as needed).
What you'll want to do next is add some checks in the code to help debug where that value is coming from. Most developers use one of the following three methods to view their debug info:
1. Add Dialog.Message() actions where ever you want the code to tell you what it is doing (Problem here is you have to go and pull them all out later).
2. Debug.Print() outputs to the debug window (don't forget to show the window first).
3. Setup Factory has some nice logging facilities integrated. You can write just about anything you want to the log file using the SetupData.WriteToLogFile() action.
As I said in my original post, I do not have regular access to a machine with SF installed so you'll have to do a little of the leg work on this one.
Eagle
03-07-2006, 09:09 AM
Try this Stuff: exits on first file found , however you can modify to suit.
On Start Event for a Progress Screen:
-- set lua variable of 'filename.exe' to search for
g_YourProductName = "TryandFindthisOneifYouCan.exe";
--set some basic progress bar parameters
local nmax = 1024;
DlgProgressBar.SetRange(CTRL_PROGRESS_BAR_01, 0, nmax);
DlgProgressBar.SetStep(CTRL_PROGRESS_BAR_01, 5);
-- now call the global function FindTarget(g_YourProductName)
if FindTarget(g_YourProductName) then
DlgProgressBar.SetPos(CTRL_PROGRESS_BAR_01, nmax);
SessionVar.Set("%AppFolder%", strAppFolderPath);
Dialog.Message("Debug allocated Session Variable", SessionVar.Expand("%AppFolder%")); --remove
else
DlgProgressBar.SetPos(CTRL_PROGRESS_BAR_01, nmax);
Dialog.Message("Debug allocated Session Variable", "Target file: "..g_YourProductName.." was Not found"); --remove
--action-s how you wish to handle continuing with 'installer'
end
for Global Functions:
function Find_CB()
--basic callback display for use with a 'progress' screen
local npos = DlgProgressBar.GetPos(CTRL_PROGRESS_BAR_01);
if (npos >= 1024) then
DlgProgressBar.SetPos(CTRL_PROGRESS_BAR_01, 0);
return true; --continue
else
DlgProgressBar.SetPos(CTRL_PROGRESS_BAR_01, npos + 1);
return true; --continue
end
end
function FindTarget(Sbintgt)
-- Setup localised empty tables needed to hold your search results
local t_FilePaths = {};
local t_FileFolders = {};
local t_FixedDrives = {};
if Sbintgt then
-- Search for all drives on the system
local t_AllDrives = Drive.Enumerate();
if t_AllDrives then
-- Check if the drives found are "fixed" and if so add them to a separate table
for n, driveLetter in t_AllDrives do
if (Drive.GetType(driveLetter) == 3) then
Table.Insert(t_FixedDrives, (Table.Count(t_FixedDrives)+1), driveLetter);
end
end
end
end
-- Search for the file on each drive
if (Table.Count(t_FixedDrives) >=1) then
local bfoundtgt;
for n, driveLetter in t_FixedDrives do
if bfoundtgt then break end --break out of main loop
--local t_FilePaths = File.Find(driveLetter, Sbintgt, true, false); --no callback display
local t_FilePaths = File.Find(driveLetter, Sbintgt, true, false, Find_CB); --include the call back function(slows search performance)
if t_FilePaths then
for n, filePath in t_FilePaths do
local pathsplit = String.SplitPath(filePath);
if (pathsplit ~= "") then
local folder_path = pathsplit.Drive..pathsplit.Folder;
Table.Insert(t_FileFolders, (Table.Count(t_FileFolders)+1), folder_path);
bfoundtgt = true;
break; --exit on first found
end
end
end
end
end
if (Table.Count(t_FileFolders) >=1) then
strAppFolderPath = t_FileFolders[1];
return true;
else
return false;
end
end
hth
(searches for filenames is the least efficient and most open to wrong ID
for a target install location)
if you can be provided with a registry key which has a path to the Application
you can use this method and then verify if the mainapp.exe exists.
vBulletin® v3.8.4, Copyright ©2000-2009, Jelsoft Enterprises Ltd.