John Marzion
John Marzion

Reputation: 113

Installing VB6 app on Windows XP, Windows 7, Windows 8

I have read through countless posts on this topic, but can't wrap my brain around the whole thing. I have an old VB6 app that used to install in a folder on the root directory. Within that folder were subfolders:
\data subfolder for access databases
\quotes subfolder where user generated word documents would be stored and \backup where my program periodically backed up a copy of the mdb's

It worked great and life was simple. Now, when we try to install on Windows 7 and Windows 8, the program gets installed into program files (x86) folder. The programs run fine, but all database updates and word files are stored in a virtual store in the users folder which is not what we want.

I know why this is happening and I know I need to modify my program to accomodate Windows 7/8. Can someone please give me a clear explanation/recommendation on how to the following:

I know appdata folder under "users" is the recommended place to store the databases/word files/backups. However, on my system that is hidden and I would like it to be easily accessible to the user (not hidden), so I was thinking MyDocuments folder?

I've read this thread: Where should I store application specific settings? which gives me some sense on how to find the files/locations in code, although it's not clear how to find MyDocuments. Can anyone help?

Here is where I become even more confused. If I wanted to use something like MyDocuments\CompanyName or even the Appdata folder mentioned in the link above, how do I tell the package/deployment wizard to install the mdb files and the folders mentioned above into this specific folder? Is there a macro for the Appdata or MyDocuments folders in the PDW that I can use? I'm on an XP machine and so my path would be different than for a Windows 7/8 machine.

Any help/insight would be greatly appreciated.

Upvotes: 9

Views: 7500

Answers (2)

Cody Gray
Cody Gray

Reputation: 244772

I know why this is happening and I know I need to modify my program to accomodate Windows 7/8.

Good, then I'll try not to beat a dead horse (although this is one I regularly like to give a good flogging because so many people misunderstand it). I'll only point out that the fact your program ever worked correctly, even on the older versions of Windows, was a fortunate consequence of a latent bug. The "Program Files" folder was never meant to be writeable. You're not just working around some silly "issue" of newer versions of Windows. This is something that should have been done right from the beginning.

I know appdata folder under "users" is the recommended place to store the databases/word files/backups. However, on my system that is hidden and I would like it to be easily accessible to the user (not hidden), so I was thinking MyDocuments folder?

I know this is complicated, so let me see if I can try to make it as simple as possible…

The "App Data" folders are for data intended for internal use by your application and not intended to be seen or manipulated directly by the user.

The "My Documents" folder is for everything that the user should be able to see and directly manipulate; in other words, user data instead of application data.

And then there also per-user and global variants of each of these two folder types. In the case of "App Data", the per-user variant is further subdivided into local (which stays on the local machine only) and roaming (which follows the user account to any machine on the network to which she logs on).

So if you want the files to be "easily accessible to the user", then you should definitely use the "My Documents" folder. That's what it's for—user documents.

The reason why all of these complicated rules exist is because misbehaved applications by such popular vendors as Microsoft and Adobe had (have?) a tendency to dump junk into the user's "My Documents" folder, stuff that the user was never intended to interact with directly. Users would then open their documents folder and see a bunch of stuff they never put there. "What are all these things? These are not mine. Where are my documents?" My mother just asked me this last week when I updated her PC.

it's not clear how to find MyDocuments. Can anyone help?

From VB 6? The easy way is the one suggested by Bob and Mark in the question you looked at. This involves creating a Shell object and querying it for the location of the folder(s) you're interested in.

The part that's missing is the constant that corresponds to the "My Documents" folder. You'll find a complete list of constants here. The one you want is named ssfPERSONAL (because in the old days when this API was created, Windows wasn't as friendly and the "My Documents" name hadn't been invented yet), which has the value &H05. So the code looks like:

Const ssfPERSONAL = &H05

Dim strMyDocsPath As String
strMyDocsPath = CreateObject("Shell.Application").NameSpace(ssfPERSONAL).Self.Path

If I wanted to use something like MyDocuments\CompanyName or even the Appdata folder mentioned in the link above, how do I tell the package/deployment wizard to install the mdb files and the folders mentioned above into this specific folder? Is there a macro for the Appdata or MyDocuments folders in the PDW that I can use?

There's not much that I can add to this that Bob didn't already cover in his answer, other than to recommend that while you're modernizing this VB application, you also consider ditching the antiquated PDW in favor of a better installer.

Personally, I'm a huge fan of Inno Setup, which is a free installer utility for Windows applications that offers more features than you can shake a stick at. It works very well with VB 6 applications. I've used it many times for that myself. I think it's fairly easy to use, at least for the basics. It supports all sorts of advanced customizations, and some of that can be tricky if you don't learn well by reading documentation, but it is all very doable. I've even stumbled my way through writing Delphi code to customize Inno Setup projects!

In Inno Setup, you access the paths to system folders using one of the pre-defined constants. For example, {userdocs} and {commondocs}. These work much like (if not exactly like, it's been a long time) macros in PDW.

Of course, this still doesn't fix the problem Bob rightly points out: the concept of a user's "My Documents" folder doesn't really make much sense to an installer. Certainly you can access the global (public) "My Documents" folder because it is shared among all users, but this is probably not the one you want. The installer should be able to be run by any user with sufficient privileges, and in fact this will often be an administrator account that differs from the regular user account used to run your application. You can't assume a particular user account during setup, and your design must account for this.

It sounds like to me that a "template" approach would be a good one for you. The complete set of files used to set up a new user account could be stored in the "Program Files" folder. This is actually a good place for it because it is well protected there from erroneous modifications, and since you're only going to be reading from it, you can be guaranteed to have the necessary permissions. When the application is launched for the first time under a new user account, it could detect this fact and offer to set up the new user account for use with the application. At this point, you know that you're running under the correct user account, so you can use the above code to query the location of that user's "My Documents" folder. With the desired folder structure all set up in a subdirectory of your application's folder in "Program Files", setting up a new user account could be as simple as copying over that folder. If you need to gather information from the user or offer customization options, you could write a little "First Run Wizard".

Upvotes: 7

Bob77
Bob77

Reputation: 13267

I know appdata folder under "users" is the recommended place to store the databases/word files/backups. However, on my system that is hidden and I would like it to be easily accessible to the user (not hidden), so I was thinking MyDocuments folder?

Both of these are locations for per-user data. As such your installer cannot put anything here because under normal circumstances it won't even be running under the target runtime user and wouldn't know which one to target for this data.

Instead you'll want to decide which files are per-computer and which are per-user. Any per-user files should be created or copied by your application on "first run" which it should normally detect by checking for the presence of a per-user INI file in a per-user application folder (which it also needs to create) under LocalAppData.

Per-machine files go into an installer created folder under ProgramData (CommonAppData). In most cases your installer needs to not only create this "company/app" subfolder but also to set security on the folder to allow users to have the required access rights to items placed there. Then the installer can place any deployed per-machine data like settings files, MDBs, etc. into this folder.

An exception might be per-machine "template" files that your first-run action copies into user profiles, or other data that is read-only for the life of the application. Those can still be dumped into the Program Files subfolder next to the EXE (or in a subfolder, etc.).

The PDW is too old and primitive to do all of the installation activities required. That doesn't mean you can't hack up the setup1.vbp (provided by installing VB6 and the PDW) to make a custom setup1. But usually this isn't worth the trouble since you can't extend the PDW's "wizard" to have new screens and accept new information.

As Windows Installer came on the scene in 1998 Microsoft released a free update tool called Visual Studio 6.0 Installer 1.0 (and a year later or so 1.1) to supplement/replace the PDW.

Microsoft does not host the two download files comprising VSI 1.1 anymore though you might still find copies hosted by 3rd parties (virus scan anything like that though).

You can also use an Installer project type in a more recent version of Visual Studio (though I believe they pulled it starting in VS 2012). There are also things like the WiX tool suite and 3rd party Installer-based tools.

But even with VSI 1.1 you'll find that many things you need to have your package do cannot be specified within VSI 1.1, and this means you have to make some post-build tweaks to the MSI database. You can do this using Orca from the Installer SDK or via WSH scripts that use Windows Installer's automation interface to make these post-build edits.

I've read this thread: Where should I store application specific settings? which gives me some sense on how to find the files/locations in code, although it's not clear how to find MyDocuments. Can anyone help?

You use Shell operations either through its automation interface or API calls. This location is requested via the ssfPERSONAL, CSIDL_PERSONAL, or FOLDERID_Documents constants depending on which call you decide to make to obtain it.

Upvotes: 4

Related Questions