2

Я делаю следующее: я в реестре направляюсь в

SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

потом вытаскиваю оттуда некоторую информацию о программах и хочу поместить ее в бд

  1. Когда я вытаскиваю названия программ, некоторые из них отображаются как-то странно, примерно так: введите сюда описание изображения

И как это можно исправить? вот код того как я беру инфу:

private void Glavnoe_okno_Load(object sender, EventArgs e)
    {
        RegistryKey Namekey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
        foreach (string Key in Namekey.GetSubKeyNames())
            dataGridView1.Rows.Add(Key);
    }
  1. Как тогда мне переделать данный код, чтобы взять другие параметры, например "DisplayVersion" или "Publisher"?
  2. Каким образом тогда должен выглядеть шаблон на добавление в таблицу БД, чтобы названия программ писались в один столбец, разработчик - во второй, а версия - в третий?
aepot
  • 49,560
  • А при чем тут sql-server? – aepot May 22 '22 at 10:44
  • База данных, в которую данные надо перенести - sql-server как раз – Андрей Павлов May 22 '22 at 10:51
  • А что туда переносить? Копию реестра? Так данные уже сохранены в реестре, какой смысл их куда-то еще пересохранять? Пытаюсь понять суть вопроса. Чем сам реестр не база данных? Заведите себе ключ типа HKCU\Software\MyAppName и там храните что нужно. Базы данных обычно делают для работы с общей базой сразу из нескольких приложений на разных машинах по сети. Вы же специализируетесь на работе с реестром, почему бы его не использовать тогда на всю катушку? – aepot May 22 '22 at 10:52
  • Просто такой механизм, что данные (название программ, кто их сделал, версии программ) берутся из реестра, переносятся в бд, а потом из бд они переносятся в форму (почему именно так, к сожалению потому что здесь по ТЗ обязательно наличие бд, я с этим ничего не могу сделать) – Андрей Павлов May 22 '22 at 10:58
  • А что тогда можно почитать в таком случае, чтобы примерно понимать как работать с реестром? – Андрей Павлов May 22 '22 at 11:02
  • Чуть позже покажу как работать с реестром, правда без БД. Для БД я советую вам подготовиться к моему ответу: 1) Приложение создать под .NET 6, а не Framework 4.x. 2) Установить NuGet пакет Entity Framework Core 6. 3) Изучить подход к формированию и миграциям БД под названием Code First. 4) Познакомиться с Linq и как он используется для работы с БД. - тогда у вас получится легко реализовать то что нужно, а я постараюсь показать всё про реестр в той форме, в которой вам будет удобно прикрутить к этому всем EF Core. Вас возможно удивит, то при таком подходе не придется писать SQL запросы вручную. – aepot May 22 '22 at 11:39

1 Answers1

3

Используйте современный дотнет для разработки - .NET 6, создайте новый тестовый проект.

Написал короткий пример.

Обратите внимание, ваше приложение должно быть строго собрано как x64, а не Any CPU, в противном случае при обращении к реестру надо явно задавать RegistryHive.

Для начала, создам модель данных.

public class RegistryUninstallInfo
{
    [DisplayName("Наименование")]
    public string DisplayName { get; set; }
[DisplayName("Версия")]
public string DisplayVersion { get; set; }

[DisplayName("Разработчик")]
public string Publisher { get; set; }

[Browsable(false)]
public string UninstallString { get; set; }

}

Для нагладности дизайнер формы я не использовал, поэтому построил форму прямо в конструкторе. Просто вставьте код в проект.

using Microsoft.Win32;
using System.ComponentModel;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Text.Json;

namespace WinFormsAppRegistry;

public partial class Form1 : Form { private BindingList<RegistryUninstallInfo> Applications { get; } = new BindingList<RegistryUninstallInfo>(); private RegistryUninstallInfo SelectedItem { get; set; } public Form1() { InitializeComponent(); Text = "Пример работы с реестром для StackOverflow на русском"; MinimumSize = new Size(600, 400); DoubleBuffered = true; var panel = new TableLayoutPanel() { RowCount = 2 }; panel.Dock = DockStyle.Fill; panel.RowStyles.Add(new RowStyle() { SizeType = SizeType.Percent, Height = 100 }); panel.RowStyles.Add(new RowStyle()); panel.AutoSize = true; panel.AutoSizeMode = AutoSizeMode.GrowAndShrink; var table = new DataGridView() { Dock = DockStyle.Fill, AutoGenerateColumns = true, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, ReadOnly = true, AllowUserToAddRows = false, SelectionMode = DataGridViewSelectionMode.FullRowSelect }; table.DataSource = Applications; table.CellDoubleClick += Table_CellDoubleClick; table.SelectionChanged += Table_SelectionChanged; SetDoubleBuffered(table, true); panel.Controls.Add(table, 0, 0); var button = new Button() { Text = "Обновить" }; button.Click += UpdatedButton_Click; panel.Controls.Add(button, 0, 1); Controls.Add(panel);
}

public static void SetDoubleBuffered(Control c, bool value)
{
    typeof(Control).GetProperty(&quot;DoubleBuffered&quot;, BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(c, value);
}

private void Form1_Load(object sender, EventArgs e)
{
    LoadRegistry();
}
private void UpdatedButton_Click(object sender, EventArgs e)
{
    LoadRegistry();
}

private void Table_SelectionChanged(object sender, EventArgs e)
{
    DataGridView table = (DataGridView)sender;
    if (table.SelectedRows.Count &gt; 0)
        SelectedItem = table.SelectedRows[0].DataBoundItem as RegistryUninstallInfo;
}

private void Table_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
    MessageBox.Show(JsonSerializer.Serialize(SelectedItem, new JsonSerializerOptions() { WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }));
}

private void LoadRegistry()
{
    Applications.Clear();
    using var section = Registry.LocalMachine.OpenSubKey(@&quot;SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall&quot;);
    foreach (string keyName in section.GetSubKeyNames())
    {
        using var key = section.OpenSubKey(keyName);
        string name = key.GetValue(&quot;DisplayName&quot;)?.ToString();
        if (name != null)
        {
            Applications.Add(new RegistryUninstallInfo
            {
                DisplayName = name,
                DisplayVersion = key.GetValue(&quot;DisplayVersion&quot;)?.ToString(),
                Publisher = key.GetValue(&quot;Publisher&quot;)?.ToString(),
                UninstallString = key.GetValue(&quot;UninstallString&quot;)?.ToString(),
            });
        }
    }
}

}

Костыль SetDoubleBuffered делает так чтобы таблица не притормаживала при отрисовке.

Выглядит это так

введите сюда описание изображения

Если нажать на строчку двойным кликом, появится сообщение

введите сюда описание изображения

База данных как прокси здесь не очень подходит. Но у вас наверняка есть какие-то дополнительные функции в проекте, например вижу "Белый список", вот для них и используйте БД. Полностью дублировать данные в БД, которые лежат в реестре - смысла 0, потому что при обновлении данных вам придется стирать таблицу в БД полностью и записывать туда все заново, так с базами данных не делают.

Чуть подробнее я рассматривал привязки данных здесь

aepot
  • 49,560
  • Cпасибо большое за помощь, осталось только разобраться как реализовать тогда белый и черный списки, как я понимаю лучше сделать отдельные таблицы для программ, которые вошли в белый или черный список и таблицы для тех, которые не вошли, или ка вы думаете? – Андрей Павлов May 22 '22 at 13:20
  • @АндрейПавлов видели строчки типа {FF3FA798-77E6-4622-A230-668E749C08BC} - это называтеся GUID, в .NET даже тип такой есть Guid, правда в секции Uninstall не у всех приложений он есть, но его можно найти Classes Root реестра, если чуть поглубже разобраться. Так вот, его и надо по-хорошему использовать как уникальный идентификатор приложения, на основе них и стоит строить всякие списки. Например я удалил приложение, потом поставил заново, а GUID будет тот же, то есть вы сможете идентифицировать любое приложение даже после переустановки операционной системы полностью - стильно и надежно. – aepot May 22 '22 at 13:24
  • Хорошо, я буду думать над реализацией этого дела, если что попрошу еще совета – Андрей Павлов May 22 '22 at 13:27
  • @АндрейПавлов еще обратите внимание, ваше приложение должно быть строго x64, а не Any CPU, в противном случае при обращении к реестру надо явно задавать RegistryHive – aepot May 22 '22 at 13:30
  • Я понял, учту это – Андрей Павлов May 22 '22 at 13:31
  • @АндрейПавлов про GUID нагуглил http://pyatilistnik.org/kak-uznat-iz-reestra-guid-prilozheniya-v-windows/ – aepot May 22 '22 at 13:32
  • 1
    Спасибо еще раз вам за помощь – Андрей Павлов May 22 '22 at 14:36
  • aepot, вы говорили про использование реестра как базы данных, я сделал отдельный вопрос на эту тему https://ru.stackoverflow.com/q/1414771/430652 – Андрей Павлов May 29 '22 at 06:43