3

I maintain a VB6 application that stores its data (access files) in a subfolder of the application folder. So, when the user installs the application to the default location of C:\Program Files\MyApp the data ends up in the Virtual Store. I have now been given the sweet task of converting the 1000 or so App.Path statements to a path to a Data folder that will not have any security issues. Can someone please help me out by pointing the way to some resources that will spoonfeed to me how to handle data in the Users\< Username>\AppData\Local\ folder?
Should I use the local AppData folder, or can I have the user choose a suitable location?

DavRob60
  • 3,517
  • 7
  • 34
  • 56
Dabblernl
  • 15,831
  • 18
  • 96
  • 148
  • 2
    Pretty much a duplicate of [this question](http://stackoverflow.com/questions/4273424/where-should-i-store-application-specific-settings). Check out the [accepted answer](http://stackoverflow.com/questions/4273424/where-should-i-store-application-specific-settings/4275821#4275821) by, ahem, me with help from Bob Riemersma and Cody Gray – MarkJ Dec 20 '10 at 09:53
  • I experienced this exact problem a while back. You have my sympathies. Just a note, App.Path is inconsistent in that it returns 'C:\' for the root, but omits the last '\' for other directories. We created a shell function for it. Most likely this will never be a problem, but it's good to be aware of these things. – jakdep Dec 20 '10 at 11:05
  • @MarkJ: this question indeed is an exact duplicate of the other you so eloquently and elegantly answered. I will vote to close this one. – Dabblernl Dec 20 '10 at 15:38

4 Answers4

2

I would use the local AppData folder:

Dim sAppData As String

sAppData = Environ("USERPROFILE") & "\AppData"
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
2

Well if we assume a couple of things:

  • This is only an issue for Vista or later.
  • Your data is in subfolders, under App.Path.

... I have a sort of workaround that might be used.

Note that I only use this trick when I have a bunch of old VB6 programs that were written to use data in folders beneath App.Path, sort of a quick and dirty hack to get a lot of programs working quickly. I almost always add or update the application manifest as well, mostly to prevent virtualization.


The changes I make are:

  • Add a little code to Sub Main (inserting a Sub Main if the program doesn't already have one).
  • Add two Class modules (invoked by the new Sub Main code) to the project.

When the new program is deployed, on Vista or later the program needs to be run once as administrator. In the newest version of my add-in code the program will prompt the user to rerun it elevated if required, and when OKed it does so and self-terminates.

After the first run everything should be hunky-dory, running much as it did under Win2K, XP, etc.


This startup code that requires elevation provides a list of the App.Path subfolders required to the PathLinks class.

Pathlinks creates a program folder under the Public special folder, then creates matching subfolders for the data under that. Next it moves any files and subfolders in these App.Path subfolders into the new locations. Finally it creates symlinks to the new folders back under App.Path.

If running under Windows prior to Vista, PathLinks merely creates any of the list of App.Path subfolders (under App.Path) that don't already exist (i.e. by installation).

From here on the program will find the files in the new location, without needing any changes to its use of App.Path at all.


One of the two add-in Classes is cosmetic and you can remove it. It just lets the startup code invoke TaskDialog instead of using a MsgBox call.

Be sure to scroll down for the newest version posted at PathLinks - Tame App.Path Under Vista+

Note that the sample project skips running the application when it does that "first time elevated" trick. It just does an Exit Sub in Sub Main after relocating data and symlinking to it.

Bob77
  • 13,167
  • 1
  • 29
  • 37
  • 1
    Note that you can take the code, and instead of adding it into the application you can create a small post-install helper. For PDW installs you can even create a custom Setup1.exe that performs these steps at the end, or write the helper to run a renamed Setup1 (call it Setup2) name the helper Setup1 so the bootstrap runs the helper program, which runs the renamed "Setup2", awaits completion, removes Setup2, then moves the data and creates the symlinks. – Bob77 Dec 21 '10 at 23:51
  • Thanks for this, but I will go the long and painful way of removing all App.Path references. – Dabblernl Dec 27 '10 at 09:42
0

A useful discussion can be found here

Community
  • 1
  • 1
Dabblernl
  • 15,831
  • 18
  • 96
  • 148
0

I don't know if stil some one (else as I was still searching for it) searching for this. but I found a good answer on this page http://www.vbforums.com/showthread.php?564256-Classic-VB-Where-should-I-store-the-files-that-my-program-uses-creates

I used this code the get the correct folder path.

'this peace of code must be on the top of jour module in the declaration part.
Public Enum eSpecialFolders
  SpecialFolder_Documents = &H5         'the Documents folder for the current Windows user
  SpecialFolder_Favorites = &H6         'for the Favorites folder
  SpecialFolder_Videos = &HD            'For the Video's folder
  SpecialFolder_Desktop = &H10          'for the desktop folder
  SpecialFolder_AppData = &H1A          'for the current Windows user, on any computer on the network [Windows 98 or later]
  SpecialFolder_LocalAppData = &H1C     'for the current Windows user, on this computer only [Windows 2000 or later]
  SpecialFolder_CommonAppData = &H23    'for all Windows users on this computer [Windows 2000 or later]
  SpecialFolder_Windows = &H24          'for the windows folder
  SpecialFolder_System32 = &H25         'For the windows system32 folder
  SpecialFolder_Pictures = &H27         'for the picture folder
  SpecialFolder_User = &H28             'for user folder C:\Users\sidxxxx
End Enum

'this can be placed before or after other functions
Public Function SpecialFolder(pFolder As eSpecialFolders) As String
'Returns the path to the specified special folder (AppData etc)

Dim objShell  As Object
Dim objFolder As Object

  Set objShell = CreateObject("Shell.Application")
  Set objFolder = objShell.namespace(CLng(pFolder))

  If (Not objFolder Is Nothing) Then SpecialFolder = objFolder.Self.Path

  Set objFolder = Nothing
  Set objShell = Nothing

  If SpecialFolder = "" Then Err.Raise 513, "SpecialFolder", "The folder path could not be detected"

End Function

I Used it in the same module like this in a other function.

FileName = SpecialFolder(SpecialFolder_AppData) & "\Log\" & "log.log"

this will set FileName = "C:\Users\username\AppData\Roaming\Log\log.log"

Kind Regards