mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 04:07:40 +02:00
[Hosts] Handle hidden hosts file (#34308)
* handle hidden hosts file * don't remove hidden attribute
This commit is contained in:
committed by
GitHub
parent
1cbf512ed0
commit
9af757f5ce
@@ -2,6 +2,7 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
using System.IO.Abstractions.TestingHelpers;
|
using System.IO.Abstractions.TestingHelpers;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -248,25 +249,53 @@ namespace Hosts.Tests
|
|||||||
{
|
{
|
||||||
var fileSystem = new CustomMockFileSystem();
|
var fileSystem = new CustomMockFileSystem();
|
||||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||||
var hostsFile = new MockFileData(string.Empty);
|
|
||||||
hostsFile.Attributes = System.IO.FileAttributes.ReadOnly;
|
var hostsFile = new MockFileData(string.Empty)
|
||||||
|
{
|
||||||
|
Attributes = FileAttributes.ReadOnly,
|
||||||
|
};
|
||||||
|
|
||||||
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
||||||
|
|
||||||
await Assert.ThrowsExceptionAsync<ReadOnlyHostsException>(async () => await service.WriteAsync("# Empty hosts file", Enumerable.Empty<Entry>()));
|
await Assert.ThrowsExceptionAsync<ReadOnlyHostsException>(async () => await service.WriteAsync("# Empty hosts file", Enumerable.Empty<Entry>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Remove_ReadOnly()
|
public void Remove_ReadOnly_Attribute()
|
||||||
{
|
{
|
||||||
var fileSystem = new CustomMockFileSystem();
|
var fileSystem = new CustomMockFileSystem();
|
||||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||||
var hostsFile = new MockFileData(string.Empty);
|
|
||||||
hostsFile.Attributes = System.IO.FileAttributes.ReadOnly;
|
var hostsFile = new MockFileData(string.Empty)
|
||||||
|
{
|
||||||
|
Attributes = FileAttributes.ReadOnly,
|
||||||
|
};
|
||||||
|
|
||||||
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
||||||
|
|
||||||
service.RemoveReadOnly();
|
service.RemoveReadOnlyAttribute();
|
||||||
var readOnly = fileSystem.FileInfo.FromFileName(service.HostsFilePath).Attributes.HasFlag(System.IO.FileAttributes.ReadOnly);
|
|
||||||
|
var readOnly = fileSystem.FileInfo.FromFileName(service.HostsFilePath).Attributes.HasFlag(FileAttributes.ReadOnly);
|
||||||
Assert.IsFalse(readOnly);
|
Assert.IsFalse(readOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task Save_Hidden_Hosts()
|
||||||
|
{
|
||||||
|
var fileSystem = new CustomMockFileSystem();
|
||||||
|
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||||
|
|
||||||
|
var hostsFile = new MockFileData(string.Empty)
|
||||||
|
{
|
||||||
|
Attributes = FileAttributes.Hidden,
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
||||||
|
|
||||||
|
await service.WriteAsync("# Empty hosts file", Enumerable.Empty<Entry>());
|
||||||
|
|
||||||
|
var hidden = fileSystem.FileInfo.FromFileName(service.HostsFilePath).Attributes.HasFlag(FileAttributes.Hidden);
|
||||||
|
Assert.IsTrue(hidden);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace HostsUILib.Helpers
|
|||||||
public class HostsService : IHostsService, IDisposable
|
public class HostsService : IHostsService, IDisposable
|
||||||
{
|
{
|
||||||
private const string _backupSuffix = $"_PowerToysBackup_";
|
private const string _backupSuffix = $"_PowerToysBackup_";
|
||||||
|
private const int _defaultBufferSize = 4096; // From System.IO.File source code
|
||||||
|
|
||||||
private readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
@@ -197,7 +198,16 @@ namespace HostsUILib.Helpers
|
|||||||
_backupDone = true;
|
_backupDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _fileSystem.File.WriteAllLinesAsync(HostsFilePath, lines, Encoding);
|
// FileMode.OpenOrCreate is necessary to prevent UnauthorizedAccessException when the hosts file is hidden
|
||||||
|
using var stream = _fileSystem.FileStream.Create(HostsFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, _defaultBufferSize, FileOptions.Asynchronous);
|
||||||
|
using var writer = new StreamWriter(stream, Encoding);
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
await writer.WriteLineAsync(line.AsMemory());
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.SetLength(stream.Position);
|
||||||
|
await writer.FlushAsync();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -292,7 +302,7 @@ namespace HostsUILib.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveReadOnly()
|
public void RemoveReadOnlyAttribute()
|
||||||
{
|
{
|
||||||
var fileInfo = _fileSystem.FileInfo.FromFileName(HostsFilePath);
|
var fileInfo = _fileSystem.FileInfo.FromFileName(HostsFilePath);
|
||||||
if (fileInfo.IsReadOnly)
|
if (fileInfo.IsReadOnly)
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ namespace HostsUILib.Helpers
|
|||||||
|
|
||||||
void OpenHostsFile();
|
void OpenHostsFile();
|
||||||
|
|
||||||
void RemoveReadOnly();
|
void RemoveReadOnlyAttribute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ namespace HostsUILib.ViewModels
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
public void OverwriteHosts()
|
public void OverwriteHosts()
|
||||||
{
|
{
|
||||||
_hostsService.RemoveReadOnly();
|
_hostsService.RemoveReadOnlyAttribute();
|
||||||
_ = Task.Run(SaveAsync);
|
_ = Task.Run(SaveAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user