@@ -188,8 +188,18 @@ private static HostsFileEntryModifyResult EnableEntry(HostsFileEntry entry)
188188 return HostsFileEntryModifyResult . BackupError ;
189189 }
190190
191- // Replace the entry in the hosts file
192- var hostsFileLines = File . ReadAllLines ( HostsFilePath ) . ToList ( ) ;
191+ // Enable the entry in the hosts file
192+ List < string > hostsFileLines ;
193+
194+ try
195+ {
196+ hostsFileLines = [ .. File . ReadAllLines ( HostsFilePath ) ] ;
197+ }
198+ catch ( Exception ex )
199+ {
200+ Log . Error ( $ "EnableEntry - Failed to read hosts file: { HostsFilePath } ", ex ) ;
201+ return HostsFileEntryModifyResult . ReadError ;
202+ }
193203
194204 bool entryFound = false ;
195205
@@ -199,7 +209,15 @@ private static HostsFileEntryModifyResult EnableEntry(HostsFileEntry entry)
199209 {
200210 entryFound = true ;
201211
202- hostsFileLines [ i ] = entry . Line . TrimStart ( '#' , ' ' ) ;
212+ hostsFileLines . RemoveAt ( i ) ;
213+ hostsFileLines . Insert ( i , CreateEntryLine ( new HostsFileEntry
214+ {
215+ IsEnabled = true ,
216+ IPAddress = entry . IPAddress ,
217+ Hostname = entry . Hostname ,
218+ Comment = entry . Comment ,
219+ Line = entry . Line
220+ } ) ) ;
203221
204222 break ;
205223 }
@@ -250,8 +268,18 @@ private static HostsFileEntryModifyResult DisableEntry(HostsFileEntry entry)
250268 return HostsFileEntryModifyResult . BackupError ;
251269 }
252270
253- // Replace the entry in the hosts file
254- var hostsFileLines = File . ReadAllLines ( HostsFilePath ) . ToList ( ) ;
271+ // Disable the entry in the hosts file
272+ List < string > hostsFileLines ;
273+
274+ try
275+ {
276+ hostsFileLines = [ .. File . ReadAllLines ( HostsFilePath ) ] ;
277+ }
278+ catch ( Exception ex )
279+ {
280+ Log . Error ( $ "DisableEntry - Failed to read hosts file: { HostsFilePath } ", ex ) ;
281+ return HostsFileEntryModifyResult . ReadError ;
282+ }
255283
256284 bool entryFound = false ;
257285
@@ -261,7 +289,15 @@ private static HostsFileEntryModifyResult DisableEntry(HostsFileEntry entry)
261289 {
262290 entryFound = true ;
263291
264- hostsFileLines [ i ] = "# " + entry . Line ;
292+ hostsFileLines . RemoveAt ( i ) ;
293+ hostsFileLines . Insert ( i , CreateEntryLine ( new HostsFileEntry
294+ {
295+ IsEnabled = false ,
296+ IPAddress = entry . IPAddress ,
297+ Hostname = entry . Hostname ,
298+ Comment = entry . Comment ,
299+ Line = entry . Line
300+ } ) ) ;
265301
266302 break ;
267303 }
@@ -287,6 +323,133 @@ private static HostsFileEntryModifyResult DisableEntry(HostsFileEntry entry)
287323 return HostsFileEntryModifyResult . Success ;
288324 }
289325
326+ /// <summary>
327+ /// Add a hosts file entry asynchronously.
328+ /// </summary>
329+ /// <param name="entry">Entry to add.</param>
330+ /// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was added successfully, otherwise an error result.</returns>"/>
331+ public static Task < HostsFileEntryModifyResult > AddEntryAsync ( HostsFileEntry entry )
332+ {
333+ return Task . Run ( ( ) => AddEntry ( entry ) ) ;
334+ }
335+
336+ /// <summary>
337+ /// Add a hosts file entry.
338+ /// </summary>
339+ /// <param name="entry">Entry to add.</param>
340+ /// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was added successfully, otherwise an error result.</returns>"/>
341+ private static HostsFileEntryModifyResult AddEntry ( HostsFileEntry entry )
342+ {
343+ // Create a backup of the hosts file before making changes
344+ if ( CreateBackup ( ) == false )
345+ {
346+ Log . Error ( "AddEntry - Failed to create backup before adding entry." ) ;
347+ return HostsFileEntryModifyResult . BackupError ;
348+ }
349+
350+ // Add the entry to the hosts file
351+ List < string > hostsFileLines ;
352+
353+ try
354+ {
355+ hostsFileLines = [ .. File . ReadAllLines ( HostsFilePath ) ] ;
356+ }
357+ catch ( Exception ex )
358+ {
359+ Log . Error ( $ "AddEntry - Failed to read hosts file: { HostsFilePath } ", ex ) ;
360+ return HostsFileEntryModifyResult . ReadError ;
361+ }
362+
363+ hostsFileLines . Add ( CreateEntryLine ( entry ) ) ;
364+
365+ try
366+ {
367+ Log . Debug ( $ "AddEntry - Writing changes to hosts file: { HostsFilePath } ") ;
368+ File . WriteAllLines ( HostsFilePath , hostsFileLines ) ;
369+ }
370+ catch ( Exception ex )
371+ {
372+ Log . Error ( $ "AddEntry - Failed to write changes to hosts file: { HostsFilePath } ", ex ) ;
373+ return HostsFileEntryModifyResult . WriteError ;
374+ }
375+
376+ return HostsFileEntryModifyResult . Success ;
377+ }
378+
379+ /// <summary>
380+ /// Edit a hosts file entry asynchronously.
381+ /// </summary>
382+ /// <param name="entry">Entry to edit.</param>
383+ /// <param name="newEntry">New entry to replace the old one.</param>
384+ /// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was edited successfully, otherwise an error result.</returns>"/>
385+ public static Task < HostsFileEntryModifyResult > EditEntryAsync ( HostsFileEntry entry , HostsFileEntry newEntry )
386+ {
387+ return Task . Run ( ( ) => EditEntry ( entry , newEntry ) ) ;
388+ }
389+
390+ /// <summary>
391+ /// Edit a hosts file entry.
392+ /// </summary>
393+ /// <param name="entry">Entry to edit.</param>
394+ /// <param name="newEntry">New entry to replace the old one.</param>
395+ /// <returns><see cref="HostsFileEntryModifyResult.Success"/> if the entry was edited successfully, otherwise an error result.</returns>"/>
396+ private static HostsFileEntryModifyResult EditEntry ( HostsFileEntry entry , HostsFileEntry newEntry )
397+ {
398+ // Create a backup of the hosts file before making changes
399+ if ( CreateBackup ( ) == false )
400+ {
401+ Log . Error ( "EditEntry - Failed to create backup before editing entry." ) ;
402+ return HostsFileEntryModifyResult . BackupError ;
403+ }
404+
405+ // Replace the entry from the hosts file
406+ List < string > hostsFileLines ;
407+
408+ try
409+ {
410+ hostsFileLines = [ .. File . ReadAllLines ( HostsFilePath ) ] ;
411+ }
412+ catch ( Exception ex )
413+ {
414+ Log . Error ( $ "EditEntry - Failed to read hosts file: { HostsFilePath } ", ex ) ;
415+ return HostsFileEntryModifyResult . ReadError ;
416+ }
417+
418+ bool entryFound = false ;
419+
420+ for ( var i = 0 ; i < hostsFileLines . Count ; i ++ )
421+ {
422+ if ( hostsFileLines [ i ] == entry . Line )
423+ {
424+ entryFound = true ;
425+
426+ hostsFileLines . RemoveAt ( i ) ;
427+ hostsFileLines . Insert ( i , CreateEntryLine ( newEntry ) ) ;
428+
429+ break ;
430+ }
431+ }
432+
433+ if ( ! entryFound )
434+ {
435+ Log . Warn ( $ "EditEntry - Entry not found in hosts file: { entry . Line } ") ;
436+ return HostsFileEntryModifyResult . NotFound ;
437+ }
438+
439+ try
440+ {
441+ Log . Debug ( $ "EditEntry - Writing changes to hosts file: { HostsFilePath } ") ;
442+ File . WriteAllLines ( HostsFilePath , hostsFileLines ) ;
443+ }
444+ catch ( Exception ex )
445+ {
446+ Log . Error ( $ "EditEntry - Failed to write changes to hosts file: { HostsFilePath } ", ex ) ;
447+ return HostsFileEntryModifyResult . WriteError ;
448+ }
449+
450+ return HostsFileEntryModifyResult . Success ;
451+ }
452+
290453 /// <summary>
291454 /// Delete a hosts file entry asynchronously.
292455 /// </summary>
@@ -312,7 +475,17 @@ private static HostsFileEntryModifyResult DeleteEntry(HostsFileEntry entry)
312475 }
313476
314477 // Remove the entry from the hosts file
315- var hostsFileLines = File . ReadAllLines ( HostsFilePath ) . ToList ( ) ;
478+ List < string > hostsFileLines ;
479+
480+ try
481+ {
482+ hostsFileLines = [ .. File . ReadAllLines ( HostsFilePath ) ] ;
483+ }
484+ catch ( Exception ex )
485+ {
486+ Log . Error ( $ "DeleteEntry - Failed to read hosts file: { HostsFilePath } ", ex ) ;
487+ return HostsFileEntryModifyResult . ReadError ;
488+ }
316489
317490 bool entryFound = false ;
318491
@@ -344,10 +517,29 @@ private static HostsFileEntryModifyResult DeleteEntry(HostsFileEntry entry)
344517 Log . Error ( $ "DeleteEntry - Failed to write changes to hosts file: { HostsFilePath } ", ex ) ;
345518 return HostsFileEntryModifyResult . WriteError ;
346519 }
347- OnHostsFileChanged ( ) ;
520+
348521 return HostsFileEntryModifyResult . Success ;
349522 }
350523
524+ /// <summary>
525+ /// Create a line for the hosts file entry.
526+ /// </summary>
527+ /// <param name="entry">Entry to create the line for.</param>
528+ /// <returns>Line for the hosts file entry.</returns>
529+ private static string CreateEntryLine ( HostsFileEntry entry )
530+ {
531+ var line = entry . IsEnabled ? "" : "# " ;
532+
533+ line += $ "{ entry . IPAddress } { entry . Hostname } ";
534+
535+ if ( ! string . IsNullOrWhiteSpace ( entry . Comment ) )
536+ {
537+ line += $ " # { entry . Comment } ";
538+ }
539+
540+ return line . Trim ( ) ;
541+ }
542+
351543 /// <summary>
352544 /// Create a "daily" backup of the hosts file (before making a change).
353545 /// </summary>
0 commit comments