[英]Why is vbs able to find the INSTALLLOCATION when C# using both DTF and MSI API cannot?
VBS 按我的要求工作,但 COM API 和使用 C# 的 DTF 都沒有找到 InstallLocation。 以下是我到目前為止所做的。
感謝這篇文章,我能夠使用 vbs 找到在注冊表中不可用的 InstallLocation。 我知道 vbs 正在調用 COM API 在%WINDIR%\system32\msi.dll
上可用。
所以我想我會使用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。
但這也沒有成功。 以下是我的代碼。 這不會觸發異常,甚至無法通過 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();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.