Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Finding hidden folders with WScript.Shell

Status
Not open for further replies.

Bryan - Gendev

Programmer
Jan 9, 2011
408
0
16
AU
I am using code I found here many years ago - it produces a listing of all folders ( and files) from a selected point on any of my drives. However the list does not contain the system hidden folder 'appdata' and all of its contents. I wish to see that folder and its contents. I can imagine a modification to the code below would do this. I tried opttree.Value = 2 with no apparent change.

Code:
oShell = Createobject("WScript.Shell")
If Thisform.opttree.Value = 1
	oShell.Run('cmd /c '+Iif(Thisform.chkInclude.Value = 0,'tree "','tree /f "')+;
				Thisform._SourceFolder+'" > '+Thisform._TreeFile,2,.T.)
Else
	oShell.Run('cmd /c '+Iif(Thisform.chkInclude.Value = 0,'tree /a "','tree /a /f "')+;
				Thisform._SourceFolder+'" > '+Thisform._TreeFile,2,.T.)
Endif

Can anyone help?
GenDev
 
Gendev,
It's not VFP code, it's a powershell script. You call it with ShellExec() (Or however you've set yours up), you can just make a text file of the code above, name it anything .ps and then run that in your shell exec from within whatever starting directory you want.


Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCAP, CDCP, CDCS, CDCE, CTDC, CTIA, ATS, ATD

"I try to be nice, but sometimes my mouth doesn't cooperate.
 
The code given in a previous post fails

problem_kfw4bz.png


Anyone suggest why?

GenDev
 
Agbain, gendev, open your yes, the full code is this:

Code:
Dimension aryFiles(1)
=GetAllFiles(GETDIR(), @aryFiles)
SET STEP ON

FUNCTION GetAllFiles(cDirectory, aryParam)
    LOCAL ARRAY aryTemp(1,5)
    LOCAL nCount, nMax, nLen, cFile
    SET DEFAULT TO (cDirectory)
    =ADIR(aryTemp, "*.*","AHRSD",1)
    nMax = ALEN(aryTemp,1)
    FOR nCount = 1 TO nMax
        cFile = ALLTRIM(aryTemp(nCount,1))
        IF !(cFile == ".") AND !(cFile == "..")
            IF "D" $ aryTemp(nCount,5)
                =GetAllFiles(ADDBS(cDirectory + cFile), @aryParam)
            ELSE
                nLen = ALEN(aryParam)
                IF !EMPTY(aryParam(nLen))
                    DIMENSION aryParam(nLen + 1)
                    nLen = nLen + 1
                ENDIF
                aryParam(nLen) = cDirectory + cFile
            ENDIF
        ENDIF
    ENDFOR
ENDFUNC

Edit
It begins by creating the array, thus will not get to the error.
That was assuming it works, I got the same error in cas of drilling down my user profile main folder, I'll need to debug this and come back with a solution to that detail problem, don't know yet where that comes from.

Chriss
 
The problem I had is with a corrupt subfolder in the TEMP directory:

In my case "C:\Users\ChrissM\AppData\Local\Temp\s0cnm1dj.2q1\Feedback\es", stepping one directory up within File Explorere I get this:
esfolder_s9hty6.jpg


And when trying to enter the "es" subfolder:
es_corrupt_bdy7jc.jpg

ADIR itself doesn't break this way, but it creates no array, which then leads to VFPs error

So this is a fix:
Code:
Dimension aryFiles(1)
=GetAllFiles(Getdir(), @aryFiles)
Set Step On

Function GetAllFiles(cDirectory, aryParam)
   Local Array aryTemp(1,5)
   Local nCount, nMax, nLen, cFile
   Try
      Set Default To (cDirectory)
      nMax = Adir(aryTemp, "*.*","AHRSD",1)
      For nCount = 1 To nMax
         cFile = Alltrim(aryTemp(nCount,1))
         If !(cFile == ".") And !(cFile == "..")
            If "D" $ aryTemp(nCount,5)
               =GetAllFiles(Addbs(cDirectory + cFile), @aryParam)
            Else
               nLen = Alen(aryParam)
               If !Empty(aryParam(nLen))
                  Dimension aryParam(nLen + 1)
                  nLen = nLen + 1
               Endif
               aryParam(nLen) = cDirectory + cFile
            Endif
         Endif
      Endfor
   Catch
   Endtry
Endfunc

This needs further adaptions to your needs because it finally only creates a list of file names, takes very long for that and does so without keeping their attributes (hidden, for example). You rather want the directories, not all the files, don't you?

This will list only directories:
Code:
Dimension aryFiles(1,2)
? 'pick the root directory'
lcRootDir = GETDIR()
=GetAllDirs(lcRootDir, @aryFiles)
? 'The result is in the array aryFiles. Look into it in the Locals window of the debugger' 
SET STEP ON

Function GetAllDirs(cDirectory, aryParam)
   Local Array aryTemp(1,5)
   Local nCount, nMax, nLen, cFile
   
   If Upper(Addbs(cDirectory))=Upper(Addbs(GetEnv("TEMP")))
      Return
   Endif
   
   Try
      Set Default To (cDirectory)
      nMax = Adir(aryTemp, "*.*","AHRSD",1)
      If nMax>0
         nLen = Alen(aryParam,1)
         If !Empty(aryParam(nLen,2))
            Dimension aryParam[nLen + 1,2]
            nLen = nLen + 1
         Endif
         aryParam[nLen,1] = cDirectory
         aryParam[nLen,2] = aryTemp[1,5]
      Endif
      For nCount = 1 To nMax
         cFile = Alltrim(aryTemp(nCount,1))
         If !(cFile == ".") And !(cFile == "..")
            If "D" $ aryTemp(nCount,5)
               =GetAllDirs(Addbs(cDirectory + cFile), @aryParam)
* only do this, if you also want to list all files               
*!*	            Else
*!*	               nLen = Alen(aryParam)
*!*	               If !Empty(aryParam(nLen))
*!*	                  Dimension aryParam(nLen + 1)
*!*	                  nLen = nLen + 1
*!*	               Endif
*!*	               aryParam(nLen) = cDirectory + cFile
            Endif
         Endif
      Endfor
   Catch
   Endtry
Endfunc

It still takes "forever", if I run it on my user proflie as root folder. Not only does the TEMP folder within it has vast number of files, it also has a large nukmber of directories, dito web browser profile folders. So I wonder for what use case you need this or your original tree usage. If you look for some specific file, it's better to use the filer search tool of VFP or Windows file index searchj, after adding the root folder to the index.

Chriss
 
To show what you get (in the view of the debugger locals window):

dirlist_bjetas.jpg

So the result array contains directory names in the first column and the attributes like ...D. for a normal directory in the second column. A hidden directory will have an H within these flags.

Chriss
 
In thread184-1812247 a result was Rick C. Hodgin's extended vfp2c32.fll - originally by Christian Ehlscheidt, in which Rick added recursing subfolders to the AdirEx() function of the FLL.

So there's the potential of getting the tree with many more informations (file sizes, attributes), too.



Chriss
 
Thankyou Chriss
I hadn't realised the depth of the problem when I first asked the question and then I tried the code as I showed..
I shall look further into this out of interest in what you have shown.

GenDev+
 
There's not much depth to the problem. Well, tree simply does whatt it does, but does not show attributes of neither directories nor files, I think it doesn't even list files, it just generates an (ASCII) tree representation of the directory system. and it does not list hidden folders and there's no command line switch that makes it do that, so that's a dead end that can't be used ofr your purpose.

This could have been the end of the story, but we established ADIR solves the problem of showing file and folder attributes. It does neither generate a graph nor does it recurse into subdirs, though. But it's part of VFP and functions and recursive calls of functions can do what you finally need.

The problem you encountered couldn't really have been forseen by the FAQ programmer, but it wasn't hard to fix it by encapsulating the SET DEFAULT into a TRY.

That solves getting at all the information necessary, but there are manyfold residue problems, of which you might not have encountered many, like you still don't get a graph as tree did provide and ADIR is slow in comparison to tree, not only because you have to program the recursion, not only because it also gets more informations like file size and times, it simply is slower. No problem, if you just want to use this for normal/moderate sized folder structures and not something as large and with very deep nested branches as a user profile folder is.

Your major title suggests you only want hidden folders. You don't really have expressed what you're mainly after, though and it seems to me it's the graphical representation, which should include hidden folders, too. Well, if you dig into AppData, just because there's also the Local and Roaming part of a profile, you also dig into Temp, which is vast and deeply nested, so that's making it convuluted, cluttered and you woulnd't profit much of that. That's perhaps also a reason they hide that folder, it's nothing that's made for users, all the appdata directory provides is room for applications to tore their stuff, each their own and including temp files, "there's nothing to see here, move on", that's the idea behind hiding, besides anyone can set the hidden attribute to their own folder for their own reasons.

So what are you really after? Tree does a fine job, do you want it to show the hidden branch of appdata and are you sure you want this showm, have you looked into it and not seen how deeply convolued that part of the directory system is? I assume you're after hidden things like app inin files, well, there's no deidcated way to get at them, you have to know where they are, it's usually only the business of the software that stores them for itself. Looking into the whole file system to find something specific and building a graph also isn't useful for that purpose, there would be much more use of a dedicated search for files of type INI, for example. And Windows indexing can make searches faster, really much faster. The downside of searching anywhere is, that Windows does not index everywhere.

Besides all that, you know to find out what a specific EXE reads procmon is the best, it's just not simple to automate because it just takes a human to look at the result log and look for the interesting files accessed, isn't it? Therefore I don't assume you really do this for that reason, but what are you really after?

If you simply want to show the hidden folder and their sub structure, not every hidden folder has such a deep and convoluted structure as appdata, but regarding hidden folders Windows itself sets hidden, they are hidden with the intention to say "none of your businness", without restricting permissions, as all apps usually working non elevated should be able to write in appdata, nontheless. That's all there is to appdata, inlcuding TEMP. If an app has it's ini there and not at a more obvious place, then they don't use an INI for users to have a way to configure them by changing the INI. For my apps, I put an ini into the application folder usually and give permissions to write into them, if I want that, or put them into appdata and document that in a "How to" or "configuration" section of the application help file, for example. Or, even more likely (for me) I give them a configuratoin form within my application. I think what you described about TMG is that its ini options also are configurable within the application. There's a reason you do a tool to make work with TMG easier, so there's that. But you simply will need a small table with version number 1-9 and location of app.ini as second column and be done with that. You can assume it's version 9, you have means to find out the list of installed software by a WMI query, and get file version information from a TMG*.exe, so that's how I would tackle that. Once you know the version and location of TMG app.ini you can verify that with DIRECTORY() - including if it's hidden or not. And FILE() or ADIR() and then act on that ini.

Chriss
 
Gendev,

just to clear up one point: When I said hiding folders, especiall the appdata folder, from the normal user, that wouldn't look into the options of file explorer to show hidden folder, too is like Microsoft saying that' "non of your business" I didn't mean you personally, also not as someone with less professional knowledge, I didn't want to be disrespectful. I hope you didn't get this wrong.

I also don't think your demand is useless, I like the simplicity of an ascii treeview TREE gives me and didn't know it before. It's more compact than what you can get from dir /s, actaully nice.

I still don't know whether your demand to let TREE also show hidden folders and their substructure is specifically about appdata or just a gneeral idea. But just for fun I did this:
1. I deleted as much from temp to get a less deep and less convoluted directory structure from the part of C:\Users\accountname\Local\Temp alone, vbesides all the other subfolders, and then I started cmd.exe ()in Admin mode, might not matter much, but of course you get the most from that). And then I CDed into the appdata folder that is hidden and ran tree from thgat as root folder, so within AppData I ran [pre]tree /a /f >appdataoverview.txt[/pre]

It took a few minutes to finish , the file is about 6MB and then I opened it in notepad++, where you have a better handling of large textfile, a line numbering and a very simple way of zooming in and out (chaning font size) with the mouswheel. Thius is how the tree looks zoomed out to the minimum font size (not really readable, though I guess it's still 2x2 pxels per character:

appdatatree_eb3ocj.jpg


I circled the scroolbar handle to emphasize how small the portio is you see from the overall tree. This is I estimate about 200 lines of the whole tree and the tree ends here:
appdatatreend_ovfvbo.jpg

So it's almost 110.000 lines of directories and files. True, the /f options means to also list all files.

I have fun, but I don't see a value in that for the human overview of something that is really not of interest in all details anyway. You see why I think there are better and more straight forward ways to get at what you're really after.

Here, by the way is the same thing without the /f option, so only directories:
appdatatreedironly_gzv7ud.jpg

Still long, but it ends here:
appdatatreedironlyend_t166tm.jpg

Just about 18.000 directories.

Still not anything I'd call an overall "overview" for a human. Did you follow some other threads here, recently there's been a bit of dicsussion of AI, ChatGPT et al., the measurement about units of processing there are tokens, I'd compare that to the ability of a humans short term memory of 7 seconds or the ability - unless you're an autist, perhaps, to spot (count, distinguish) 5-9 things at once in a picture. I don't mean this to be a 1:1 comparison, but there are such things that limit what's useful in a UI, too.

Not all hidden folders are that bloated as AppData. And my single case also is that large (despite cleaning temp) because I have Visual Studio installed, a lot is from that. But you see in that specific hidden folder AppData the only thing that is perhaps useful to get to a target you actually want is to have all that as data a query can search in, but not for display.

So all in all, I hope I'm making clear why I'm not so enthusiastic about your idea to get hidden folders with tree or a replacement of tree and I'm still here to help and guide you, if you would just tell what you're after with this feature.

Chriss
 
Chriss,
My original post ( idea ) came to me as we were researching my SET DEFA problem - I ran the Option in PathWiz to investigate appdata, found it not there and wondered if I could modify the tree code to get it. That's where it all took off. So when a thread with more code was posted I tried the code and got the error I reported so I asked why/can it be fixed. You took it from there and I enjoyed your posts. I wont be changing my app's code - the Option is just a useful addition for TMG users who might be 'hunting' for exhibits somewhere on their PC - as I said it's quite fast and doesn't require messing with File Explorer.

GenDev
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top