为什么 vbs 能够在同时使用 DTF 和 MSI API 的 C# 中找到 INSTALLLOCATION?
Why is vbs able to find the INSTALLLOCATION when C# using both DTF and MSI API cannot?
VBS 按我的要求工作,但 COM API 和使用 C# 的 DTF 都没有找到 InstallLocation。以下是我到目前为止所做的。
感谢 this post,我能够使用 vbs 找到在注册表中不可用的 InstallLocation。我知道 vbs 正在调用 %WINDIR%\system32\msi.dll
.
上可用的 COM API
C# COM API
所以我想我会用C#来调用这个方法。但它失败了。即使我可以确认存在和安装,它也无法打开其中一个产品 GUID(我检查了三遍)。
注意:有些产品没有抛出异常,并且正确找到了 InstallLocation。这还不是全部。
以下是我的代码。
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;
}
好的,没用,让我们试试 DTF。
C# DTF
但是那也没有成功。以下是我的代码。这不会触发异常,甚至无法通过 COM API 检测到的异常也能够检测到自身,但 InstallLocation 属性 是空字符串。
注意:有些产品确实填写了 InstallLocation 属性。这还不是全部。
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;
}
为什么 VBS 能够检测到 InstallLocation 而 C# 都不能?我错过了什么?
我不能使用VBS的原因是try catch不可用,除非我使用vb.net。
根据 SteinAsmul 的建议 DTF 不会自动调用与成本相关的操作,我进一步阅读了 DTF 文档。
我发现 DoAction
在 DTF 中也可用。所以我使用了以下内容,var installLocation 现在有了我正在寻找的预期值。
Installer.SetInternalUI(InstallUIOptions.Silent);
var session = Installer.OpenProduct(product.Value);
session.DoAction("CostInitialize");
session.DoAction("CostFinalize");
var installLocation = session["INSTALLLOCATION"];
session.Close();
您可以试试这个,尽管它不是很“完善”或经过测试。
使用 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"]);
}
}
}
使用 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();
}
}
}
VBS 按我的要求工作,但 COM API 和使用 C# 的 DTF 都没有找到 InstallLocation。以下是我到目前为止所做的。
感谢 this post,我能够使用 vbs 找到在注册表中不可用的 InstallLocation。我知道 vbs 正在调用 %WINDIR%\system32\msi.dll
.
C# COM API
所以我想我会用C#来调用这个方法。但它失败了。即使我可以确认存在和安装,它也无法打开其中一个产品 GUID(我检查了三遍)。
注意:有些产品没有抛出异常,并且正确找到了 InstallLocation。这还不是全部。
以下是我的代码。
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;
}
好的,没用,让我们试试 DTF。
C# DTF
但是那也没有成功。以下是我的代码。这不会触发异常,甚至无法通过 COM API 检测到的异常也能够检测到自身,但 InstallLocation 属性 是空字符串。
注意:有些产品确实填写了 InstallLocation 属性。这还不是全部。
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;
}
为什么 VBS 能够检测到 InstallLocation 而 C# 都不能?我错过了什么?
我不能使用VBS的原因是try catch不可用,除非我使用vb.net。
根据 SteinAsmul 的建议 DTF 不会自动调用与成本相关的操作,我进一步阅读了 DTF 文档。
我发现 DoAction
在 DTF 中也可用。所以我使用了以下内容,var installLocation 现在有了我正在寻找的预期值。
Installer.SetInternalUI(InstallUIOptions.Silent);
var session = Installer.OpenProduct(product.Value);
session.DoAction("CostInitialize");
session.DoAction("CostFinalize");
var installLocation = session["INSTALLLOCATION"];
session.Close();
您可以试试这个,尽管它不是很“完善”或经过测试。
使用 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"]);
}
}
}
使用 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();
}
}
}