Недавно мне нужно было автоматизировать Natural Docs установить через Ketarin . Я мог предположить, что он был установлен по умолчанию (%ProgramFiles(x86)%\Natural Docs
), но я решил использовать безопасный подход. К сожалению, даже если установщик создал ключ на HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
, ни одно из его значений не привело меня к поиску установочного каталога.
Ответ Stein предлагает функцию AppSearch MSI, и это выглядит интересно, но, к сожалению, установщик Natural Docs MSI не предоставляет таблицу Signature для его подхода.
Поэтому я решил поискать в реестре, чтобы найти ссылку на установочный каталог Natural Docs, и я нашел его в ключе HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components
.
Я разработал Reg Class в C # для Ketarin, который позволяет рекурсию. Поэтому я просматриваю все значения через HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components
, и если исполняемый файл Основного приложения (NaturalDocs.exe) найден в одном из значений подразделов, он извлекается (C:\Program Files (x86)\Natural Docs\NaturalDocs.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 = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components";
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 или процессов сборки.
Обратите внимание, что процесс перечисления Ключа Компонентов может сильно загружать процессор. В приведенном выше примере есть параметр Length, который вы можете использовать, чтобы показать некоторый прогресс пользователю (может быть что-то вроде «i from (subKeysName.Length - 1) оставшихся ключей» - будьте изобретательны). Аналогичный подход можно использовать в RegClassVBS.
Оба класса (RegClassCS и RegClassVBS) имеют документацию и примеры, которые могут вам помочь, и вы можете использовать его в любом программном обеспечении и внести свой вклад в их разработку, сделав коммит на git-репо и (конечно) открыв проблему на страницах GitHub, если вы обнаружите проблему, которую не можете решить самостоятельно, мы можем попытаться воспроизвести проблему, чтобы выяснить, что мы можем с этим сделать. =) * * Тысяча тридцать-девять