常规用户运行时,MSI的.NET应用程序快捷方式

时间:2009-03-09 20:02:42

标签: visual-studio-2005 windows-installer shortcuts

我有一个C#应用程序,它使用Visual Studio 2005中的内置MSI构建器。

使用MSI(通过CD)将应用程序部署到目标计算机上后,我启动桌面快捷方式(作为特权用户),程序按预期运行。但是,如果我以非特权用户身份退出然后再尝试运行该应用程序,则计算机会开始寻找MSI,因为它想要修复/配置它。当然这会失败,因为它无法再找到MSI。

但是,我可以浏览到Program Files中的应用程序文件夹,并将快捷方式复制到桌面并完全正常运行。

我如何解决这个问题?我已经改变了一些设置试图绕过这个没有运气。

编辑:我有InstallAllUsers = True set。

5 个答案:

答案 0 :(得分:6)

正如here所解释的,Visual Studio只能创建使用MSI文件检查所有文件和注册表值是否存在的“广告快捷方式”。

在同一链接中,您可以找到解决方案:编辑MSI数据库以在Property表中添加值。 我测试了它,你只需要添加“ DISABLEADVTSHORTCUTS ”,其值为“1”。

要添加它,您可以使用属于Windows Installer SDK的ORCA工具。 这是手动方式......我想你不会喜欢它。

所以我进一步看了一下,发现你可以使用Window Installer SDK提供的命令行和VBS脚本来做到这一点:

Cscript WiRunSQL.vbs Test.msi "INSERT INTO `Property` (`Property`.`Property`,`Property`.`Value`) VALUES ('DISABLEADVTSHORTCUTS',1)"

现在你只需要为你的安装项目设置一个post build事件(它与“常规”项目略有不同,请参阅here)以执行此脚本。

对我来说效果很好!

其他资源:
MSI property table reference
Edit MSI with command line

答案 1 :(得分:0)

安装“大家”或“只是我”时,通常会有一个选项。一定要检查每个人。您甚至可以在构建msi时将其设置为默认值。

作为补充说明,旧版本的MS Office也存在同样的问题(可能它仍然存在;我不需要检查最近的版本 - 也许这意味着没有解决方案)。当我以前在小型计算机商店工作时,每当我们设置新的构建时,我们总是创建初始用户帐户,然后手动启动办公室一次,以便为我们的用户提供额外的步骤。

答案 2 :(得分:0)

桌面快捷方式基本上是一种特殊的快捷方式,可以触发Windows安装程序的弹性检查 - 尝试恢复丢失的文件,文件夹和注册表项。

我很可能会说你有一些缺少的每用户注册表项(HKCU或HKCR),因此Windows Installer会尝试找到MSI来重新创建它们。

答案 3 :(得分:0)

编辑2010年6月:我创建的MSI在Windows XP上的VS 2005下。当我尝试使用相同的MSI在Vista下安装/卸载时,卸载不是很干净。我没有评估范围或原因,但我不建议在未经进一步调查的情况下在Vista上使用此解决方案。

原始帖子:

我仍然没有找到解决我问题的真正解决方案,虽然解决方法 - 有点黑客 - 对我的目的来说效果很好。我在其他网站上找到了建议(如果我再次找到它,我会发布一个链接)。

我创建了一个具有两个功能的VBS文件:一个创建快捷方式,另一个根据需要创建目录结构。当文件执行时,它会根据开发人员认为合适的次数调用MakeShortcut。

第二个VBS文件的工作方式相同,但删除了快捷方式。

我将第一个文件作为自定义操作的一部分(右键单击安装项目,视图,自定义操作)在安装文件夹中调用。我在Uninstall文件夹中调用第二个。

问题是两个VBS文件安装到目标目录以及程序的其余部分。可能有办法摆脱它们,但我真的不在乎它们会留在那里。再一次,这是一个黑客攻击,并不像我希望的那样优雅,但它能够很好地工作,直到我能找到更好的解决方案。

以下是两个文件,以防有人想要使用它们:

'创建SHORTCUTS.VBS

MakeShortcut "%AllUsersProfile%\Start Menu\Programs\My Prog Folder", _
             "My Prog", _
             "%ProgramFiles%\My prog\prog.exe"


Function MakeShortcut (location, text, target)

    Dim objShortcut
    Dim objShell
    Dim expLocation

    Set objShell = CreateObject("WScript.Shell")
    expLocation  = objShell.ExpandEnvironmentStrings(location)
    expTarget    = objShell.ExpandEnvironmentStrings(target)

    MakeDirectory(expLocation)

    set objShortcut = objShell.CreateShortcut(expLocation & "\" & text & ".lnk") 
    objShortcut.TargetPath = expTarget
    objShortcut.Save
End Function


Function MakeDirectory (newPath)

    Dim objFSO
    Dim arrPath
    Dim length
    Dim count
    Dim path

    Set objFSO = CreateObject("Scripting.FileSystemObject")

    If objFSO.FolderExists(newPath) Then    
        Exit Function
    End If

    path = ""
    count = 0
    arrPath = split(newPath, "\")
    length = ubound(arrPath)
    While count <= length 
        path = path + arrPath(count) + "\"
        count = count + 1
        If Not objFSO.FolderExists(path) Then 
            objFSO.CreateFolder(path)
        End If
    Wend
End Function

删除SHORTCUTS.VBS

DeleteShortcut "%AllUsersProfile%\Start Menu\Programs\My Prog Folder", _
               "My Prog.lnk", _
               True


Function DeleteShortcut (location, shortcut, delLoc)

    Dim objShortcut
    Dim objShell
    Dim expLocation

    Set objShell = CreateObject("WScript.Shell")
    Set objFSO   = CreateObject("Scripting.FileSystemObject")
    expLocation  = objShell.ExpandEnvironmentStrings(location)

    DeleteDirectory(expLocation)

    If objFSO.FileExists(expLocation) Then
       objFSO.DeleteFile expLocation & "\" & shortcut
    End If 

    If delLoc = True Then
        DeleteDirectory location
    End If

End Function


Function DeleteDirectory (path)

    Dim objFSO

    Set objFSO = CreateObject("Scripting.FileSystemObject")

    If objFSO.FolderExists(path) Then  
        objFSO.DeleteFolder path, True
    End If
End Function

答案 4 :(得分:0)

如果MSI将任何注册表项写入HKCU,则当新用户第一次运行该应用程序时,Windows Installer会发现该用户不存在这些条目并尝试创建它们。为什么Windows Installer认为它需要原始MSI文件,这超出了我的范围(C:\ Windows \ Installer中的存根应该足够,但似乎不是)。

在任何情况下,替换快捷方式都不是一个完整的快捷方式,因为其他操作(如调用COM组件)可以调用与通告的快捷方式调用相同的自我修复过程。