简体   繁体   English

为什么 vbs 能够找到 INSTALLLOCATION 而 C# 同时使用 DTF 和 MSI API 不能?

[英]Why is vbs able to find the INSTALLLOCATION when C# using both DTF and MSI API cannot?

VBS works as I desired, but both COM API and DTF using C# is not locating the InstallLocation. VBS 按我的要求工作,但 COM API 和使用 C# 的 DTF 都没有找到 InstallLocation。 Followings are what I have done so far.以下是我到目前为止所做的。


Thanks to this post , I was able to find a InstallLocation that is not available on registry using vbs.感谢这篇文章,我能够使用 vbs 找到在注册表中不可用的 InstallLocation。 I understand that vbs is calling for COM API available on %WINDIR%\system32\msi.dll .我知道 vbs 正在调用 COM API 在%WINDIR%\system32\msi.dll上可用。


C# COM API C# COM API

So I thought I would use C# to call this method up.所以我想我会使用C#来调用这个方法。 But it failed.但它失败了。 Even though I can confirm the existence and installation, it cannot open one of the product GUID (I tripple checked).即使我可以确认存在和安装,它也无法打开其中一个产品 GUID(我检查了三次)。

Note: there were products that did not throw exception and InstallLocation were properly found.注意:有些产品没有抛出异常并且正确找到了 InstallLocation。 Its just not all.这还不是全部。

Followings are my code.以下是我的代码。

        static Dictionary<string, string> FindInstallLocationsCOM(Dictionary<string, string> products)
        {
            var locationDictionary = new Dictionary<string, string>();

            // Get the type of the Windows Installer object
            Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");

            // Create the Windows Installer object
            Object installerObj = Activator.CreateInstance(installerType);
            Installer installer = installerObj as Installer;

            foreach (var product in products)
            {
                try
                {
                    var session = installer.OpenProduct(product.Value);
                    if (session != null)
                    {
                        session.DoAction("CostInitialize");
                        session.DoAction("CostFinalize");
                        var installLocation = session.Property["INSTALLLOCATION"];
                        MessageBox.Show(product.Key + "\n" + "Product Code : " + product.Value + "\n" + "Install Location : " + installLocation);
                        locationDictionary.Add(product.Key, installLocation);
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("Error : Could not open Product " + e.Message + "\n" + "Product : " + product.Key + "\n" + "Product Code : " + product.Value);
                }
            }

            return locationDictionary;
        }

OK that did not work, let's try DTF.好的,那没有用,让我们试试 DTF。


C# DTF C# DTF

But that also was not successful.但这也没有成功。 Following is my code.以下是我的代码。 This does not trigger exception, and even the one that was not detectable via COM API was able to detect itself, but InstallLocation property was empty string.这不会触发异常,甚至无法通过 COM API 检测到的异常也能够检测到自身,但 InstallLocation 属性为空字符串。

Note: there were products that did have InstallLocation property filled.注意:有些产品确实填充了 InstallLocation 属性。 Its just not all.这还不是全部。

        static Dictionary<string,string> FindInstallLocation(Dictionary<string,string> products)
        {
            var locationDictionary = new Dictionary<string, string>();

            foreach (var product in products)
            {
                try
                {
                    var installed = new ProductInstallation(product.Value);
                    if (installed != null)
                    {
                        var installLocation = installed.InstallLocation;
                        MessageBox.Show(product.Key + "\n" + "Product Code : " + product.Value + "\n" + "Install Location : " + installLocation);
                        locationDictionary.Add(product.Key, installLocation);
                    }
                    else
                    {
                        MessageBox.Show(product.Key + "\n" + "Product Code : " + product.Value + "\n" + "Is not installed");
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("Error :  " + e.Message + "\n" + "Product : " + product.Key + "\n" + "Product Code : " + product.Value);
                }
            }

            return locationDictionary;
        }

Why is VBS able to detect the InstallLocation when neither of C# is not able to?为什么 VBS 能够检测到 InstallLocation 而 C# 都检测不到? What am I missing?我错过了什么?

The reason I cannot use VBS is because the try catch is not available unless I use vb.net.我不能使用 VBS 的原因是因为 try catch 不可用,除非我使用 vb.net。

After SteinAsmul's suggesion that DTF does not automatically call cost related action, I did further reading in the DTF document.在 SteinAsmul 建议 DTF 不会自动调用与成本相关的操作之后,我进一步阅读了 DTF 文档。

I found an DoAction is also available in DTF.我发现DoAction在 DTF 中也可用。 So I used the following, and the var installLocation now has the expected value I was looking for.所以我使用了以下内容,var installLocation 现在有了我正在寻找的预期值。

Installer.SetInternalUI(InstallUIOptions.Silent);
var session = Installer.OpenProduct(product.Value);
session.DoAction("CostInitialize");
session.DoAction("CostFinalize");
var installLocation = session["INSTALLLOCATION"];
session.Close();

You can try this though it is not very "polished" or tested.尽管它不是很“完善”或经过测试,但您可以尝试一下。

Using COM:使用 COM:

using System;
using System.Windows.Forms;
using WindowsInstaller;

namespace DTFTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
            var installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
            if (installer == null) { return; }

            var session = installer.OpenProduct("Product-GUID-here");
            if (session == null) { return; }

            session.DoAction("CostInitialize");
            session.DoAction("CostFinalize");

            MessageBox.Show(session.Property["Directory-Property-Here"]);
        }
    }
}

Using DTF:使用 DTF:

using System;
using Microsoft.Deployment.WindowsInstaller;
using System.Windows.Forms;

namespace DTFTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Installer.SetInternalUI(InstallUIOptions.Silent);
            var session = Installer.OpenProduct("Product-GUID-here");
            session.DoAction("CostInitialize");
            session.DoAction("CostFinalize");
            MessageBox.Show(session["Directory-Property-Here"]);
            session.Close();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM