如何获取安装目录?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取安装目录?相关的知识,希望对你有一定的参考价值。

MSI存储将来卸载任务的安装目录。

使用INSTALLPROPERTY_INSTALLLOCATION属性(即"InstallLocation")只有安装程序在安装过程中设置了ARPINSTALLLOCATION属性。但是这个属性是可选的,几乎没有人使用它。

我怎样才能检索安装目录?

答案

使用注册表项来跟踪安装目录,这样您可以在升级和删除产品时引用它。

使用WIX我会在安装目录的Directory标记之后创建一个创建密钥的Component

另一答案

我会尝试使用Installer.OpenProduct(productcode)。这将打开一个会话,然后您可以在该会话中询问房产(“TARGETDIR”)。

另一答案

试试这个:var sPath = this.Context.Parameters [“assemblypath”]。ToString();

另一答案

我使用MsiGetComponentPath() - 您需要ProductId和ComponentId,但是您可以获得已安装文件的完整路径 - 只需选择一个到达安装目录位置的路径即可。如果你想获得任何随机MSI的目录值,我不相信有一个API可以让你这样做。

另一答案

正如线程中其他地方所述,我通常在HKLM中编写一个注册表项,以便能够轻松检索安装目录以进行后续安装。

如果我正在处理尚未执行此操作的设置,我将使用内置的Windows Installer功能AppSearch:http://msdn.microsoft.com/en-us/library/aa367578(v=vs.85).aspx通过指定要查找的文件签名来查找以前安装的目录。

文件签名可以包含文件名,文件大小和文件版本以及其他文件属性。可以通过一定程度的灵活性指定每个签名,以便您可以找到同一文件的不同版本,例如通过指定要查找的版本范围。请查看SDK文档:http://msdn.microsoft.com/en-us/library/aa371853(v=vs.85).aspx

在大多数情况下,我使用主应用程序EXE并通过查找具有正确版本和日期的文件的窄版本范围来设置严格签名。

另一答案

最近我需要通过Natural Docs自动化Ketarin安装。我可以假设它被安装到默认路径(%ProgramFiles(x86)%Natural Docs),但我决定采取安全的方法。可悲的是,即使安装程序在HKLMSoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall上创建了一个密钥,它的价值也没有让我找到安装目录。

Stein回答建议AppSearch MSI功能,它看起来很有趣,但遗憾的是Natural Docs MSI安装程序没有为他的方法工作提供Signature表。

所以我决定通过注册表搜索任何对自然文档安装目录的引用,我找到一个进入HKLMSOFTWAREMicrosoftWindowsCurrentVersionInstallerUserDataS-1-5-18Components密钥。

MSI Components Registry Key

我在C#中为Ketarin开发了Reg类,允许递归。因此,我通过HKLMSOFTWAREMicrosoftWindowsCurrentVersionInstallerUserDataS-1-5-18Components查看所有值,如果将主应用程序可执行文件(NaturalDocs.exe)发现到其中一个子项值中,则将其提取(C:Program Files (x86)Natural DocsNaturalDocs.exe变为C:Program Files (x86)Natural Docs)并将其添加到系统环境变量%PATH%(所以我可以调用“ NaturalDocs.exe“直接而不是使用完整路径”。

注册表“类”(实际上是函数)可以在GitHub(RegClassCS)上找到。

System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("NaturalDocs.exe", "-h");
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;

var process = System.Diagnostics.Process.Start (startInfo);
process.WaitForExit();

if (process.ExitCode != 0)
{
    string Components = @"SOFTWAREMicrosoftWindowsCurrentVersionInstallerUserDataS-1-5-18Components";

    bool breakFlag = false;

    string hKeyName = "HKEY_LOCAL_MACHINE";
    if (Environment.Is64BitOperatingSystem)
    {
        hKeyName = "HKEY_LOCAL_MACHINE64";
    }

    string[] subKeyNames = RegGetSubKeyNames(hKeyName, Components);
    // Array.Reverse(subKeyNames);
    for(int i = 0; i <= subKeyNames.Length - 1; i++)
    {
        string[] valueNames = RegGetValueNames(hKeyName, subKeyNames[i]);
        foreach(string valueName in valueNames)
        {
            string valueKind = RegGetValueKind(hKeyName, subKeyNames[i], valueName);
            switch(valueKind)
            {
                case "REG_SZ":
                // case "REG_EXPAND_SZ":
                // case "REG_BINARY":
                    string valueSZ = (RegGetValue(hKeyName, subKeyNames[i], valueName) as String);
                    if (valueSZ.IndexOf("NaturalDocs.exe") != -1)
                    {
                        startInfo = new System.Diagnostics.ProcessStartInfo("setx", "path "%path%;" + System.IO.Path.GetDirectoryName(valueSZ) + "" /M");
                        startInfo.Verb = "runas";

                        process = System.Diagnostics.Process.Start (startInfo);
                        process.WaitForExit();

                        if (process.ExitCode != 0)
                        {
                            Abort("SETX failed.");
                        }

                        breakFlag = true;
                    }
                    break;

                /*  
                case "REG_MULTI_SZ":
                    string[] valueMultiSZ = (string[])RegGetValue("HKEY_CURRENT_USER", subKeyNames[i], valueKind);

                    for(int k = 0; k <= valueMultiSZ.Length - 1; k++)
                    {
                        Ketarin.Forms.LogDialog.Log("valueMultiSZ[" + k + "] = " + valueMultiSZ[k]);
                    }
                    break;
                */

                default:
                    break;
            }

            if (breakFlag)
            {
                break;
            }
        }

        if (breakFlag)
        {
            break;
        }
    }
}

即使您不使用Ketarin,也可以轻松粘贴该功能并通过Visual Studio或CSC构建它。

可以使用RegClassVBS采用更通用的方法,该方法允许注册表项递归,并且不依赖于.NET Framework平台或构建过程。

请注意,枚举组件密钥的过程可能会占用大量CPU资源。上面的示例有一个Length参数,您可以使用该参数向用户显示一些进度(可能类似于“i from(subKeysName.Length - 1)key remaining are” - 具有创造性)。可以在RegClassVBS中采用类似的方法。

这两个类(RegClassCS和RegClassVBS)都有可以指导您的文档和示例,您可以在任何软件中使用它,并有助于它们的开发,在git repo上进行提交,并且(当然)在它的github上打开一个问题页面如果您发现任何您无法自行解决的问题,我们可以尝试重现该问题以找出我们可以做些什么。 =)

以上是关于如何获取安装目录?的主要内容,如果未能解决你的问题,请参考以下文章

如何从Android片段中的相机获取图像

如何获取当前显示的片段?

如何从 Firebase 获取数据到 Recyclerview 中的片段?

如何通过 viewModels 获取 viewModel? (片段-ktx)

如何在片段中获取rootview?

一旦单击带有 in 片段的回收器列表项,如何将片段意向活动,以及如何获取回收器项目值?