如何让NSIS在另一个用户的%APPDATA%中创建一个文件?

时间:2012-06-08 15:00:37

标签: postgresql nsis appdata

我为postgresql 9.1编写了一个NSIS安装程序脚本。安装程序正常工作,但重启后,服务未启动(安装后,数据库正常启动)

我想这是因为postgres服务用户的%APPDATA%中没有pgpass.conf文件。据我所知,我的安装脚本将pgpass.conf文件添加到运行安装程序的用户的%APPDATA%(在我的情况下是管理员帐户)。这无济于事。

我尝试了以下操作,将pgpass.conf添加到所有用户,bt我想这会将其添加到一种通配符中,而不是每个用户的%APPDATA%:

SetShellVarContext "all"
SetOutPath "$APPDATA\postgresql"
File config\pgpass.conf
SetShellVarContext "current"
SetOutPath "$APPDATA\postgresql"
File config\pgpass.conf

我在文档中找不到c:/ Users / postgres的宏名称。这可能是实现它的一种方式。但是对于WindowsXP,7,我希望我需要一种可移植的方式来解决/ Users目录。

我希望我可以使用类似SetShellVarContext“postgres”的东西,然后让NSIS在c:\ Users \ postgres \ AppData \ postgresql中编写pgpass.conf文件。

有办法做到这一点吗?

谢谢你!

3 个答案:

答案 0 :(得分:1)

没有记录方法可以为没有令牌句柄的其他用户获取shell文件夹(并且要获取令牌句柄,您需要用户密码,或者如果用户已登录,您可以获得他们的令牌,如果您正在运行SYSTEM)

然后我们搬到无证领土;您可以尝试this macro或以GetProfilesDirectory作为根目录自行构建路径。

答案 1 :(得分:1)

SetShellVarContext ALL将为您提供%programdata%位置(在Win7中),这是与%appdata%位置不同的位置(也来自NSIS中的$APPDATA。 (Sym链接使它们看起来像是一样的......但它们完全不同Dir的!!!)

NSIS会将上下文从%APPDATA%更改为%PROGRAMDATA%,具体取决于SetShellVarContext所有vs当前切换。但仍然使用$APPDATA var。

所以简而言之,我猜你的文件到了错误的位置。 我相信您只想以管理员身份安装,但让postgres的本地用户拥有一个额外的文件pgpass.conf

根据Win7或WinXP设置变量,因为您要写入的路径都不同。

要测试只是将文件写入您知道postgres用户的位置!

StrCpy $WINVER_VAR "C:\Users\postgresql\AppData\Roaming" ;;or whatever based on OS
SetOutPath "$WINVER_VAR\postgresql"

或者更好地使用

File /oname=$WINVER_VAR\postgresql\pgpass.conf pgpass.conf

只需从安装程序复制到您想要的位置,并且在管理员的目录中没有其他未使用的副本。

注意:在XP中,%APPDATA%位于Documents&设置......我不记得确切的路径。所以你必须验证!

添加到系统上的每个用户...查看“定位插件”或获取系统上所有用户的列表,并执行相同的操作。

答案 2 :(得分:0)

SID(安全标识符)是一种安全标识符,用于标识Windows NT的用户帐户,组,域或计算机。系统使用帐户SID操作,而不是其配置文件用户名。 SID在创建时分配给每个帐户,因此如果您要使用相同的名称和密码再次创建帐户,SID当然会有所不同。重新创建帐户将导致生成新的SID。如果你正在接受我正在铺设的东西,它们是独一无二的。

MACRO:

;=#
;= ${GETUSERSID} $0 "Username"
;       $0          = The returning SID value
;       "Username"  = The username of the account you wish the SID
;                   If the username is an empty value, then the SID of the
;                   current user will be given to $0.
!define GETUSERSID "!insertmacro _GETUSERSID"
!macro _GETUSERSID _RESULT _USER
      System::Store S
      StrCpy $0 ${_USER}
      StrCmp $0 "" 0 +2
      ExpandEnvStrings $0 "%USERNAME%"
      System::Call "*(&t1024)i.r1"
      System::Call "advapi32::LookupAccountName(tn,tr0,ir1,*i1024,tn,*i1024,*in)i.r0"
      IntCmp $0 1 0 +2 +2
      System::Call "advapi32::ConvertSidToStringSid(ir1,*t.s)"
      IntCmp $0 1 +2 0 0
      Push error
      System::Free $1
      System::Store L
      Pop "${_RESULT}"
!macroend

${GETUSERSID} $0 "Username"
MessageBox MB_ICONINFORMATION|MB_OK "User's SID:$\r$\n$$0 is holding $0" IDOK

现在,这是列出主机PC上所有注册用户帐户的示例:

System::Call "netapi32::NetQueryDisplayInformation(wn,i1,i0,i-1,i${NSIS_MAX_STRLEN},*i.R0,*i.R1)i.R4"
${If} $R4 = 0
    ${For} $R4 1 $R0
        System::Call "*$R1(i.R2,i.R3,i,w,i,i)"
        IntFmt "$R2" ${STR} $R2
        IntFmt "$R3" ${STR} $R3
        ${GetUserSID} "$R2" "$R5"
        IntOp $R1 $R1 + 24
        DetailPrint "-----------------"
        DetailPrint "Name: $R2"
        DetailPrint "SID: $R5"
        DetailPrint "$R3"
    ${Next}
    System::Call "netapi32::NetApiBufferFree(iR1)"
${EndIf}

现在我不确定这是否会起作用(可能会提交,但总会有ACL)但是这里有一个例子(如果我理解你的问题正确的话),就是在暗示你在问什么。

${GETUSERSID} $0 "postgres"
ReadRegStr $1 HKU "$0\Volatile Environment" "APPDATA"
DetailPrint "APPDATA: $1"
AccessControl::GrantOnFile $1 "USER" "ListDirectory + GenericRead + GenericExecute" 
AccessControl::EnableFileInheritance $1
SetOutPath "$1\postgresql"
File config\pgpass.conf

这只是一个快速解决方案..甚至不确定这会起作用,但也许是朝着正确方向迈出的一步?希望这有帮助!