我了解到这种行为涉及称为“按需安装”(又名“自我修复”)的东西。安装包创建的不寻常快捷方式称为“广告快捷方式”。现在我有了问题的名称,很容易找到有关如何解决它的信息。尤其:
这些页面包含大量信息。为了方便其他可能偶然发现这篇文章的人,我将总结他们所说的话:
广告快捷方式是做一些花哨的事情的特殊快捷方式。最值得注意的是,他们在启动目标之前重新安装损坏的应用程序。关于它们是善的、恶的还是无害的存在一些争论。在我看来,他们做了大多数用户没想到的事情,这让他们变得邪恶。因此,我想为我的应用程序禁用它们。
Visual Studio 安装项目会自动创建 MSI 包,默认情况下会生成广告的快捷方式。在安装 MSI 程序包时,通过使用 DISABLEADVTSHORTCUTS=1 作为 Setup.exe 的命令行参数很容易覆盖该默认值。此外,使用像 Orca 这样的实用程序,您可以通过插入 DISABLEADVTSHORTCUTS=1 作为 MSI 的属性来手动更改默认值。但是,如果您希望 Visual Studio 自动创建不创建广告快捷方式的 MSI 包,那就更难了。我是这样做的:
首先,我在上面的一个链接中使用 Gary Chang 提供的 DisableAdvt 代码创建了一个 VBS 文件(我在下面重复了该代码)。只需创建一个文本文件,粘贴代码。并将其保存为 DisableAdvt.vbs。
然后,为您的设置项目创建一个构建后事件。确切的语法将取决于您的文件位置。因为我的 DisableAdvt.vbs 位于解决方案文件夹的“工具”子文件夹中,所以我的构建后事件如下所示:
- "$(ProjectDir)..\Tools\DisableAdvt\DisableAdvt.vbs" "$(BuiltOuputPath)"
这就是我必须做的。它就像一个魅力。
-TC
一些注意事项:
在 Visual Studio 2005 中,安装项目的生成事件的访问方式与其他类型的项目不同。单击解决方案资源管理器中的项目名称,然后在“属性”窗格中查找 PostBuildEvent。
Orca 是一个实用程序,可用于手动将 DISABLEADVTSHORTCUTS 属性插入 MSI 文件。使用我的方法,不需要 Orca。但是,它对于验证构建事件是否正在进行预期的更改很有用。
在构建事件中,拼写错误的“BuiltOuputPath”是故意的。
这是 Gary Chang 的 DisableAdvt.vbs 代码(请注意,我在第 21 行修正了一个错字——非常重要!):
Option Explicit
Const msiOpenDatabaseModeTransact = 1
Dim argNum, argCount:argCount = Wscript.Arguments.Count
Dim openMode : openMode = msiOpenDatabaseModeTransact
' Connect to Windows installer object
On Error Resume Next
Dim installer : Set installer = Nothing
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") :
CheckError
' Open database
Dim databasePath:databasePath = Wscript.Arguments(0)
Dim database : Set database = installer.OpenDatabase(databasePath, openMode) : CheckError
' Process SQL statements
Dim query, view, record, message, rowData, columnCount, delim, column
query = "INSERT INTO Property(Property, Value) VALUES ('DISABLEADVTSHORTCUTS', '1')"
Set view = database.OpenView(query) : CheckError
view.Execute : CheckError
database.Commit
If Not IsEmpty(message) Then Wscript.Echo message
Wscript.Quit 0
Sub CheckError
Dim message, errRec
If Err = 0 Then Exit Sub
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
If Not installer Is Nothing Then
Set errRec = installer.LastErrorRecord
If Not errRec Is Nothing Then message = message & vbLf & errRec.FormatText
End If
Fail message
End Sub
Sub Fail(message)
Wscript.Echo message
Wscript.Quit 2
End Sub