我已经阅读了关于这个主题的无数帖子,但无法将我的大脑包裹在整个事物中.我有一个旧的VB6应用程序,用于安装在根目录下的文件夹中.在该文件夹中有子文件夹:
\ data子文件夹,用于访问数据库
\ quotes子文件夹,用户生成的word文档将存储在其中,
\ backup,我的程序定期备份mdb的副本
它运作良好,生活很简单.现在,当我们尝试在Windows 7和Windows 8上安装时,程序将安装到程序文件(x86)文件夹中.程序运行正常,但所有数据库更新和word文件都存储在users文件夹中的虚拟存储中,这不是我们想要的.
我知道为什么会这样,我知道我需要修改我的程序以适应Windows 7/8.有人可以给我一个明确的解释/建议,如何做到以下几点:
我知道"用户"下的appdata文件夹是存储数据库/ word文件/备份的推荐位置.但是,在我隐藏的系统上,我希望用户可以轻松访问它(不是隐藏的),所以我在想MyDocuments文件夹?
我已经读过这个帖子:我应该在哪里存储应用程序特定的设置?这让我对如何在代码中找到文件/位置有所了解,虽然目前尚不清楚如何找到MyDocuments. 有人可以帮忙吗?
这是我变得更加困惑的地方.如果我想使用MyDocuments\CompanyName甚至上面链接中提到的Appdata文件夹, 我如何告诉程序包/部署向导将mdb文件和上述文件夹安装到此特定文件夹中? 我可以使用PDW中的Appdata或MyDocuments文件夹的宏吗?我在XP机器上,因此我的路径与Windows 7/8机器不同.
任何帮助/见解将不胜感激.
我知道为什么会这样,我知道我需要修改我的程序以适应Windows 7/8.
好,然后我会尽量不打败死马(虽然这是一个我经常喜欢鞭打的人,因为很多人误解了它).我只会指出,即使在较旧版本的Windows上,您的程序正常工作的事实也是潜在错误的幸运结果."Program Files"文件夹从未打算成为可写的.你不只是解决一些愚蠢的"问题"的新版Windows.这应该是从一开始就应该做的事情.
我知道"用户"下的appdata文件夹是存储数据库/ word文件/备份的推荐位置.但是,在我隐藏的系统上,我希望用户可以轻松访问它(不是隐藏的),所以我在想MyDocuments文件夹?
我知道这很复杂,所以让我看看我是否可以尽量让它变得简单......
在"应用程序数据"文件夹是用于您的应用程序内部使用,数据不打算被视为或由用户直接操作.
在"我的文档"文件夹是所有用户应该能够看到和直接操作; 换句话说,用户数据而不是应用程序数据.
然后还有这两种文件夹类型中的每一种的每用户和全局变体.在"应用程序数据"的情况下,每用户变体进一步细分为本地(仅驻留在本地机器上)和漫游(其跟随用户帐户到她登录的网络上的任何机器).
因此,如果您希望文件"易于用户访问",那么您一定要使用"我的文档"文件夹.这就是它的用户文档.
所有这些复杂规则存在的原因是因为像微软和Adobe这样的流行供应商的行为不端的应用程序(有?)倾向于将垃圾转储到用户的"我的文档"文件夹中,这是用户从未打算与之交互的内容.直.然后用户打开他们的文档文件夹,看到他们从未放在那里的一堆东西."这些东西是什么?这些不是我的.我的文件在哪里?" 上周我更新她的电脑时,我母亲就问过我.
目前尚不清楚如何找到MyDocuments.有人可以帮忙吗?
从VB 6?简单的方法是鲍勃和马克在你看到的问题中提出的方法.这涉及创建一个Shell对象并查询它您感兴趣的文件夹的位置.
缺少的部分是与"我的文档"文件夹对应的常量.你会在这里找到一个完整的常量列表.你想要的那个被命名ssfPERSONAL(因为在过去创建这个API时,Windows不是那么友好而且"我的文档"这个名字还没有被发明),它具有价值&H05.所以代码看起来像:
Const ssfPERSONAL = &H05
Dim strMyDocsPath As String
strMyDocsPath = CreateObject("Shell.Application").NameSpace(ssfPERSONAL).Self.Path
Run Code Online (Sandbox Code Playgroud)
如果我想使用MyDocuments\CompanyName甚至上面链接中提到的Appdata文件夹,我如何告诉程序包/部署向导将mdb文件和上述文件夹安装到此特定文件夹中?我可以使用PDW中的Appdata或MyDocuments文件夹的宏吗?
没有多少,我可以补充一点,鲍勃没有在已经覆盖他的回答,除了建议,当你这个现代化VB应用程序,你也可以考虑有利于更好的安装程序的抛弃过时的PDW.
就个人而言,我是一个巨大的风扇Inno Setup的,这对于提供更多的功能比你能撼动一棒的Windows应用程序自由安装程序.它适用于VB 6应用程序.我已经多次使用它了.我觉得它很容易使用,至少对于基础知识来说.它支持各种高级自定义,如果你通过阅读文档不能很好地学习,其中一些可能会很棘手,但这一切都非常可行.我甚至偶然发现了编写Delphi代码以定制Inno Setup项目的方法!
在Inno Setup中,您可以使用其中一个预定义的常量访问系统文件夹的路径.例如,{userdocs}和{commondocs}.这些工作与PDW中的宏(如果不完全相同,已经很长时间)一样.
当然,这仍然无法解决Bob正确指出的问题:用户的"我的文档"文件夹的概念对安装程序来说并没有多大意义.当然,您可以访问全局(公共)"我的文档"文件夹,因为它在所有用户之间共享,但这可能不是您想要的.安装程序应该能够由具有足够权限的任何用户运行,实际上这通常是与用于运行应用程序的常规用户帐户不同的管理员帐户.您无法在设置期间假设特定用户帐户,并且您的设计必须考虑到这一点.
对我来说,"模板"方法对你来说是个好方法.用于设置新用户帐户的完整文件集可以存储在"Program Files"文件夹中.这实际上是一个很好的地方,因为它可以很好地保护它免受错误的修改,并且因为你只是要从中读取它,所以你可以保证拥有必要的权限.当应用程序首次在新用户帐户下启动时,它可以检测到这一事实并提供设置新用户帐户以供应用程序使用.此时,您知道您在正确的用户帐户下运行,因此您可以使用上面的代码来查询该用户的"我的文档"文件夹的位置.使用所需的文件夹结构全部设置在"程序文件"中应用程序文件夹的子目录中,设置新用户帐户可能就像复制该文件夹一样简单.如果您需要从用户收集信息或提供自定义选项,您可以编写一些"首次运行向导".
我知道“users”下的appdata文件夹是存储数据库/word文件/备份的推荐位置。但是,在我的隐藏系统上,我希望用户可以轻松访问它(而不是隐藏),所以我在想 MyDocuments 文件夹?
这两个都是每个用户数据的位置。因此,您的安装程序无法在此处放置任何内容,因为在正常情况下,它甚至不会在目标运行时用户下运行,并且不知道该数据的目标用户是哪一个。
相反,您需要决定哪些文件是针对每台计算机的,哪些是针对每用户的。任何每用户文件都应由应用程序在“首次运行”时创建或复制,通常应通过检查每用户应用程序文件夹中是否存在每用户 INI 文件来检测(它也需要创建该文件)在 LocalAppData 下。
每台计算机的文件进入安装程序在 ProgramData (CommonAppData) 下创建的文件夹中。在大多数情况下,您的安装程序不仅需要创建此“公司/应用程序”子文件夹,还需要设置该文件夹的安全性,以允许用户对放置在那里的项目拥有所需的访问权限。然后安装程序可以将任何已部署的每台计算机数据(如设置文件、MDB 等)放入此文件夹中。
例外情况可能是首次运行操作复制到用户配置文件中的每台计算机“模板”文件,或在应用程序生命周期内只读的其他数据。这些仍然可以转储到 EXE 旁边的 Program Files 子文件夹中(或子文件夹等)。
PDW 过于陈旧和原始,无法完成所有所需的安装活动。这并不意味着您不能修改 setup1.vbp(通过安装 VB6 和 PDW 提供)来制作自定义 setup1。但通常这不值得麻烦,因为您无法扩展 PDW 的“向导”来拥有新屏幕并接受新信息。
1998 年,随着 Windows Installer 的出现,Microsoft 发布了一个名为 Visual Studio 6.0 Installer 1.0(以及大约一年后的 1.1)的免费更新工具来补充/替换 PDW。
Microsoft 不再托管包含 VSI 1.1 的两个下载文件,尽管您可能仍然会找到由第 3 方托管的副本(尽管进行病毒扫描)。
您还可以在更新版本的 Visual Studio 中使用安装程序项目类型(尽管我相信他们从 VS 2012 开始就将其拉取了)。还有 WiX 工具套件和基于第三方安装程序的工具等。
但即使使用 VSI 1.1,您也会发现软件包执行的许多操作无法在 VSI 1.1 中指定,这意味着您必须对 MSI 数据库进行一些构建后调整。您可以使用安装程序 SDK 中的 Orca 或通过使用 Windows Installer 的自动化界面进行这些构建后编辑的 WSH 脚本来执行此操作。
我读过这个帖子:我应该在哪里存储应用程序特定的设置?这让我对如何在代码中查找文件/位置有了一些了解,尽管不清楚如何查找 MyDocuments。有人可以帮忙吗?
您可以通过其自动化接口或 API 调用来使用 Shell 操作。该位置是通过ssfPERSONAL、CSIDL_PERSONAL或FOLDERID_Documents常量请求的,具体取决于您决定进行哪个调用来获取它。