Skip to content

Commit 2932333

Browse files
committed
Feature: Add & edit hosts file entry
1 parent 1cdd57d commit 2932333

File tree

2 files changed

+145
-3
lines changed

2 files changed

+145
-3
lines changed

Source/NETworkManager.Models/HostsFileEditor/HostsFileEditor.cs

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,113 @@ private static HostsFileEntryModifyResult DisableEntry(HostsFileEntry entry)
287287
return HostsFileEntryModifyResult.Success;
288288
}
289289

290+
/// <summary>
291+
/// Add a hosts file entry asynchronously.
292+
/// </summary>
293+
/// <param name="entry">Entry to add.</param>
294+
/// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was added successfully, otherwise an error result.</returns>"/>
295+
public static Task<HostsFileEntryModifyResult> AddEntryAsync(HostsFileEntry entry)
296+
{
297+
return Task.Run(() => AddEntry(entry));
298+
}
299+
300+
/// <summary>
301+
/// Add a hosts file entry.
302+
/// </summary>
303+
/// <param name="entry">Entry to add.</param>
304+
/// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was added successfully, otherwise an error result.</returns>"/>
305+
private static HostsFileEntryModifyResult AddEntry(HostsFileEntry entry)
306+
{
307+
// Create a backup of the hosts file before making changes
308+
if (CreateBackup() == false)
309+
{
310+
Log.Error("AddEntry - Failed to create backup before adding entry.");
311+
return HostsFileEntryModifyResult.BackupError;
312+
}
313+
314+
// Add the entry to the hosts file
315+
var hostsFileLines = File.ReadAllLines(HostsFilePath).ToList();
316+
317+
hostsFileLines.Add(CreateEntryLine(entry));
318+
319+
try
320+
{
321+
Log.Debug($"AddEntry - Writing changes to hosts file: {HostsFilePath}");
322+
File.WriteAllLines(HostsFilePath, hostsFileLines);
323+
}
324+
catch (Exception ex)
325+
{
326+
Log.Error($"AddEntry - Failed to write changes to hosts file: {HostsFilePath}", ex);
327+
return HostsFileEntryModifyResult.WriteError;
328+
}
329+
330+
return HostsFileEntryModifyResult.Success;
331+
}
332+
333+
/// <summary>
334+
/// Edit a hosts file entry asynchronously.
335+
/// </summary>
336+
/// <param name="entry">Entry to edit.</param>
337+
/// <param name="newEntry">New entry to replace the old one.</param>
338+
/// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was edited successfully, otherwise an error result.</returns>"/>
339+
public static Task<HostsFileEntryModifyResult> EditEntryAsync(HostsFileEntry entry, HostsFileEntry newEntry)
340+
{
341+
return Task.Run(() => EditEntry(entry, newEntry));
342+
}
343+
344+
/// <summary>
345+
/// Edit a hosts file entry.
346+
/// </summary>
347+
/// <param name="entry">Entry to edit.</param>
348+
/// <param name="newEntry">New entry to replace the old one.</param>
349+
/// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was edited successfully, otherwise an error result.</returns>"/>
350+
public static HostsFileEntryModifyResult EditEntry(HostsFileEntry entry, HostsFileEntry newEntry)
351+
{
352+
// Create a backup of the hosts file before making changes
353+
if (CreateBackup() == false)
354+
{
355+
Log.Error("EditEntry - Failed to create backup before editing entry.");
356+
return HostsFileEntryModifyResult.BackupError;
357+
}
358+
359+
// Replace the entry from the hosts file
360+
var hostsFileLines = File.ReadAllLines(HostsFilePath).ToList();
361+
362+
bool entryFound = false;
363+
364+
for (var i = 0; i < hostsFileLines.Count; i++)
365+
{
366+
if (hostsFileLines[i] == entry.Line)
367+
{
368+
entryFound = true;
369+
370+
hostsFileLines.RemoveAt(i);
371+
hostsFileLines.Insert(i, CreateEntryLine(newEntry));
372+
373+
break;
374+
}
375+
}
376+
377+
if (!entryFound)
378+
{
379+
Log.Warn($"EditEntry - Entry not found in hosts file: {entry.Line}");
380+
return HostsFileEntryModifyResult.NotFound;
381+
}
382+
383+
try
384+
{
385+
Log.Debug($"EditEntry - Writing changes to hosts file: {HostsFilePath}");
386+
File.WriteAllLines(HostsFilePath, hostsFileLines);
387+
}
388+
catch (Exception ex)
389+
{
390+
Log.Error($"EditEntry - Failed to write changes to hosts file: {HostsFilePath}", ex);
391+
return HostsFileEntryModifyResult.WriteError;
392+
}
393+
394+
return HostsFileEntryModifyResult.Success;
395+
}
396+
290397
/// <summary>
291398
/// Delete a hosts file entry asynchronously.
292399
/// </summary>
@@ -344,10 +451,29 @@ private static HostsFileEntryModifyResult DeleteEntry(HostsFileEntry entry)
344451
Log.Error($"DeleteEntry - Failed to write changes to hosts file: {HostsFilePath}", ex);
345452
return HostsFileEntryModifyResult.WriteError;
346453
}
347-
OnHostsFileChanged();
454+
348455
return HostsFileEntryModifyResult.Success;
349456
}
350457

458+
/// <summary>
459+
/// Create a line for the hosts file entry.
460+
/// </summary>
461+
/// <param name="entry">Entry to create the line for.</param>
462+
/// <returns>Line for the hosts file entry.</returns>
463+
private static string CreateEntryLine(HostsFileEntry entry)
464+
{
465+
var line = entry.IsEnabled ? "" : "# ";
466+
467+
line += $"{entry.IPAddress} {entry.Hostname}";
468+
469+
if (!string.IsNullOrWhiteSpace(entry.Comment))
470+
{
471+
line += $" # {entry.Comment}";
472+
}
473+
474+
return line.Trim();
475+
}
476+
351477
/// <summary>
352478
/// Create a "daily" backup of the hosts file (before making a change).
353479
/// </summary>

Source/NETworkManager/ViewModels/HostsFileEditorViewModel.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,19 @@ private async Task AddEntryAction()
295295

296296
var childWindow = new HostsFileEditorEntryChildWindow();
297297

298-
var childWindowViewModel = new HostsFileEditorEntryViewModel(async _ =>
298+
var childWindowViewModel = new HostsFileEditorEntryViewModel(async instance =>
299299
{
300300
childWindow.IsOpen = false;
301301
ConfigurationManager.Current.IsChildWindowOpen = false;
302302

303+
await HostsFileEditor.AddEntryAsync(new HostsFileEntry
304+
{
305+
IsEnabled = instance.IsEnabled,
306+
IPAddress = instance.IPAddress,
307+
Hostname = instance.Hostname,
308+
Comment = instance.Comment
309+
});
310+
303311
IsModifying = false;
304312
}, _ =>
305313
{
@@ -326,11 +334,19 @@ private async Task EditEntryAction()
326334

327335
var childWindow = new HostsFileEditorEntryChildWindow();
328336

329-
var childWindowViewModel = new HostsFileEditorEntryViewModel(async _ =>
337+
var childWindowViewModel = new HostsFileEditorEntryViewModel(async instance =>
330338
{
331339
childWindow.IsOpen = false;
332340
ConfigurationManager.Current.IsChildWindowOpen = false;
333341

342+
await HostsFileEditor.EditEntryAsync(instance.Entry, new HostsFileEntry
343+
{
344+
IsEnabled = instance.IsEnabled,
345+
IPAddress = instance.IPAddress,
346+
Hostname = instance.Hostname,
347+
Comment = instance.Comment
348+
});
349+
334350
IsModifying = false;
335351
}, _ =>
336352
{

0 commit comments

Comments
 (0)