├── .gitignore ├── DeviceIOControl ├── Constant.cs ├── DeviceIOControl.csproj ├── DeviceIOControl.csproj.user ├── DeviceIoControl.cs ├── Disc │ ├── Disc.cs │ ├── Perfomance.cs │ └── Smart │ │ ├── AttributeThresholds.cs │ │ ├── IdentifyDma.cs │ │ └── SmartInfoCollection.cs ├── FileSystem │ └── FileSystem.cs ├── LogicalDrive.cs ├── Native │ ├── AtaApi.cs │ ├── DiscApi.cs │ ├── FsctlApi.cs │ ├── Methods.cs │ ├── StorageApi.cs │ ├── VolumeApi.cs │ └── WinApi.cs ├── PinnedBufferReader.cs ├── Properties │ └── PublishProfiles │ │ ├── FolderProfile.pubxml │ │ └── FolderProfile.pubxml.user ├── Storage │ ├── Properties.cs │ └── Storage.cs ├── Utils.cs └── Volume │ └── Volume.cs ├── Hardware ├── Computer.cs ├── Hardware.csproj └── Windows │ ├── DeviceIoInfo │ ├── Device.cs │ ├── DeviceInfo.cs │ └── VendorEnum.cs │ ├── Network │ ├── Adapter.cs │ └── NetworkInfo.cs │ └── RAM │ ├── MemoryStatusEx.cs │ └── NativeMethods.cs ├── LICENSE ├── README.md ├── SysMonAvalonia.sln ├── SysMonAvalonia ├── App.axaml ├── App.axaml.cs ├── Assets │ ├── Fonts │ │ └── SegoeUILight.ttf │ ├── Locale │ │ ├── en.json │ │ └── ru.json │ ├── Styles │ │ ├── Dark.xaml │ │ └── Light.xaml │ ├── WeatherIcons │ │ ├── Black │ │ │ ├── 30 │ │ │ │ ├── weather_0.png │ │ │ │ ├── weather_1.png │ │ │ │ ├── weather_10.png │ │ │ │ ├── weather_11.png │ │ │ │ ├── weather_12.png │ │ │ │ ├── weather_13.png │ │ │ │ ├── weather_14.png │ │ │ │ ├── weather_15.png │ │ │ │ ├── weather_16.png │ │ │ │ ├── weather_17.png │ │ │ │ ├── weather_18.png │ │ │ │ ├── weather_19.png │ │ │ │ ├── weather_2.png │ │ │ │ ├── weather_20.png │ │ │ │ ├── weather_21.png │ │ │ │ ├── weather_22.png │ │ │ │ ├── weather_23.png │ │ │ │ ├── weather_3.png │ │ │ │ ├── weather_4.png │ │ │ │ ├── weather_5.png │ │ │ │ ├── weather_6.png │ │ │ │ ├── weather_7.png │ │ │ │ ├── weather_8.png │ │ │ │ └── weather_9.png │ │ │ └── 65 │ │ │ │ ├── weather_0.png │ │ │ │ ├── weather_1.png │ │ │ │ ├── weather_10.png │ │ │ │ ├── weather_11.png │ │ │ │ ├── weather_12.png │ │ │ │ ├── weather_13.png │ │ │ │ ├── weather_14.png │ │ │ │ ├── weather_15.png │ │ │ │ ├── weather_16.png │ │ │ │ ├── weather_17.png │ │ │ │ ├── weather_18.png │ │ │ │ ├── weather_19.png │ │ │ │ ├── weather_2.png │ │ │ │ ├── weather_20.png │ │ │ │ ├── weather_21.png │ │ │ │ ├── weather_22.png │ │ │ │ ├── weather_23.png │ │ │ │ ├── weather_3.png │ │ │ │ ├── weather_4.png │ │ │ │ ├── weather_5.png │ │ │ │ ├── weather_6.png │ │ │ │ ├── weather_7.png │ │ │ │ ├── weather_8.png │ │ │ │ └── weather_9.png │ │ └── White │ │ │ ├── 30 │ │ │ ├── weather_0.png │ │ │ ├── weather_1.png │ │ │ ├── weather_10.png │ │ │ ├── weather_11.png │ │ │ ├── weather_12.png │ │ │ ├── weather_13.png │ │ │ ├── weather_14.png │ │ │ ├── weather_15.png │ │ │ ├── weather_16.png │ │ │ ├── weather_17.png │ │ │ ├── weather_18.png │ │ │ ├── weather_19.png │ │ │ ├── weather_2.png │ │ │ ├── weather_20.png │ │ │ ├── weather_21.png │ │ │ ├── weather_22.png │ │ │ ├── weather_23.png │ │ │ ├── weather_3.png │ │ │ ├── weather_4.png │ │ │ ├── weather_5.png │ │ │ ├── weather_6.png │ │ │ ├── weather_7.png │ │ │ ├── weather_8.png │ │ │ └── weather_9.png │ │ │ └── 65 │ │ │ ├── weather_0.png │ │ │ ├── weather_1.png │ │ │ ├── weather_10.png │ │ │ ├── weather_11.png │ │ │ ├── weather_12.png │ │ │ ├── weather_13.png │ │ │ ├── weather_14.png │ │ │ ├── weather_15.png │ │ │ ├── weather_16.png │ │ │ ├── weather_17.png │ │ │ ├── weather_18.png │ │ │ ├── weather_19.png │ │ │ ├── weather_2.png │ │ │ ├── weather_20.png │ │ │ ├── weather_21.png │ │ │ ├── weather_22.png │ │ │ ├── weather_23.png │ │ │ ├── weather_3.png │ │ │ ├── weather_4.png │ │ │ ├── weather_5.png │ │ │ ├── weather_6.png │ │ │ ├── weather_7.png │ │ │ ├── weather_8.png │ │ │ └── weather_9.png │ └── icon.ico ├── Converters │ ├── BitmapValueConverter.cs │ ├── DataValueConverter.cs │ ├── DeviceIoValueConverter.cs │ ├── NetworkValueConvert.cs │ └── SettingsValueConverter.cs ├── Data │ ├── ComboData.cs │ ├── DeviceIoData.cs │ ├── ForecastData.cs │ ├── SettingData.cs │ └── WeatherData.cs ├── Localization │ └── Language.cs ├── Models │ ├── ChartModel.cs │ ├── ComboModel.cs │ ├── DeviceIoModel.cs │ ├── ForecastModel.cs │ ├── SettingModel.cs │ └── WeatherModel.cs ├── NLog.config ├── Program.cs ├── Services │ └── AppService.cs ├── SysMonAvalonia.csproj ├── SysMonAvalonia.csproj.user ├── ViewLocator.cs ├── ViewModels │ ├── ComboWidgetViewModel.cs │ ├── DeviceIoWidgetViewModel.cs │ ├── SettingViewModel.cs │ ├── ViewModelBase.cs │ └── WeatherWidgetViewModel.cs ├── Views │ ├── ComboWidgetView.axaml │ ├── ComboWidgetView.axaml.cs │ ├── DeviceIoWidgetView.axaml │ ├── DeviceIoWidgetView.axaml.cs │ ├── SettingView.axaml │ ├── SettingView.axaml.cs │ ├── WeatherWidgetView.axaml │ └── WeatherWidgetView.axaml.cs ├── app.manifest └── nuget.config └── Weather ├── Helper.cs ├── LocationData.cs ├── NLog.config ├── Providers ├── AccuWeather.cs ├── Gismeteo.cs ├── IProvider.cs ├── OpenWeatherMap.cs ├── Providers.cs ├── WorldWeatherOnline.cs └── Wunderground.cs ├── Weather.csproj ├── WeatherData.cs └── WindUnitEnum.cs /.gitignore: -------------------------------------------------------------------------------- 1 | /.git/ 2 | /.vs/ 3 | /DeviceIOControl/obj/ 4 | /DeviceIOControl/bin/ 5 | /Hardware/obj/ 6 | /Hardware/bin/ 7 | /SysMonAvalonia/obj/ 8 | /SysMonAvalonia/bin/ 9 | /Weather/obj/ 10 | /Weather/bin/ 11 | /SysMonAvalonia/Properties/ 12 | -------------------------------------------------------------------------------- /DeviceIOControl/DeviceIOControl.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | AnyCPU 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /DeviceIOControl/DeviceIOControl.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | <_LastSelectedProfileId>D:\SourcesCode\DeviceIOControl\DeviceIOControl\Properties\PublishProfiles\FolderProfile.pubxml 5 | 6 | -------------------------------------------------------------------------------- /DeviceIOControl/Disc/Disc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.ComponentModel; 4 | using DeviceIOControl.Native; 5 | using DeviceIOControl.Disc.Smart; 6 | 7 | namespace DeviceIOControl.Disc 8 | { 9 | public class Disc 10 | { 11 | private readonly DeviceIoControl _device; 12 | private SmartInfoCollection _smart; 13 | private DiscApi.GETVERSIONINPARAMS? _version; 14 | private DiscApi.DISK_GEOMETRY_EX? _driveGeometryEx; 15 | private Boolean? _isWritable; 16 | /// Device 17 | private DeviceIoControl Device { get { return this._device; } } 18 | 19 | /// Returns version information, a capabilities mask, and a bitmask for the device. 20 | /// This IOCTL must be handled by drivers that support Self-Monitoring Analysis and Reporting Technology (SMART). 21 | public DiscApi.GETVERSIONINPARAMS? Version 22 | { 23 | get 24 | { 25 | if (this._version == null) 26 | { 27 | DiscApi.GETVERSIONINPARAMS prms; 28 | if (this.Device.IoControl(Constant.IOCTL_DISC.SMART_GET_VERSION, null, out prms)) 29 | this._version = prms; 30 | else 31 | this._version = prms; 32 | } 33 | return this._version.Value.Equals(default(DiscApi.GETVERSIONINPARAMS)) ? (DiscApi.GETVERSIONINPARAMS?)null : this._version.Value; 34 | } 35 | } 36 | 37 | /// Returns information about the physical disk's geometry (media type, number of cylinders, tracks per cylinder, sectors per track, and bytes per sector). 38 | public DiscApi.DISK_GEOMETRY_EX DriveGeometryEx 39 | { 40 | get 41 | { 42 | if (this._driveGeometryEx == null) 43 | this._driveGeometryEx = this.Device.IoControl( 44 | Constant.IOCTL_DISC.GET_DRIVE_GEOMETRY_EX, 45 | null); 46 | return this._driveGeometryEx.Value; 47 | } 48 | } 49 | 50 | /// Self-Monitoring Analysis and Reporting Technology info 51 | /// Smart can be null if SAMRT commands not supported 52 | public SmartInfoCollection Smart 53 | { 54 | get 55 | { 56 | if (this._smart == null && this.Version != null && this.Version.Value.IsSmartSupported) 57 | this._smart = new SmartInfoCollection(this.Device); 58 | return this._smart; 59 | } 60 | } 61 | 62 | /// Determines whether the specified disk is writable. 63 | /// WinAPI operation fails. 64 | public Boolean IsWritable 65 | { 66 | get 67 | { 68 | if (this._isWritable == null) 69 | if (this.Device.IoControl(Constant.IOCTL_DISC.IS_WRITABLE)) 70 | this._isWritable = true; 71 | else 72 | { 73 | Int32 error = Marshal.GetLastWin32Error(); 74 | if (error == (Int32)Constant.ERROR.WRITE_PROTECT) 75 | this._isWritable = false; 76 | else 77 | throw new Win32Exception(error); 78 | } 79 | return this._isWritable.Value; 80 | } 81 | } 82 | 83 | /// Create instance of disc IO control commands class 84 | /// Device 85 | internal Disc(DeviceIoControl device) 86 | { 87 | this._device = device; 88 | } 89 | 90 | /// Get disc performance managed 91 | /// Perfomance manager 92 | public Performance GetDiscPerformance() 93 | { 94 | return new Performance(this.Device); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /DeviceIOControl/Disc/Perfomance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DeviceIOControl.Native; 3 | 4 | namespace DeviceIOControl.Disc 5 | { 6 | /// Collect perfomance counters from HDD 7 | public class Performance : IDisposable 8 | { 9 | private readonly DeviceIoControl _device; 10 | private Boolean _counterIsActive = false; 11 | 12 | /// Device 13 | private DeviceIoControl Device { get { return this._device; } } 14 | 15 | /// Create instance of deviceperfomance counters 16 | /// device 17 | internal Performance(DeviceIoControl device) 18 | { 19 | this._device = device; 20 | } 21 | /// Query performance counters 22 | /// Performance counters 23 | public DiscApi.DISK_PERFORMANCE QueryPerformanceInfo() 24 | { 25 | DiscApi.DISK_PERFORMANCE result = this.Device.IoControl( 26 | Constant.IOCTL_DISC.PERFORMANCE, 27 | null); 28 | this._counterIsActive = true; 29 | return result; 30 | } 31 | /// Close perfomace counters manager 32 | public void Dispose() 33 | { 34 | if (this._counterIsActive) 35 | { 36 | this.Device.IoControl( 37 | Constant.IOCTL_DISC.PERFORMANCE_OFF, 38 | null); 39 | this._counterIsActive = false; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DeviceIOControl/Disc/Smart/AttributeThresholds.cs: -------------------------------------------------------------------------------- 1 | using DeviceIOControl.Native; 2 | 3 | namespace DeviceIOControl.Disc.Smart 4 | { 5 | /// S.M.A.R.T. attribute & threshold value 6 | public struct AttributeThresholds 7 | { 8 | private readonly DiscApi.DRIVEATTRIBUTE _attribute; 9 | private readonly DiscApi.ATTRTHRESHOLD _threshold; 10 | /// Attribute value 11 | public DiscApi.DRIVEATTRIBUTE Attribute { get { return this._attribute; } } 12 | /// Threshold value 13 | public DiscApi.ATTRTHRESHOLD Threshold { get { return this._threshold; } } 14 | 15 | internal AttributeThresholds(DiscApi.DRIVEATTRIBUTE attribute, DiscApi.ATTRTHRESHOLD threshold) 16 | : this() 17 | { 18 | this._attribute = attribute; 19 | this._threshold = threshold; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DeviceIOControl/Disc/Smart/IdentifyDma.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace DeviceIOControl.Disc.Smart 5 | { 6 | /// Device DMA/UDMA modes 7 | public struct IdentifyDma 8 | { 9 | /// DMA type 10 | public enum DmaType 11 | { 12 | /// UDMA 13 | UDma = 0, 14 | /// DMA 15 | Dma = 1, 16 | } 17 | private readonly DmaType _type; 18 | private readonly SmartInfoCollection _info; 19 | /// Device info 20 | private SmartInfoCollection Info { get { return this._info; } } 21 | /// Type of DMA 22 | private DmaType Type { get { return this._type; } } 23 | /// DMA/UDMA structure indexes 24 | private static Int32[] DmaIndex = new Int32[] { 88, 63, }; 25 | /// DMA/UDMA structure max bit pos 26 | private static Int32[] DmaMaxPos = new Int32[] { 5, 2, }; 27 | /// Max DMA/UDMA mode supported 28 | public Int64? Max 29 | { 30 | get 31 | { 32 | Int64 pos = this.GetHighBitPos(false); 33 | return pos != 1 ? pos : (Int64?)null; 34 | } 35 | } 36 | /// DMA/UDMA mode selected 37 | public Int64? Selected 38 | { 39 | get 40 | { 41 | Int64 pos = this.GetHighBitPos(true); 42 | return this.Max.HasValue && pos != -1 ? pos : (Int64?)null; 43 | } 44 | } 45 | 46 | /// Create instance of DMA/UDMA info structure 47 | /// Device info 48 | /// DMA/UDMA 49 | public IdentifyDma(SmartInfoCollection info, DmaType type) 50 | { 51 | this._info = info; 52 | this._type = type; 53 | } 54 | private Int64 GetHighBitPos(Boolean isSelected) 55 | { 56 | return 0; 57 | /*Int32 index = IdentifyDma.DmaIndex[(Int32)this.Type]; 58 | Int32 maxPos = IdentifyDma.DmaMaxPos[(Int32)this.Type]; 59 | return Utils.HighBitPos( 60 | isSelected ? this.Info.SystemParams[index] >> 8 : this.Info.SystemParams[index], 61 | maxPos);*/ 62 | } 63 | /// DMA/UDMA values as string 64 | /// 65 | public override String ToString() 66 | { 67 | Int64? max = this.Max; 68 | Int64? selected = this.Selected; 69 | 70 | String result = String.Empty; 71 | if (max.HasValue) 72 | { 73 | result = String.Format(CultureInfo.CurrentUICulture, "Max {0} mode supported {1}{2}", 74 | this.Type.ToString().ToUpperInvariant(), 75 | max, 76 | max > 0 ? " and below" : String.Empty); 77 | if (selected.HasValue) 78 | result += Environment.NewLine + String.Format(CultureInfo.CurrentUICulture, "{0} mode selected {1}", 79 | this.Type.ToString().ToUpperInvariant(), 80 | selected); 81 | } 82 | return result; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /DeviceIOControl/FileSystem/FileSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.ComponentModel; 5 | using DeviceIOControl.Native; 6 | 7 | namespace DeviceIOControl.FileSystem 8 | { 9 | /// File system control commands 10 | public class FileSystem 11 | { 12 | private readonly DeviceIoControl _device; 13 | private FsctlApi.NTFS_VOLUME_DATA_BUFFER? _volumeData; 14 | 15 | /// Device 16 | private DeviceIoControl Device { get { return this._device; } } 17 | 18 | /// Represents volume data. 19 | public FsctlApi.NTFS_VOLUME_DATA_BUFFER VolumeData 20 | { 21 | get 22 | { 23 | return (this._volumeData == null 24 | ? this._volumeData = this.Device.IoControl( 25 | Constant.FSCTL.GET_NTFS_VOLUME_DATA, null) 26 | : this._volumeData).Value; 27 | } 28 | } 29 | 30 | /// Determines whether the specified volume is mounted 31 | public Boolean IsVolumeMounted 32 | { 33 | get { return this.Device.IoControl(Constant.FSCTL.IS_VOLUME_MOUNTED); } 34 | } 35 | 36 | /// Create instance of file system IO commands class 37 | /// Device 38 | public FileSystem(DeviceIoControl device) 39 | { 40 | this._device = device; 41 | } 42 | 43 | /// Retrieves a bitmap of occupied and available clusters on a volume. 44 | /// Represents the occupied and available clusters on a disk. 45 | public IEnumerable GetVolumeBitmap() 46 | { 47 | UInt64 startingLcn = 0; 48 | UInt32 bytesReturned; 49 | Boolean moreDataAvailable = false; 50 | 51 | do 52 | { 53 | FsctlApi.VOLUME_BITMAP_BUFFER part = this.GetVolumeBitmap(startingLcn, out bytesReturned, out moreDataAvailable); 54 | if (moreDataAvailable) 55 | startingLcn = bytesReturned; 56 | yield return part; 57 | } while (moreDataAvailable); 58 | } 59 | 60 | /// Метод не работает и вываливается по: 0x00000057 - The parameter is incorrect 61 | /// 62 | /// 63 | public FsctlApi.FIND_BY_SID_OUTPUT FindFilesBySid(String accountName) 64 | { 65 | if (String.IsNullOrEmpty(accountName)) 66 | throw new ArgumentNullException("accountName"); 67 | 68 | FsctlApi.FIND_BY_SID_DATA fsInParams = new FsctlApi.FIND_BY_SID_DATA(); 69 | fsInParams.Restart = 1; 70 | fsInParams.Sid = Methods.LookupAccountName(accountName); 71 | 72 | //var currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); 73 | //System.Security.Principal.SecurityIdentifier managedSid = new System.Security.Principal.SecurityIdentifier(fsInParams.Sid, 0); 74 | 75 | UInt32 bytesReturned; 76 | FsctlApi.FIND_BY_SID_OUTPUT result; 77 | Boolean resultCode = this.Device.IoControl( 78 | Constant.FSCTL.FIND_FILES_BY_SID, 79 | fsInParams, 80 | out bytesReturned, 81 | out result); 82 | 83 | if (resultCode) 84 | return result; 85 | else 86 | { 87 | Int32 error = Marshal.GetLastWin32Error(); 88 | throw new Win32Exception(error); 89 | } 90 | } 91 | 92 | /// Retrieves a bitmap of occupied and available clusters on a volume. 93 | /// 94 | /// The LCN from which the operation should start when describing a bitmap. 95 | /// This member will be rounded down to a file-system-dependent rounding boundary, and that value will be returned. 96 | /// Its value should be an integral multiple of eight. 97 | /// 98 | /// Returned length of bytes 99 | /// Not all data readed 100 | /// Win32 Exception occured. See winerror.h for details 101 | /// Represents the occupied and available clusters on a disk. 102 | public FsctlApi.VOLUME_BITMAP_BUFFER GetVolumeBitmap(UInt64 startingLcn, out UInt32 bytesReturned, out Boolean moreDataAvailable) 103 | { 104 | FsctlApi.STARTING_LCN_INPUT_BUFFER fsInParams = new FsctlApi.STARTING_LCN_INPUT_BUFFER(); 105 | fsInParams.StartingLcn = startingLcn;//0xA000; 106 | 107 | FsctlApi.VOLUME_BITMAP_BUFFER result; 108 | Boolean resultCode = this.Device.IoControl( 109 | Constant.FSCTL.GET_VOLUME_BITMAP, 110 | fsInParams, 111 | out bytesReturned, 112 | out result); 113 | 114 | if (resultCode) 115 | moreDataAvailable = false; 116 | else 117 | { 118 | Int32 error = Marshal.GetLastWin32Error(); 119 | if (error == (Int32)Constant.ERROR.MORE_DATA) 120 | moreDataAvailable = true; 121 | else 122 | throw new Win32Exception(error); 123 | } 124 | return result; 125 | } 126 | 127 | /// Retrieves the information from various file system performance counters. 128 | /// Contains statistical information from the file system. 129 | public FsctlApi.FILESYSTEM_STATISTICS GetStatistics() 130 | { 131 | UInt32 bytesReturned; 132 | FsctlApi.FILESYSTEM_STATISTICS result = this.Device.IoControl( 133 | Constant.FSCTL.FILESYSTEM_GET_STATISTICS, 134 | null, 135 | out bytesReturned); 136 | 137 | /*const UInt32 SizeOfFileSystemStat = 56; 138 | using(BytesReader reader = new BytesReader(result.Data)) 139 | { 140 | UInt32 padding = 0; 141 | switch(result.FileSystemType) 142 | { 143 | case FsctlAPI.FILESYSTEM_STATISTICS.FILESYSTEM_STATISTICS_TYPE.NTFS: 144 | FsctlAPI.NTFS_STATISTICS ntfsStat = reader.BytesToStructure(ref padding); 145 | break; 146 | case FsctlAPI.FILESYSTEM_STATISTICS.FILESYSTEM_STATISTICS_TYPE.FAT: 147 | FsctlAPI.FAT_STATISTICS fatStat = reader.BytesToStructure(ref padding); 148 | break; 149 | case FsctlAPI.FILESYSTEM_STATISTICS.FILESYSTEM_STATISTICS_TYPE.EXFAT: 150 | FsctlAPI.EXFAT_STATISTICS exFatStat = reader.BytesToStructure(ref padding); 151 | break; 152 | } 153 | }*/ 154 | return result; 155 | } 156 | 157 | /// Retrieves the information from various file system performance counters 158 | /// Support for this structure started with Windows 10 159 | /// Contains statistical information from the file system 160 | public FsctlApi.FILESYSTEM_STATISTICS_EX GetStatisticsEx() 161 | { 162 | UInt32 bytesReturned; 163 | FsctlApi.FILESYSTEM_STATISTICS_EX result = this.Device.IoControl( 164 | Constant.FSCTL.FILESYSTEM_GET_STATISTICS, 165 | null, 166 | out bytesReturned); 167 | 168 | return result; 169 | } 170 | 171 | /// 172 | /// Locks a volume if it is not in use. 173 | /// A locked volume can be accessed only through handles to the file object (*hDevice) that locks the volume. 174 | /// 175 | /// Device exception 176 | /// Lock action status 177 | public void LockVolume() 178 | { 179 | this.Device.IoControl(Constant.FSCTL.LOCK_VOLUME, null); 180 | } 181 | 182 | /// Unlocks a volume. 183 | /// Device exception 184 | /// Unlock action status 185 | public void UnlockVolume() 186 | { 187 | this.Device.IoControl(Constant.FSCTL.UNLOCK_VOLUME, null); 188 | } 189 | 190 | /// Dismounts a volume regardless of whether or not the volume is currently in use. 191 | /// Device exception 192 | /// Dismount action status 193 | public void DismountVolume() 194 | { 195 | this.Device.IoControl(Constant.FSCTL.DISMOUNT_VOLUME, null); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /DeviceIOControl/LogicalDrive.cs: -------------------------------------------------------------------------------- 1 | using DeviceIOControl.Native; 2 | 3 | namespace DeviceIOControl 4 | { 5 | public struct LogicalDrive 6 | { 7 | private readonly string _name; 8 | 9 | private readonly WinApi.DRIVE _type; 10 | 11 | public string Name => _name; 12 | 13 | public WinApi.DRIVE Type => _type; 14 | 15 | internal LogicalDrive(string name, WinApi.DRIVE type) 16 | { 17 | this = default(LogicalDrive); 18 | _name = name; 19 | _type = type; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DeviceIOControl/Native/AtaApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace DeviceIOControl.Native 5 | { 6 | /// ATA IOCTL structures 7 | public struct AtaApi 8 | { 9 | /// The ATA_PASS_THROUGH_EX structure is used in conjunction with an request to instruct the port driver to send an embedded ATA command to the target device. 10 | [StructLayout(LayoutKind.Sequential)] 11 | public struct ATA_PASS_THROUGH_EX 12 | { 13 | /// Indicates the direction of data transfer and specifies the kind of operation to be performed. 14 | [Flags] 15 | public enum AtaPassThroughFlags : ushort 16 | { 17 | /// Wait for DRDY status from the device before sending the command to the device. 18 | DRDY_REQUIRED = 1 << 0, 19 | /// Read data from the device. 20 | DATA_IN = 1 << 1, 21 | /// Write data to the device. 22 | DATA_OUT = 1 << 2, 23 | /// The ATA command to be sent uses the 48-bit logical block address (LBA) feature set. 24 | /// When this flag is set, the contents of the PreviousTaskFile member in the ATA_PASS_THROUGH_EX structure should be valid. 25 | _48BIT_COMMAND = 1 << 3, 26 | /// Set the transfer mode to DMA. 27 | USE_DMA = 1 << 4, 28 | /// Read single sector only. 29 | NO_MULTIPLE = 1 << 5, 30 | } 31 | /// Specifies the length in bytes of the ATA_PASS_THROUGH_EX structure. 32 | public UInt16 Length; 33 | /// Indicates the direction of data transfer and specifies the kind of operation to be performed. 34 | public AtaPassThroughFlags AtaFlags; 35 | /// Contains an integer that indicates the IDE port or bus for the request. This value is set by the port driver. 36 | public Byte PathId; 37 | /// Contains an integer that indicates the target device on the bus. This value is set by the port driver. 38 | public Byte TargetId; 39 | /// Indicates the logical unit number of the device. This value is set by the port driver. 40 | public Byte Lun; 41 | /// Reserved for future use. 42 | public Byte ReservedAsUchar; 43 | /// 44 | /// Indicates the size, in bytes, of the data buffer. 45 | /// If an underrun occurs, the miniport driver must update this member to the number of bytes that were actually transferred. 46 | /// 47 | public UInt32 DataTransferLength; 48 | /// Indicates the number of seconds that are allowed for the request to execute before the OS-specific port driver determines that the request has timed out. 49 | public UInt32 TimeOutValue; 50 | /// Reserved for future use. 51 | public UInt32 ReservedAsUlong; 52 | /// Specifies the offset, in bytes, from the beginning of this structure to the data buffer. 53 | public UInt32 DataBufferOffset; 54 | /// Specifies the contents of the task file input registers prior to the current pass-through command. 55 | /// This member is not used when the ATA_FLAGS_48BIT_COMMAND flag is not set. 56 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 57 | public Byte[] PreviousTaskFile; 58 | /// Specifies the content of the task file register on both input and output. 59 | /// http://msdn.microsoft.com/en-us/library/windows/hardware/ff551323%28v=vs.85%29.aspx 60 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 61 | public Byte[] CurrentTaskFile; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /DeviceIOControl/Native/VolumeApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace DeviceIOControl.Native 5 | { 6 | /// Volume IOCTL structures 7 | public struct VolumeApi 8 | { 9 | /// Represents a physical location on a disk. It is the output buffer for the control code. 10 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365727%28v=vs.85%29.aspx 11 | [StructLayout(LayoutKind.Sequential)] 12 | public struct VOLUME_DISK_EXTENTS 13 | { 14 | /// Represents a disk extent. 15 | [StructLayout(LayoutKind.Sequential)] 16 | public struct DISK_EXTENT 17 | { 18 | /// The number of the disk that contains this extent. 19 | /// This is the same number that is used to construct the name of the disk, for example, the X in "\\?\PhysicalDriveX" or "\\?\HarddiskX". 20 | public UInt32 DiskNumber; 21 | /// The offset from the beginning of the disk to the extent, in bytes. 22 | public UInt64 StartingOffset; 23 | /// The number of bytes in this extent. 24 | public UInt64 ExtentLength; 25 | } 26 | /// The number of disks in the volume (a volume can span multiple disks). 27 | /// 28 | /// An extent is a contiguous run of sectors on one disk. 29 | /// When the number of extents returned is greater than one (1), the error code ERROR_MORE_DATA is returned. 30 | /// You should call DeviceIoControl again, allocating enough buffer space based on the value of NumberOfDiskExtents after the first DeviceIoControl call. 31 | /// 32 | public UInt32 NumberOfDiskExtents; 33 | /// An array of DISK_EXTENT structures. 34 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 35 | public DISK_EXTENT[] Extents;//TODO: Если дисков больше 10, то метод DeviceIoControl вернёт ERROR_MORE_DATA. 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DeviceIOControl/Native/WinApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DeviceIOControl.Native 4 | { 5 | /// Native structures 6 | public struct WinApi 7 | { 8 | /// The MEDIA_TYPE enumerators are used in conjunction with the IOCTL_DISK_FORMAT_TRACKS request to format the specified set of contiguous tracks on the disk. 9 | /// Removable disks include zip drivers, jaz drives, magneto-optical (MO) drives, and LS-120 floppies as well as regular floppies. 10 | public enum MEDIA_TYPE 11 | { 12 | /// Format is unknown 13 | Unknown, 14 | /// 5.25", 1.2MB, 512 bytes/sector 15 | F5_1Pt2_512, 16 | /// 3.5", 1.44MB, 512 bytes/sector 17 | F3_1Pt44_512, 18 | /// 3.5", 2.88MB, 512 bytes/sector 19 | F3_2Pt88_512, 20 | /// 3.5", 20.8MB, 512 bytes/sector 21 | F3_20Pt8_512, 22 | /// 3.5", 720KB, 512 bytes/sector 23 | F3_720_512, 24 | /// 5.25", 360KB, 512 bytes/sector 25 | F5_360_512, 26 | /// 5.25", 320KB, 512 bytes/sector 27 | F5_320_512, 28 | /// 5.25", 320KB, 1024 bytes/sector 29 | F5_320_1024, 30 | /// 5.25", 180KB, 512 bytes/sector 31 | F5_180_512, 32 | /// 5.25", 160KB, 512 bytes/sector 33 | F5_160_512, 34 | /// Removable media other than floppy 35 | RemovableMedia, 36 | /// Fixed hard disk media 37 | FixedMedia, 38 | /// 3.5", 120M Floppy 39 | F3_120M_512, 40 | /// 3.5" , 640KB, 512 bytes/sector 41 | F3_640_512, 42 | /// 5.25", 640KB, 512 bytes/sector 43 | F5_640_512, 44 | /// 5.25", 720KB, 512 bytes/sector 45 | F5_720_512, 46 | /// 3.5" , 1.2Mb, 512 bytes/sector 47 | F3_1Pt2_512, 48 | /// 3.5" , 1.23Mb, 1024 bytes/sector 49 | F3_1Pt23_1024, 50 | /// 5.25", 1.23MB, 1024 bytes/sector 51 | F5_1Pt23_1024, 52 | /// 3.5" MO 128Mb 512 bytes/sector 53 | F3_128Mb_512, 54 | /// 3.5" MO 230Mb 512 bytes/sector 55 | F3_230Mb_512, 56 | /// 8", 256KB, 128 bytes/sector 57 | F8_256_128, 58 | /// 3.5", 200M Floppy (HiFD) 59 | F3_200Mb_512, 60 | /// 3.5", 240Mb Floppy (HiFD) 61 | F3_240M_512, 62 | /// 3.5", 32Mb Floppy 63 | F3_32M_512, 64 | } 65 | 66 | /// Define the method codes for how buffers are passed for I/O and FS controls 67 | public enum METHOD : byte 68 | { 69 | /// Specifies the buffered I/O method, which is typically used for transferring small amounts of data per request. 70 | BUFFERED = 0, 71 | /// Specifies the direct I/O method, which is typically used for reading or writing large amounts of data, using DMA or PIO, that must be transferred quickly. 72 | IN_DIRECT = 1, 73 | /// Specifies the direct I/O method, which is typically used for reading or writing large amounts of data, using DMA or PIO, that must be transferred quickly. 74 | OUT_DIRECT = 2, 75 | /// 76 | /// Specifies neither buffered nor direct I/O. 77 | /// The I/O manager does not provide any system buffers or MDLs. 78 | /// The IRP supplies the user-mode virtual addresses of the input and output buffers that were specified to DeviceIoControl or IoBuildDeviceIoControlRequest, without validating or mapping them. 79 | /// 80 | NEITHER = 3, 81 | } 82 | 83 | /// The SID_NAME_USE enumeration contains values that specify the type of a security identifier (SID). 84 | public enum SID_NAME_USE 85 | { 86 | /// A user SID. 87 | SidTypeUser = 1, 88 | /// A group SID. 89 | SidTypeGroup, 90 | /// A domain SID. 91 | SidTypeDomain, 92 | /// An alias SID. 93 | SidTypeAlias, 94 | /// A SID for a well-known group. 95 | SidTypeWellKnownGroup, 96 | /// A SID for a deleted account. 97 | SidTypeDeletedAccount, 98 | /// A SID that is not valid. 99 | SidTypeInvalid, 100 | /// A SID of unknown type. 101 | SidTypeUnknown, 102 | /// A SID for a computer. 103 | SidTypeComputer, 104 | /// A mandatory integrity label SID. 105 | SidTypeLabel, 106 | } 107 | 108 | /// Access flags 109 | [Flags] 110 | public enum FILE_ACCESS_FLAGS : uint 111 | { 112 | /// Read 113 | GENERIC_READ = 0x80000000, 114 | /// Write 115 | GENERIC_WRITE = 0x40000000, 116 | /// Execute 117 | GENERIC_EXECUTE = 0x20000000, 118 | /// All 119 | GENERIC_ALL = 0x10000000, 120 | } 121 | 122 | /// Share 123 | [Flags] 124 | public enum FILE_SHARE : uint 125 | { 126 | /// 127 | /// Enables subsequent open operations on a file or device to request read access. 128 | /// Otherwise, other processes cannot open the file or device if they request read access. 129 | /// 130 | READ = 0x00000001, 131 | /// 132 | /// Enables subsequent open operations on a file or device to request write access. 133 | /// Otherwise, other processes cannot open the file or device if they request write access. 134 | /// 135 | WRITE = 0x00000002, 136 | /// 137 | /// Enables subsequent open operations on a file or device to request delete access. 138 | /// Otherwise, other processes cannot open the file or device if they request delete access. 139 | /// If this flag is not specified, but the file or device has been opened for delete access, the function fails. 140 | /// 141 | DELETE = 0x00000004, 142 | } 143 | 144 | /// Defines the access check value for any access. 145 | [Flags] 146 | public enum FILE_ACCESS : ushort 147 | { 148 | /// Request all access. 149 | ANY_ACCESS = 0, 150 | /// Request read access. 151 | /// Can be used with FILE_WRITE_ACCESS. 152 | READ_ACCESS = 0x0001, 153 | /// Request write access. 154 | /// Can be used with FILE_READ_ACCESS. 155 | WRITE_ACCESS = 0x0002, 156 | } 157 | 158 | /// Disposition 159 | public enum CreateDisposition : uint 160 | { 161 | /// Create new 162 | CREATE_NEW = 1, 163 | /// Create always 164 | CREATE_ALWAYS = 2, 165 | /// Open exising 166 | OPEN_EXISTING = 3, 167 | /// Open always 168 | OPEN_ALWAYS = 4, 169 | /// Truncate existing 170 | TRUNCATE_EXISTING = 5, 171 | } 172 | 173 | /// Drive types 174 | public enum DRIVE : uint 175 | { 176 | /// The drive type cannot be determined. 177 | UNKNOWN = 0, 178 | /// The root directory does not exist. 179 | NO_ROOT_DIR = 1, 180 | /// The drive can be removed from the drive. 181 | REMOVABLE = 2, 182 | /// The disk cannot be removed from the drive. 183 | FIXED = 3, 184 | /// The drive is a remote (network) drive. 185 | REMOTE = 4, 186 | /// The drive is a CD-ROM drive. 187 | CDROM = 5, 188 | /// The drive is a RAM disk. 189 | RAMDISK = 6, 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /DeviceIOControl/PinnedBufferReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.InteropServices; 4 | using System.Security.Permissions; 5 | 6 | namespace DeviceIOControl 7 | { 8 | [DefaultProperty("Length")] 9 | public class PinnedBufferReader : IDisposable 10 | { 11 | private GCHandle _gcHandle; 12 | 13 | private IntPtr _gcPointer; 14 | 15 | private readonly byte[] _buffer; 16 | 17 | private byte[] Buffer => _buffer; 18 | 19 | private IntPtr Handle => _gcPointer; 20 | 21 | public byte this[uint index] => Buffer[index]; 22 | 23 | public int Length => Buffer.Length; 24 | 25 | //[EnvironmentPermission(SecurityAction.LinkDemand, Unrestricted = true)] 26 | public PinnedBufferReader(byte[] buffer) 27 | { 28 | _buffer = buffer; 29 | _gcHandle = GCHandle.Alloc(_buffer, GCHandleType.Pinned); 30 | _gcPointer = _gcHandle.AddrOfPinnedObject(); 31 | } 32 | 33 | //[EnvironmentPermission(SecurityAction.LinkDemand, Unrestricted = true)] 34 | public T BytesToStructure(ref uint padding) where T : struct 35 | { 36 | int length; 37 | T result = BytesToStructure(padding, out length); 38 | padding += (uint)length; 39 | return result; 40 | } 41 | 42 | //[EnvironmentPermission(SecurityAction.LinkDemand, Unrestricted = true)] 43 | public T BytesToStructure(uint padding) where T : struct 44 | { 45 | int length; 46 | return BytesToStructure(padding, out length); 47 | } 48 | 49 | //[EnvironmentPermission(SecurityAction.LinkDemand, Unrestricted = true)] 50 | public T BytesToStructure(uint padding, out int length) where T : struct 51 | { 52 | length = Marshal.SizeOf(typeof(T)); 53 | if (length + padding > Buffer.Length) 54 | { 55 | throw new ArgumentOutOfRangeException("padding"); 56 | } 57 | IntPtr ptr = ((padding == 0) ? Handle : new IntPtr(Handle.ToInt64() + padding)); 58 | return (T)Marshal.PtrToStructure(ptr, typeof(T)); 59 | } 60 | 61 | public string BytesToStringUni(uint padding) 62 | { 63 | int length; 64 | return BytesToStringUni(padding, out length); 65 | } 66 | 67 | public string BytesToStringUni(ref uint padding) 68 | { 69 | int length; 70 | string result = BytesToStringUni(padding, out length); 71 | padding += (uint)length; 72 | return result; 73 | } 74 | 75 | public string BytesToStringUni(uint padding, out int length) 76 | { 77 | if (padding > Buffer.Length) 78 | { 79 | throw new ArgumentOutOfRangeException("padding"); 80 | } 81 | IntPtr ptr = ((padding == 0) ? Handle : new IntPtr(Handle.ToInt64() + padding)); 82 | string text = Marshal.PtrToStringUni(ptr); 83 | length = (text.Length + 1) * Marshal.SystemDefaultCharSize; 84 | return text; 85 | } 86 | 87 | public string BytesToStringAnsi(uint padding) 88 | { 89 | int length; 90 | return BytesToStringAnsi(padding, out length); 91 | } 92 | 93 | public string BytesToStringAnsi(ref uint padding) 94 | { 95 | int length; 96 | string result = BytesToStringAnsi(padding, out length); 97 | padding += (uint)length; 98 | return result; 99 | } 100 | 101 | public string BytesToStringAnsi(uint padding, out int length) 102 | { 103 | if (padding > Buffer.Length) 104 | { 105 | throw new ArgumentOutOfRangeException("padding"); 106 | } 107 | IntPtr ptr = ((padding == 0) ? Handle : new IntPtr(Handle.ToInt64() + padding)); 108 | string text = Marshal.PtrToStringAnsi(ptr); 109 | length = text.Length + 1; 110 | return text; 111 | } 112 | 113 | public byte[] GetBytes(uint padding, uint length) 114 | { 115 | if (padding + length > Buffer.Length) 116 | { 117 | throw new ArgumentOutOfRangeException("padding"); 118 | } 119 | byte[] array = new byte[length]; 120 | Array.Copy(Buffer, padding, array, 0L, array.Length); 121 | return array; 122 | } 123 | 124 | public static T BytesToStructure(byte[] buffer, ref uint padding) where T : struct 125 | { 126 | int length; 127 | T result = BytesToStructure(buffer, padding, out length); 128 | padding += (uint)length; 129 | return result; 130 | } 131 | 132 | public static T BytesToStructure(byte[] buffer, uint padding) where T : struct 133 | { 134 | int length; 135 | return BytesToStructure(buffer, padding, out length); 136 | } 137 | 138 | public static T BytesToStructure(byte[] buffer, uint padding, out int length) where T : struct 139 | { 140 | using PinnedBufferReader pinnedBufferReader = new PinnedBufferReader(buffer); 141 | return pinnedBufferReader.BytesToStructure(padding, out length); 142 | } 143 | 144 | public static string BytesToStringUni(byte[] buffer, uint padding, out int length) 145 | { 146 | using PinnedBufferReader pinnedBufferReader = new PinnedBufferReader(buffer); 147 | return pinnedBufferReader.BytesToStringUni(padding, out length); 148 | } 149 | 150 | public static string BytesToStringAnsi(byte[] buffer, uint padding, out int length) 151 | { 152 | using PinnedBufferReader pinnedBufferReader = new PinnedBufferReader(buffer); 153 | return pinnedBufferReader.BytesToStringAnsi(padding, out length); 154 | } 155 | 156 | public static byte[] StructureToArray(T structure) where T : struct 157 | { 158 | int num = Marshal.SizeOf((object)structure); 159 | byte[] array = new byte[num]; 160 | IntPtr intPtr = Marshal.AllocHGlobal(num); 161 | try 162 | { 163 | Marshal.StructureToPtr((object)structure, intPtr, fDeleteOld: true); 164 | Marshal.Copy(intPtr, array, 0, num); 165 | return array; 166 | } 167 | finally 168 | { 169 | Marshal.FreeHGlobal(intPtr); 170 | } 171 | } 172 | 173 | public void Dispose() 174 | { 175 | Dispose(disposing: true); 176 | GC.SuppressFinalize(this); 177 | } 178 | 179 | protected virtual void Dispose(bool disposing) 180 | { 181 | if (disposing && _gcHandle.IsAllocated) 182 | { 183 | _gcHandle.Free(); 184 | } 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /DeviceIOControl/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | bin\Release\net5.0\publish\ 10 | FileSystem 11 | net5.0 12 | win-x64 13 | true 14 | False 15 | False 16 | False 17 | 18 | -------------------------------------------------------------------------------- /DeviceIOControl/Properties/PublishProfiles/FolderProfile.pubxml.user: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | True|2021-05-19T13:09:37.2377369Z; 8 | 9 | -------------------------------------------------------------------------------- /DeviceIOControl/Storage/Storage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.ComponentModel; 4 | using DeviceIOControl.Native; 5 | 6 | namespace DeviceIOControl.Storage 7 | { 8 | /// Storage IO control commands 9 | public class Storage 10 | { 11 | #region Fields 12 | private readonly DeviceIoControl _device; 13 | private Properties _properties; 14 | private StorageApi.STORAGE_DEVICE_NUMBER? _deviceNumber; 15 | private StorageApi.GET_MEDIA_TYPES? _mediaTypesEx; 16 | private StorageApi.MEDIA_SERIAL_NUMBER_DATA? _serialNumber; 17 | private StorageApi.STORAGE_READ_CAPACITY? _readCapacity; 18 | #endregion Fields 19 | 20 | /// Device 21 | private DeviceIoControl Device { get { return this._device; } } 22 | 23 | /// Device descriptors 24 | public Properties Properties 25 | { 26 | get 27 | { 28 | return this._properties == null 29 | ? this._properties = new Properties(this.Device) 30 | : this._properties; 31 | } 32 | } 33 | 34 | /// Contains information about a device. 35 | public StorageApi.STORAGE_DEVICE_NUMBER DeviceNumber 36 | { 37 | get 38 | { 39 | return (this._deviceNumber == null 40 | ? this._deviceNumber = this.Device.IoControl( 41 | Constant.IOCTL_STORAGE.GET_DEVICE_NUMBER, 42 | null) 43 | : this._deviceNumber).Value; 44 | } 45 | } 46 | /// Queries the USB generic parent driver for the serial number of a USB device. 47 | /// 48 | /// If a USB device has a CSM-1 content security interface, a USB client driver can query for its serial number using this request. 49 | /// USB client drivers that help implement a digital rights management (DRM) system can use this information to ensure that only legitimate customers have access to digitized intellectual property. 50 | /// 51 | public StorageApi.MEDIA_SERIAL_NUMBER_DATA SerialNumber 52 | { 53 | get 54 | { 55 | return (this._serialNumber == null 56 | ? this._serialNumber = this.Device.IoControl( 57 | Constant.IOCTL_STORAGE.GET_MEDIA_SERIAL_NUMBER, 58 | null) 59 | : this._serialNumber).Value; 60 | } 61 | } 62 | 63 | /// Contains information about the media types supported by a device. 64 | public StorageApi.GET_MEDIA_TYPES MediaTypesEx 65 | { 66 | get 67 | { 68 | return (this._mediaTypesEx == null 69 | ? this._mediaTypesEx = this.Device.IoControl( 70 | Constant.IOCTL_STORAGE.GET_MEDIA_TYPES_EX, 71 | null) 72 | : this._mediaTypesEx).Value; 73 | } 74 | } 75 | 76 | /// Retrieves the geometry information for the device. 77 | public StorageApi.STORAGE_READ_CAPACITY ReadCapacity 78 | { 79 | get 80 | { 81 | return (this._readCapacity == null 82 | ? this._readCapacity = this.Device.IoControl( 83 | Constant.IOCTL_STORAGE.READ_CAPACITY, null) 84 | : this._readCapacity).Value; 85 | } 86 | } 87 | 88 | /// Determines whether the media has changed on a removable-media device that the caller has opened for read or write access. 89 | public Boolean CheckVerify 90 | { 91 | get 92 | { 93 | Boolean result = this.Device.IoControl(Constant.IOCTL_STORAGE.CHECK_VERIFY); 94 | if (result) 95 | return true; 96 | else 97 | { 98 | Int32 error = Marshal.GetLastWin32Error(); 99 | if (error == (Int32)Constant.ERROR.NOT_READY) 100 | return false; 101 | else throw new Win32Exception(error); 102 | } 103 | } 104 | } 105 | /// Determines whether the media has changed on a removable-media device - the caller has opened with FILE_READ_ATTRIBUTES. 106 | public Boolean CheckVerify2 107 | { 108 | get 109 | { 110 | Boolean result = this.Device.IoControl(Constant.IOCTL_STORAGE.CHECK_VERIFY2); 111 | if (result) 112 | return true; 113 | else 114 | { 115 | Int32 error = Marshal.GetLastWin32Error(); 116 | if (error == (Int32)Constant.ERROR.NOT_READY) 117 | return false; 118 | else throw new Win32Exception(error); 119 | } 120 | } 121 | } 122 | 123 | /// Create instance of storage IO commands class 124 | /// Device 125 | internal Storage(DeviceIoControl device) 126 | { 127 | this._device = device; 128 | } 129 | 130 | /// Enables or disables the mechanism that ejects media, for those devices possessing that locking capability. 131 | /// Prevent device to eject media 132 | public void PreventMediaRemoval(Boolean prevent) 133 | { 134 | this.Device.IoControl(Constant.IOCTL_STORAGE.MEDIA_REMOVAL, prevent); 135 | } 136 | 137 | /// Causes the device to eject the media if the device supports ejection capabilities. 138 | /// Device exception 139 | public void EjectMedia() 140 | { 141 | this.Device.IoControl(Constant.IOCTL_STORAGE.EJECT_MEDIA, null); 142 | } 143 | 144 | /// Retrieves the hotplug configuration of the specified device. 145 | /// Hotplug information for a device. 146 | public StorageApi.STORAGE_HOTPLUG_INFO GetHotPlugInfo() 147 | { 148 | return this.Device.IoControl( 149 | Constant.IOCTL_STORAGE.GET_HOTPLUG_INFO, 150 | null); 151 | } 152 | 153 | /// Polls for a prediction of device failure. 154 | /// Report whether a device is currently predicting a failure. 155 | public StorageApi.STORAGE_PREDICT_FAILURE PredictFailure() 156 | { 157 | return this.Device.IoControl( 158 | Constant.IOCTL_STORAGE.PREDICT_FAILURE, 159 | null); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /DeviceIOControl/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Globalization; 4 | 5 | namespace DeviceIOControl 6 | { 7 | /// Utils 8 | public struct Utils 9 | { 10 | private const Int64 FileSize = 1024; 11 | private static String[] FileSizeType = new String[] { "bytes", "Kb", "Mb", "Gb", }; 12 | /// Swap odd/even bytes in array of USHORTS 13 | /// Buffer 14 | /// Start position 15 | /// Count 16 | /// buffer is null 17 | /// buffer length is less than start index 18 | /// String 19 | public static String SwapBytes(UInt16[] buffer, UInt64 start, UInt64 count) 20 | { 21 | if (buffer == null) 22 | throw new ArgumentNullException("buffer"); 23 | if ((UInt64)buffer.LongLength < start) 24 | throw new ArgumentException("Start index less than buffer length."); 25 | 26 | StringBuilder result = new StringBuilder(); 27 | for (UInt64 loop = start; loop < start + count; loop++) 28 | { 29 | Byte[] part = BitConverter.GetBytes((buffer[loop] << 8 | buffer[loop] >> 8)); 30 | String zz = Encoding.ASCII.GetString(part, 0, part.Length - 2); 31 | result.Append(zz); 32 | } 33 | 34 | return result.ToString(); 35 | } 36 | /// Swap chars in IDREGS array 37 | /// Char buffer 38 | /// buffer is null 39 | /// Swapped string 40 | public static String SwapChars(Char[] buffer) 41 | { 42 | if (buffer == null) 43 | throw new ArgumentNullException("buffer"); 44 | 45 | StringBuilder result = new StringBuilder(); 46 | for (Int32 loop = 0; loop < buffer.Length; loop += 2) 47 | { 48 | result.Append(buffer[loop + 1]); 49 | result.Append(buffer[loop]); 50 | } 51 | return result.ToString(); 52 | } 53 | /// Find highest non-zero bit position 54 | /// Value 55 | /// highest non-zero bit position 56 | /// Bit position 57 | public static Int64 HighBitPos(Int64 value, Int32 maxPos) 58 | { 59 | Int32 pos; 60 | for (pos = maxPos; !(pos < 0 || ((value >> pos) & 1) == 1); pos--) ; 61 | return pos; 62 | } 63 | /// Makes a 32 bit integer from two 16 bit shorts 64 | /// The low order value. 65 | /// The high order value. 66 | /// 67 | public static Int32 MakeDword(UInt16 low, UInt16 high) 68 | { 69 | return (low + (high << 16)); 70 | } 71 | /// Convert file size in bytes to string with dimention 72 | /// size in bytes 73 | /// Size with dimention 74 | public static String FileSizeToString(UInt64 length) 75 | { 76 | UInt64 constSize = 1; 77 | Int32 sizePosition = 0; 78 | while (length > constSize * FileSize && sizePosition + 1 < Utils.FileSizeType.Length) 79 | { 80 | constSize *= Utils.FileSize; 81 | sizePosition++; 82 | } 83 | return String.Format(CultureInfo.CurrentUICulture, "{0:n0} {1}", length / constSize, Utils.FileSizeType[sizePosition]); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /DeviceIOControl/Volume/Volume.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.ComponentModel; 4 | using DeviceIOControl.Native; 5 | 6 | namespace DeviceIOControl.Volume 7 | { 8 | /// Volume IO control commands 9 | public class Volume 10 | { 11 | #region Fields 12 | private readonly DeviceIoControl _device; 13 | private Boolean? _isClustered; 14 | private VolumeApi.VOLUME_DISK_EXTENTS? _diskExtents; 15 | #endregion Fields 16 | 17 | /// Device 18 | private DeviceIoControl Device { get { return this._device; } } 19 | 20 | /// Represents a physical location on a disk. 21 | /// Вызов не работает в Windows 7 22 | public VolumeApi.VOLUME_DISK_EXTENTS DiskExtents 23 | { 24 | get 25 | { 26 | if (this._diskExtents == null) 27 | this._diskExtents = this.Device.IoControl( 28 | Constant.IOCTL_VOLUME.GET_VOLUME_DISK_EXTENTS, 29 | null); 30 | return this._diskExtents.Value; 31 | } 32 | } 33 | 34 | /// Determines whether the specified volume is clustered. 35 | /// The volume is offline or Cluster service is not installed. 36 | public Boolean IsClustered 37 | { 38 | get 39 | { 40 | if (this._isClustered == null) 41 | if (this.Device.IoControl(Constant.IOCTL_VOLUME.IS_CLUSTERED)) this._isClustered = true; 42 | else 43 | { 44 | Int32 error = Marshal.GetLastWin32Error(); 45 | if (error == (Int32)Constant.ERROR.NO_ERROR) 46 | this._isClustered = false; 47 | else 48 | throw new Win32Exception(error); 49 | } 50 | return this._isClustered.Value; 51 | } 52 | } 53 | 54 | /// Create instance of Volume IO control commands 55 | /// Device 56 | internal Volume(DeviceIoControl device) 57 | { 58 | this._device = device; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Hardware/Computer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LibreHardwareMonitor.Hardware; 3 | using Hardware.Windows.RAM; 4 | 5 | namespace Hardware 6 | { 7 | public static class Computer 8 | { 9 | private static LibreHardwareMonitor.Hardware.Computer pc; 10 | 11 | private static ISensor CpuPercentSensor; 12 | private static ISensor CpuTempSensor; 13 | 14 | private static ISensor GpuPercentSensor; 15 | private static ISensor GpuTempSensor; 16 | 17 | private static ISensor GpuRamUsedSensor; 18 | 19 | public static float CPUPercent { get; private set; } 20 | public static float CPUTemp { get; private set; } 21 | 22 | public static float GPUPercent { get; private set; } 23 | public static float GPUTemp { get; private set; } 24 | 25 | public static float GPUTotalRam { get; private set; } 26 | public static float GPUUsedRam { get; private set; } 27 | public static float GPUPercentRam { get; private set; } 28 | 29 | public static double RamTotal { get; private set; } 30 | public static double RamUsed { get; private set; } 31 | public static double RamFree { get; private set; } 32 | public static byte RamPercent { get; private set; } 33 | 34 | static Computer() 35 | { 36 | CPUPercent = 0; 37 | CPUTemp = 0; 38 | GPUPercent = 0; 39 | GPUTemp = 0; 40 | GPUPercentRam = 0; 41 | GPUUsedRam = 0; 42 | } 43 | 44 | private static void SetSensors() 45 | { 46 | foreach (IHardware hardware in pc.Hardware) 47 | { 48 | hardware.Update(); 49 | 50 | if (hardware.HardwareType == HardwareType.Motherboard) 51 | { 52 | foreach (IHardware sub in hardware.SubHardware) 53 | { 54 | sub.Update(); 55 | 56 | if (sub.HardwareType == HardwareType.SuperIO) 57 | { 58 | foreach (ISensor sensor in sub.Sensors) 59 | { 60 | if (sensor.SensorType == SensorType.Temperature && sensor.Index == 0) 61 | { 62 | CpuTempSensor = sensor; 63 | CpuTempSensor.ValuesTimeWindow = TimeSpan.Zero; 64 | break; 65 | } 66 | } 67 | 68 | break; 69 | } 70 | } 71 | } 72 | 73 | if (hardware.HardwareType == HardwareType.Cpu) 74 | { 75 | foreach (ISensor sensor in hardware.Sensors) 76 | { 77 | if (sensor.SensorType == SensorType.Load && sensor.Index == 0) 78 | { 79 | CpuPercentSensor = sensor; 80 | CpuPercentSensor.ValuesTimeWindow = TimeSpan.Zero; 81 | break; 82 | } 83 | } 84 | } 85 | 86 | if (hardware.HardwareType == HardwareType.GpuNvidia || hardware.HardwareType == HardwareType.GpuAmd) 87 | { 88 | foreach (ISensor sensor in hardware.Sensors) 89 | { 90 | if (sensor.SensorType == SensorType.Load && sensor.Index == 0) 91 | { 92 | GpuPercentSensor = sensor; 93 | GpuPercentSensor.ValuesTimeWindow = TimeSpan.Zero; 94 | } 95 | if (sensor.SensorType == SensorType.Temperature) 96 | { 97 | GpuTempSensor = sensor; 98 | GpuTempSensor.ValuesTimeWindow = TimeSpan.Zero; 99 | } 100 | if (sensor.SensorType == SensorType.SmallData && sensor.Index == 2) GPUTotalRam = sensor.Value.Value; 101 | if (sensor.SensorType == SensorType.SmallData && sensor.Index == 1) 102 | { 103 | GpuRamUsedSensor = sensor; 104 | GpuRamUsedSensor.ValuesTimeWindow = TimeSpan.Zero; 105 | } 106 | } 107 | } 108 | } 109 | } 110 | 111 | public static void Open() 112 | { 113 | if (pc == null) 114 | { 115 | pc = new(); 116 | pc.IsCpuEnabled = true; 117 | pc.IsMotherboardEnabled = true; 118 | pc.IsGpuEnabled = true; 119 | pc.Open(); 120 | } 121 | 122 | SetSensors(); 123 | 124 | RamUpdate(); 125 | } 126 | 127 | private static void RamUpdate() 128 | { 129 | double devider = 1073741824; 130 | 131 | MemoryStatusEx msu = new(); 132 | 133 | try 134 | { NativeMethods.GlobalMemoryStatusEx(msu); } 135 | catch { return; } 136 | 137 | RamTotal = msu.TotalPhys / devider; 138 | RamFree = msu.AvailPhys / devider; 139 | RamUsed = (msu.TotalPhys - msu.AvailPhys) / devider; 140 | RamPercent = (byte)((msu.TotalPhys - msu.AvailPhys) / (msu.TotalPhys / 100)); 141 | } 142 | 143 | public static void Update() 144 | { 145 | try 146 | { 147 | CpuPercentSensor.Hardware.Update(); 148 | CPUPercent = CpuPercentSensor.Value.Value; 149 | } 150 | catch { /* ignored */ } 151 | 152 | try 153 | { 154 | CpuTempSensor.Hardware.Update(); 155 | CPUTemp = CpuTempSensor.Value.Value; 156 | } 157 | catch { /* ignored */ } 158 | 159 | try 160 | { 161 | GpuPercentSensor.Hardware.Update(); 162 | GPUPercent = GpuPercentSensor.Value.Value; 163 | } 164 | catch { /* ignored */ } 165 | 166 | try 167 | { 168 | GpuTempSensor.Hardware.Update(); 169 | GPUTemp = GpuTempSensor.Value.Value; 170 | } 171 | catch { /* ignored */ } 172 | 173 | try 174 | { 175 | GpuRamUsedSensor.Hardware.Update(); 176 | GPUUsedRam = GpuRamUsedSensor.Value.Value; 177 | } 178 | catch { /* ignored */ } 179 | 180 | GPUPercentRam = GPUUsedRam / (GPUTotalRam / 100); 181 | 182 | RamUpdate(); 183 | } 184 | 185 | public static void Close() 186 | { 187 | pc.Close(); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Hardware/Hardware.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | AnyCPU 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Hardware/Windows/DeviceIoInfo/Device.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DeviceIOControl; 3 | using DeviceIOControl.Disc; 4 | 5 | namespace Hardware.Windows.DeviceIoInfo 6 | { 7 | public class Device : IDisposable 8 | { 9 | public short Index { get; set; } 10 | public string Letter { get; set; } 11 | public VendorEnum Vendor; 12 | public string Model { get; set; } 13 | public long TotalSpace { get; set; } 14 | public long FreeSpace { get; set; } 15 | public long UsedSpace { get; set; } 16 | public byte PercentUsedSpace { get; set; } 17 | public float TotalWrite { get; set; } 18 | public byte Health { get; set; } 19 | public bool IsSmart { get; set; } 20 | public float PrevReadIo { get; set; } 21 | public float PrevWriteIo { get; set; } 22 | public DeviceIoControl DeviceControl { get; set; } 23 | public Performance DevicePerformance { get; set; } 24 | 25 | public Device() 26 | { 27 | IsSmart = true; 28 | } 29 | 30 | public void Dispose() 31 | { 32 | DevicePerformance?.Dispose(); 33 | DeviceControl?.Dispose(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Hardware/Windows/DeviceIoInfo/DeviceInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.IO; 5 | using DeviceIOControl; 6 | using DeviceIOControl.Native; 7 | using DeviceIOControl.Disc.Smart; 8 | 9 | namespace Hardware.Windows.DeviceIoInfo 10 | { 11 | public static class DeviceInfo 12 | { 13 | public static float ReadIo { get; private set; } 14 | public static float WriteIo { get; private set; } 15 | 16 | public static List LogicalDrives { get; } 17 | 18 | static DeviceInfo() 19 | { 20 | LogicalDrives = new(); 21 | } 22 | 23 | private static void SetDiscCollection() 24 | { 25 | Close(); 26 | 27 | IEnumerable logicalDevicesIo = DeviceIoControl.GetLogicalDrives(); 28 | 29 | short devIndex = 0; 30 | 31 | foreach (LogicalDrive logical in logicalDevicesIo) 32 | { 33 | if (logical.Type != WinApi.DRIVE.FIXED) 34 | continue; 35 | 36 | Device device = new() 37 | { 38 | Index = devIndex, 39 | Letter = logical.Name, 40 | DeviceControl = new DeviceIoControl(logical.Name) 41 | }; 42 | 43 | device.Model = device.DeviceControl.Disc.Smart == null ? new DriveInfo(logical.Name).VolumeLabel : 44 | device.DeviceControl.Disc.Smart.SystemParams.ModelNumber.Trim(' '); 45 | 46 | if (device.Model.Contains("samsung", StringComparison.OrdinalIgnoreCase)) 47 | device.Vendor = VendorEnum.Samsung; 48 | else if (device.Model.Contains("kingston", StringComparison.OrdinalIgnoreCase)) 49 | device.Vendor = VendorEnum.Kingston; 50 | else if (device.Model.Contains("wdc", StringComparison.OrdinalIgnoreCase)) 51 | device.Vendor = VendorEnum.WDC; 52 | else 53 | device.Vendor = VendorEnum.Other; 54 | 55 | device.DevicePerformance = device.DeviceControl.Disc.GetDiscPerformance(); 56 | device.PrevReadIo = device.DevicePerformance.QueryPerformanceInfo().BytesRead; 57 | device.PrevWriteIo = device.DevicePerformance.QueryPerformanceInfo().BytesWritten; 58 | device.TotalSpace = new DriveInfo(logical.Name).TotalSize; 59 | 60 | LogicalDrives.Add(device); 61 | 62 | devIndex++; 63 | } 64 | } 65 | 66 | public static bool IsUpdateDiscs() 67 | { 68 | if (LogicalDrives.Count == DeviceIoControl.GetLogicalDrives().Count()) return false; 69 | 70 | SetDiscCollection(); 71 | 72 | return true; 73 | 74 | } 75 | 76 | public static void UpdateSizeOfDiscs() 77 | { 78 | if (LogicalDrives == null) SetDiscCollection(); 79 | 80 | foreach (Device logic in LogicalDrives) 81 | { 82 | DriveInfo drive = new(logic.Letter); 83 | try 84 | { 85 | logic.TotalSpace = drive.TotalSize; 86 | logic.FreeSpace = drive.TotalFreeSpace; 87 | logic.UsedSpace = drive.TotalSize - drive.AvailableFreeSpace; 88 | logic.PercentUsedSpace = Convert.ToByte(logic.UsedSpace / (logic.TotalSpace / 100)); 89 | } 90 | catch (DriveNotFoundException) 91 | { 92 | throw new DriveNotFoundException(); 93 | } 94 | } 95 | } 96 | 97 | public static void UpdateInfoOfDiscs() 98 | { 99 | if (LogicalDrives == null) SetDiscCollection(); 100 | 101 | foreach (Device dev in LogicalDrives) 102 | { 103 | SmartInfoCollection smart = dev.DeviceControl.Disc.Smart; 104 | 105 | if (smart == null) continue; 106 | 107 | DiscApi.DRIVEATTRIBUTE[] driveAttributes = smart.GetAttributes(); 108 | 109 | foreach (DiscApi.DRIVEATTRIBUTE attribute in driveAttributes) 110 | { 111 | if (dev.Vendor == VendorEnum.Samsung) 112 | { 113 | if (attribute.bAttrID == 177) dev.Health = attribute.bAttrValue; 114 | if (attribute.bAttrID == 241) dev.TotalWrite = attribute.RawValue / (float)int.MaxValue; 115 | } 116 | 117 | if (dev.Vendor == VendorEnum.Kingston) 118 | { 119 | if (attribute.bAttrID == 231) dev.Health = attribute.bAttrValue; 120 | if (attribute.bAttrID == 241) dev.TotalWrite = attribute.RawValue / 1024f; 121 | } 122 | } 123 | } 124 | } 125 | 126 | public static void PerfomanceDiskUpdate(short index) 127 | { 128 | DiscApi.DISK_PERFORMANCE dIskPerformance = LogicalDrives[index].DevicePerformance.QueryPerformanceInfo(); 129 | 130 | ReadIo = (dIskPerformance.BytesRead - LogicalDrives[index].PrevReadIo) / 1000000; 131 | WriteIo = (dIskPerformance.BytesWritten - LogicalDrives[index].PrevWriteIo) / 1000000; 132 | 133 | LogicalDrives[index].PrevReadIo = dIskPerformance.BytesRead; 134 | LogicalDrives[index].PrevWriteIo = dIskPerformance.BytesWritten; 135 | } 136 | 137 | public static void Close() 138 | { 139 | foreach (Device dev in LogicalDrives) 140 | { 141 | dev.Dispose(); 142 | } 143 | 144 | LogicalDrives.Clear(); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /Hardware/Windows/DeviceIoInfo/VendorEnum.cs: -------------------------------------------------------------------------------- 1 | namespace Hardware.Windows.DeviceIoInfo 2 | { 3 | public enum VendorEnum : byte 4 | { 5 | Samsung, 6 | Kingston, 7 | WDC, 8 | Other 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Hardware/Windows/Network/Adapter.cs: -------------------------------------------------------------------------------- 1 | namespace Hardware.Windows.Network 2 | { 3 | public class Adapter 4 | { 5 | public string Name { get; set; } 6 | public string ID { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Hardware/Windows/Network/NetworkInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.NetworkInformation; 4 | 5 | namespace Hardware.Windows.Network 6 | { 7 | public static class NetworkInfo 8 | { 9 | private static int InterfaceIndex; 10 | private static string ID; 11 | 12 | public static string InterfaceID 13 | { 14 | get { return ID; } 15 | set 16 | { 17 | GetInterfaceIndex(value); 18 | ID = value; 19 | } 20 | } 21 | public static long ByteReceived { get; set; } 22 | public static long ByteSend { get; set; } 23 | 24 | public static List GetInterface() 25 | { 26 | List adapters = new List(); 27 | 28 | NetworkInterface[] networks = NetworkInterface.GetAllNetworkInterfaces(); 29 | 30 | foreach (NetworkInterface net in networks) 31 | { 32 | if (net.Speed != 0) 33 | { 34 | Adapter adapter = new Adapter(); 35 | adapter.Name = net.Name; 36 | adapter.ID = net.Id; 37 | 38 | adapters.Add(adapter); 39 | } 40 | } 41 | 42 | return adapters; 43 | } 44 | 45 | private static void GetInterfaceIndex(string id) 46 | { 47 | if (id == null) return; 48 | 49 | NetworkInterface[] networks = NetworkInterface.GetAllNetworkInterfaces(); 50 | 51 | for (byte b = 0; b < networks.Length; b++) 52 | { 53 | if (networks[b].Id.Contains(id)) 54 | { 55 | InterfaceIndex = b; 56 | break; 57 | } 58 | } 59 | } 60 | 61 | public static void SpeedUpdate() 62 | { 63 | IPv4InterfaceStatistics statistics = NetworkInterface.GetAllNetworkInterfaces()[InterfaceIndex].GetIPv4Statistics(); 64 | 65 | ByteReceived = statistics.BytesReceived; 66 | ByteSend = statistics.BytesSent; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Hardware/Windows/RAM/MemoryStatusEx.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Hardware.Windows.RAM 4 | { 5 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 6 | class MemoryStatusEx 7 | { 8 | public uint dwLength; 9 | public uint dwMemoryLoad; 10 | public ulong TotalPhys; 11 | public ulong AvailPhys; 12 | public ulong TotalPageFile; 13 | public ulong AvailPageFile; 14 | public ulong TotalVirtual; 15 | public ulong AvailVirtual; 16 | public ulong AvailExtendedVirtual; 17 | 18 | public MemoryStatusEx() 19 | { 20 | dwLength = (uint)Marshal.SizeOf(typeof(MemoryStatusEx)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Hardware/Windows/RAM/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Hardware.Windows.RAM 4 | { 5 | static class NativeMethods 6 | { 7 | const string KernelDll = "kernel32.dll"; 8 | 9 | [return: MarshalAs(UnmanagedType.Bool)] 10 | [DllImport(KernelDll, CharSet = CharSet.Auto, SetLastError = true)] 11 | public static extern bool GlobalMemoryStatusEx([In, Out] MemoryStatusEx lpBuffer); 12 | 13 | [return: MarshalAs(UnmanagedType.Bool)] 14 | [DllImport(KernelDll)] 15 | public static extern bool GetPhysicallyInstalledSystemMemory(out ulong totalMemoryInKilobytes); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 FanIT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SysMonAvalonia 2 | SysMonAvalonia - 3 desktop widgets for Windows. 3 | - Disks widgets - Showing a list of logical disks in Windows with informations about total/used size, model, speed read/write and health, total write for ssd. 4 | - Combo widgets - Showing system informations cpu, ram, video and network. 5 | - Weather widgets - Showing a current, forecast hours and forecast days weather. The widget have 4 weather providers. 6 | 7 | ![Black](https://user-images.githubusercontent.com/20283004/134173483-9ab5921f-02f2-47da-b894-f3af8d502ab7.PNG) ![White](https://user-images.githubusercontent.com/20283004/134173497-1a5c459e-49b8-4412-81ce-31152cc174b3.PNG) 8 | 9 | ## What use for the GUI? 10 | The widgets use Avalonia project for the GUI. 11 | 12 | ## What side projects does the project use? 13 | - [LibreHardwareMonitorLib](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor) for showing cpu, gpu load and temperatures. 14 | - [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) for work with json. 15 | - [DeviceIoControl assembly](https://github.com/DKorablin/DeviceIoControl#deviceiocontrol-assembly) for getting SMART date and speed read/write a disks. 16 | - [LiveCharts2](https://github.com/beto-rodriguez/LiveCharts2) display real time charts for cpu, ram, gpu, network and device io. 17 | -------------------------------------------------------------------------------- /SysMonAvalonia.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31515.178 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SysMonAvalonia", "SysMonAvalonia\SysMonAvalonia.csproj", "{8BF3DB5F-1B8B-44DC-BEBA-F5AD0A830724}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hardware", "Hardware\Hardware.csproj", "{A7EF0D95-5A28-4A0A-9EA0-E5965B228ABF}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceIOControl", "DeviceIOControl\DeviceIOControl.csproj", "{2517850D-ACC6-4005-BC06-9E380D2D4066}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Weather", "Weather\Weather.csproj", "{B4D05221-FCE1-4C7C-9484-B5F41AB8DD2D}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {8BF3DB5F-1B8B-44DC-BEBA-F5AD0A830724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {8BF3DB5F-1B8B-44DC-BEBA-F5AD0A830724}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {8BF3DB5F-1B8B-44DC-BEBA-F5AD0A830724}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {8BF3DB5F-1B8B-44DC-BEBA-F5AD0A830724}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {A7EF0D95-5A28-4A0A-9EA0-E5965B228ABF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {A7EF0D95-5A28-4A0A-9EA0-E5965B228ABF}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {A7EF0D95-5A28-4A0A-9EA0-E5965B228ABF}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {A7EF0D95-5A28-4A0A-9EA0-E5965B228ABF}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {2517850D-ACC6-4005-BC06-9E380D2D4066}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {2517850D-ACC6-4005-BC06-9E380D2D4066}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {2517850D-ACC6-4005-BC06-9E380D2D4066}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {2517850D-ACC6-4005-BC06-9E380D2D4066}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {B4D05221-FCE1-4C7C-9484-B5F41AB8DD2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {B4D05221-FCE1-4C7C-9484-B5F41AB8DD2D}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {B4D05221-FCE1-4C7C-9484-B5F41AB8DD2D}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {B4D05221-FCE1-4C7C-9484-B5F41AB8DD2D}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {920ACC45-0FCC-42B8-A052-9666687C2277} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /SysMonAvalonia/App.axaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SysMonAvalonia/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | using SysMonAvalonia.Localization; 5 | using SysMonAvalonia.Data; 6 | using SysMonAvalonia.Models; 7 | using SysMonAvalonia.Services; 8 | 9 | namespace SysMonAvalonia 10 | { 11 | public class App : Application 12 | { 13 | public override void Initialize() 14 | { 15 | AvaloniaXamlLoader.Load(this); 16 | 17 | SettingModel.Load(); 18 | 19 | Language.Load(SettingData.CurrentSetting.Culture); 20 | 21 | AppService.ChangeStyles(); 22 | } 23 | 24 | public override void OnFrameworkInitializationCompleted() 25 | { 26 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 27 | { 28 | desktop.Exit += (sender, args) => SettingModel.Save(); 29 | 30 | AppService.ShowWidgets(desktop); 31 | } 32 | 33 | base.OnFrameworkInitializationCompleted(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/Fonts/SegoeUILight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/Fonts/SegoeUILight.ttf -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/Locale/en.json: -------------------------------------------------------------------------------- 1 | { "Close":"Close", 2 | "Settings":"Settings", 3 | "Mb":"Mb", 4 | "Gb":"Gb", 5 | "Tb":"Tb", 6 | "Mbit":"Mbit/s", 7 | "Mbyte":"MB/s", 8 | "Health":"Health", 9 | "Write":"Write", 10 | "ReadIO":"Read", 11 | "WriteIO":"Write", 12 | "CpuHeader":"CPU", 13 | "GpuHeader":"GPU", 14 | "RamHeader":"RAM", 15 | "Download":"Network (Down)", 16 | "Upload":"Network (Up)", 17 | "Adapters":"Adapters", 18 | "ApparTempDesc":"Feel like", 19 | "WindSpeedDesc":"Wind", 20 | "CloudCoverDesc":"Cloudy", 21 | "ChanceOfRain":"Probability of precip", 22 | "HumidityDesc":"Humidity", 23 | "Pressure":"mm Hg", 24 | "PressureDesc":"Pressure", 25 | "UVIndexDesc":"UV-Index", 26 | "UVIndexLow":"Low", 27 | "UVIndexMedium":"Medium", 28 | "UVIndexHigh":"High", 29 | "UVIndexVeryHigh":"Very high", 30 | "UVIndexExtrem":"Extrem", 31 | "WindUnitKmH":"km/h", 32 | "WindUnitMH":"m/h", 33 | "WindUnitMS":"m/s", 34 | "WindDirDesc0":"N", 35 | "WindDirDesc22":"NNE", 36 | "WindDirDesc45":"NE", 37 | "WindDirDesc67":"ENE", 38 | "WindDirDesc90":"E", 39 | "WindDirDesc112":"ESE", 40 | "WindDirDesc135":"SE", 41 | "WindDirDesc157":"SSE", 42 | "WindDirDesc180":"S", 43 | "WindDirDesc202":"SSW", 44 | "WindDirDesc225":"SW", 45 | "WindDirDesc247":"WSW", 46 | "WindDirDesc270":"W", 47 | "WindDirDesc292":"WNW", 48 | "WindDirDesc315":"NW", 49 | "WindDirDesc337":"NNW", 50 | "WaterTempDesc":"Water", 51 | "SunsetDesc":"Sunset", 52 | "SunriseDesc":"Sunrise", 53 | "CityDesc":"City", 54 | "LastUpdateDesc":"Update at", 55 | "Hourly":"Hourly", 56 | "Daily":"Daily", 57 | "Update":"Update", 58 | "Providers":"Providers of weather", 59 | "Time":"Time", 60 | "GenTabSetting":"General", 61 | "Network":"Network", 62 | "LangSetting":"Language", 63 | "Russia":"Russian", 64 | "English":"English", 65 | "WidgSetting":"Widgets", 66 | "DiscsSetting":"Discs", 67 | "ComboSetting":"Combo", 68 | "WeatherSetting":"Weather", 69 | "ApiKeySettings":"API key", 70 | "EnterCityWM":"Enter name of city", 71 | "AutostartHeaderSetting":"Autostart", 72 | "AutostartTogle":"Autostart with Windows", 73 | "LocationSetting":"Location", 74 | "Themes":"Themes", 75 | "Dark":"Dark", 76 | "Light":"Light", 77 | "NetUnit":"Network units", 78 | "MbitSettings":"Megabits per second (Mbit/s)", 79 | "MbyteSettings":"Megabyts per second (MByte/s)", 80 | "Cancel":"Cancel", 81 | } -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/Locale/ru.json: -------------------------------------------------------------------------------- 1 | { "Close":"Закрыть", 2 | "Settings":"Настройки", 3 | "Mb":"Мб", 4 | "Gb":"Гб", 5 | "Tb":"Тб", 6 | "Mbit":"Мбит/с", 7 | "Mbyte":"МБ/с", 8 | "Health":"Здоровье", 9 | "Write":"Записано", 10 | "ReadIO":"Чтение", 11 | "WriteIO":"Запись", 12 | "CpuHeader":"ЦП", 13 | "GpuHeader":"ГПУ", 14 | "RamHeader":"ОЗУ", 15 | "Adapters":"Адаптеры", 16 | "ApparTempDesc":"По ощущению", 17 | "WindSpeedDesc":"Ветер", 18 | "CloudCoverDesc":"Облачность", 19 | "ChanceOfRain":"Вероятность осадков", 20 | "HumidityDesc":"Влажность", 21 | "Pressure":"мм. рт. ст", 22 | "PressureDesc":"Давление", 23 | "UVIndexDesc":"УФ-индекс", 24 | "UVIndexLow":"Низкий", 25 | "UVIndexMedium":"Умеренный", 26 | "UVIndexHigh":"Высокий", 27 | "UVIndexVeryHigh":"Очень высокий", 28 | "UVIndexExtrem":"Экстримальный", 29 | "WindUnitKmH":"км/ч", 30 | "WindUnitMH":"м/ч", 31 | "WindUnitMS":"м/с", 32 | "WindDirDesc0":"С", 33 | "WindDirDesc22":"ССВ", 34 | "WindDirDesc45":"СВ", 35 | "WindDirDesc67":"ВСВ", 36 | "WindDirDesc90":"В", 37 | "WindDirDesc112":"ВЮВ", 38 | "WindDirDesc135":"ЮВ", 39 | "WindDirDesc157":"ЮЮВ", 40 | "WindDirDesc180":"Ю", 41 | "WindDirDesc202":"ЮЮЗ", 42 | "WindDirDesc225":"ЮЗ", 43 | "WindDirDesc247":"ЗЮЗ", 44 | "WindDirDesc270":"З", 45 | "WindDirDesc292":"ЗСЗ", 46 | "WindDirDesc315":"СЗ", 47 | "WindDirDesc337":"ССЗ", 48 | "WaterTempDesc":"Вода", 49 | "SunsetDesc":"Закат", 50 | "SunriseDesc":"Рассвет", 51 | "CityDesc":"Город", 52 | "LastUpdateDesc":"Обновлено", 53 | "Hourly":"По часам", 54 | "Daily":"По дням", 55 | "Update":"Обновить", 56 | "Providers":"Провайдеры погоды", 57 | "Time":"Время", 58 | "GenTabSetting":"Общие", 59 | "Network":"Сеть", 60 | "LangSetting":"Язык", 61 | "Russia":"Русский", 62 | "English":"Английский", 63 | "WidgSetting":"Виджеты", 64 | "DiscsSetting":"Диски", 65 | "ComboSetting":"Комбо", 66 | "WeatherSetting":"Погода", 67 | "ApiKeySettings":"Ключ API", 68 | "EnterCityWM":"Введите название города", 69 | "AutostartHeaderSetting":"Автозапуск", 70 | "AutostartTogle":"Запускать вместе с Windows", 71 | "LocationSetting":"Местоположение", 72 | "Themes":"Темы", 73 | "Dark":"Темная", 74 | "Light":"Светлая", 75 | "NetUnit":"Единицы измерение", 76 | "MbitSettings":"Мегабит в секунду (Мбит/с)", 77 | "MbyteSettings":"Мегабайт в секунду (Мбайт/с)", 78 | "Cancel":"Отмена", 79 | } -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/Styles/Dark.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | #117dbb 9 | 10 | #117dbb 11 | 12 | #632d8b 13 | 14 | #FF0000 15 | 16 | #4f9847 17 | 18 | #d3772e 19 | 20 | /Assets/Fonts/SegoeUILight.ttf#Segoe UI 21 | 22 | 27 | 28 | 33 | 37 | 42 | 46 | 50 | 54 | 59 | 64 | 69 | 74 | 75 | 80 | 87 | 92 | 96 | 97 | 103 | 109 | 110 | 114 | -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/Styles/Light.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | #117dbb 9 | 10 | #117dbb 11 | 12 | #632d8b 13 | 14 | #FF0000 15 | 16 | #4f9847 17 | 18 | #d3772e 19 | 20 | /Assets/Fonts/SegoeUILight.ttf#Segoe UI 21 | 22 | 27 | 28 | 33 | 37 | 42 | 46 | 50 | 54 | 59 | 64 | 69 | 74 | 75 | 80 | 87 | 92 | 96 | 97 | 102 | 107 | 108 | 112 | -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_0.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_1.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_10.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_11.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_12.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_13.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_14.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_15.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_16.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_17.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_18.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_19.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_2.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_20.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_21.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_22.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_23.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_3.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_4.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_5.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_6.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_7.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_8.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/30/weather_9.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_0.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_1.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_10.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_11.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_12.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_13.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_14.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_15.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_16.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_17.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_18.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_19.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_2.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_20.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_21.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_22.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_23.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_3.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_4.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_5.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_6.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_7.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_8.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/Black/65/weather_9.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_0.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_1.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_10.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_11.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_12.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_13.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_14.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_15.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_16.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_17.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_18.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_19.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_2.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_20.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_21.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_22.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_23.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_3.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_4.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_5.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_6.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_7.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_8.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/30/weather_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/30/weather_9.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_0.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_1.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_10.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_11.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_12.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_13.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_14.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_15.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_16.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_17.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_18.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_19.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_2.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_20.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_21.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_22.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_23.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_3.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_4.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_5.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_6.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_7.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_8.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/WeatherIcons/White/65/weather_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/WeatherIcons/White/65/weather_9.png -------------------------------------------------------------------------------- /SysMonAvalonia/Assets/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FanIT/SysMonAvalonia/49c7969314f02f1ef9ef24e7b91ddf953e6fe469/SysMonAvalonia/Assets/icon.ico -------------------------------------------------------------------------------- /SysMonAvalonia/Converters/BitmapValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Globalization; 4 | using Avalonia; 5 | using Avalonia.Platform; 6 | using Avalonia.Media.Imaging; 7 | using Avalonia.Data.Converters; 8 | 9 | namespace SysMonAvalonia.Converters 10 | { 11 | class BitmapValueConverter : IValueConverter 12 | { 13 | public static BitmapValueConverter Instance = new BitmapValueConverter(); 14 | 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | if (value == null) 18 | return null; 19 | 20 | if (value is string rawUri && targetType.IsAssignableFrom(typeof(Bitmap))) 21 | { 22 | Uri uri; 23 | 24 | // Allow for assembly overrides 25 | if (rawUri.StartsWith("avares://")) 26 | { 27 | uri = new Uri(rawUri); 28 | } 29 | else 30 | { 31 | string assemblyName = Assembly.GetEntryAssembly().GetName().Name; 32 | uri = new Uri($"avares://{assemblyName}{rawUri}"); 33 | } 34 | 35 | var assets = AvaloniaLocator.Current.GetService(); 36 | var asset = assets.Open(uri); 37 | 38 | return new Bitmap(asset); 39 | } 40 | 41 | throw new NotSupportedException(); 42 | } 43 | 44 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 45 | { 46 | throw new NotSupportedException(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SysMonAvalonia/Converters/DataValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Avalonia.Data.Converters; 4 | using SysMonAvalonia.Localization; 5 | 6 | namespace SysMonAvalonia.Converters 7 | { 8 | class DataValueConverter : IValueConverter 9 | { 10 | public static DataValueConverter Instance = new DataValueConverter(); 11 | 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | string param = (string)parameter; 15 | 16 | if (param.Contains("temp")) 17 | { 18 | if (value is sbyte) 19 | { 20 | sbyte temp = (sbyte)value; 21 | 22 | if (temp == -100) return "--"; 23 | 24 | if (temp >= 0) return $"+{temp}°"; 25 | else return $"{temp}°"; 26 | } 27 | } 28 | 29 | if (param.Contains("percent")) return $"{value}%"; 30 | if (param.Contains("pressure")) return $"{value} {Language.Locale.Pressure}"; 31 | if (param.Contains("uvindex")) return $"{GetNameUVIndex((byte)value)} ({value})"; 32 | 33 | return null; 34 | } 35 | 36 | private string GetNameUVIndex(byte index) 37 | { 38 | if (index < 3) return Language.Locale.UVIndexLow; 39 | else if (index > 2 && index < 6) return Language.Locale.UVIndexMedium; 40 | else if (index > 5 && index < 8) return Language.Locale.UVIndexHigh; 41 | else if (index > 7 && index < 11) return Language.Locale.UVIndexVeryHigh; 42 | else return Language.Locale.UVIndexExtrem; 43 | } 44 | 45 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 46 | { 47 | throw new NotImplementedException(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SysMonAvalonia/Converters/DeviceIoValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Avalonia.Data.Converters; 4 | 5 | namespace SysMonAvalonia.Converters 6 | { 7 | public class DeviceIoValueConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | if (value is long) 12 | return ((long)value / 1073741824.0).ToString("0.#"); 13 | 14 | return null; 15 | } 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SysMonAvalonia/Converters/NetworkValueConvert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Avalonia.Data.Converters; 4 | using SysMonAvalonia.Data; 5 | 6 | namespace SysMonAvalonia.Converters 7 | { 8 | public class NetworkValueConvert : IValueConverter 9 | { 10 | public static NetworkValueConvert Instange = new(); 11 | 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | if (parameter is string and "gb") 15 | return (long)value / 1073741824.0; 16 | 17 | if (SettingData.CurrentSetting.NetworkUnit == SettingData.NetUnit.Megabits) 18 | return (long)value / 125000.0; 19 | else 20 | return (long)value / 1048576.0; 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SysMonAvalonia/Converters/SettingsValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using Avalonia.Data.Converters; 5 | using Weather.Providers; 6 | using Hardware.Windows.Network; 7 | using SysMonAvalonia.Data; 8 | 9 | namespace SysMonAvalonia.Converters 10 | { 11 | public class SettingsValueConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | if (parameter as string == "lang" && value is string lang) 16 | { 17 | if (lang == "en-US") return 0; 18 | if (lang == "ru-RU") return 1; 19 | } 20 | 21 | if (parameter as string == "theme") 22 | return (int)value; 23 | 24 | if (parameter as string == "wprovider") 25 | return (int)SettingData.CurrentSetting.Provider; 26 | 27 | if (parameter as string == "apikey") 28 | { 29 | int val = (int)value; 30 | 31 | if (val == 2 || val == 3) return true; 32 | else return false; 33 | } 34 | 35 | if (parameter as string == "netadapter" && value is string adapterID) 36 | { 37 | List adapterList = NetworkInfo.GetInterface(); 38 | 39 | for (int i = 0; i < adapterList.Count; i++) 40 | { 41 | if (adapterList[i].ID.Contains(adapterID)) return i; 42 | } 43 | } 44 | 45 | if (parameter as string == "netunit" && value is SettingData.NetUnit) 46 | return (int)value; 47 | 48 | return null; 49 | } 50 | 51 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 52 | { 53 | if (parameter as string == "lang" && value is int lang) 54 | { 55 | if (lang == 0) return "en-US"; 56 | if (lang == 1) return "ru-RU"; 57 | } 58 | 59 | if (parameter as string == "theme" && value is int theme) 60 | return (SettingData.Theme)theme; 61 | 62 | if (parameter as string == "wprovider" && value is int provider) 63 | return (Providers)provider; 64 | 65 | if (parameter as string == "netadapter" && value is int adapter) 66 | return NetworkInfo.GetInterface()[adapter].ID; 67 | 68 | if (parameter as string == "netunit" && value is int unit) 69 | return (SettingData.NetUnit)unit; 70 | 71 | return null; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /SysMonAvalonia/Data/ComboData.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace SysMonAvalonia.Data 4 | { 5 | public class ComboData : ReactiveObject 6 | { 7 | private double _ramTotal; 8 | private double _ramUsed; 9 | private byte _ramPercent; 10 | 11 | private float _cpuUsedPercent; 12 | private float _cpuTemp; 13 | 14 | private float _gpuUsedPercent; 15 | private float _gpuTemp; 16 | 17 | private float _gpuTotalRam; 18 | private float _gpuUsedRam; 19 | private float _gpuUsedPercentRam; 20 | 21 | private long _netByteReceived; 22 | private long _netByteSend; 23 | private long _netTotalByteReceived; 24 | private long _netTotalByteSend; 25 | 26 | private string _netUnit; 27 | 28 | public double RamTotal 29 | { 30 | get => _ramTotal; 31 | set => this.RaiseAndSetIfChanged(ref _ramTotal, value); 32 | } 33 | public double RamUsed 34 | { 35 | get => _ramUsed; 36 | set => this.RaiseAndSetIfChanged(ref _ramUsed, value); 37 | } 38 | public byte RamPercent 39 | { 40 | get => _ramPercent; 41 | set => this.RaiseAndSetIfChanged(ref _ramPercent, value); 42 | } 43 | public float CpuUsedPercent 44 | { 45 | get => _cpuUsedPercent; 46 | set => this.RaiseAndSetIfChanged(ref _cpuUsedPercent, value); 47 | } 48 | public float CpuTemp 49 | { 50 | get => _cpuTemp; 51 | set => this.RaiseAndSetIfChanged(ref _cpuTemp, value); 52 | } 53 | public float GpuUsedPercent 54 | { 55 | get => _gpuUsedPercent; 56 | set => this.RaiseAndSetIfChanged(ref _gpuUsedPercent, value); 57 | } 58 | public float GpuTemp 59 | { 60 | get => _gpuTemp; 61 | set => this.RaiseAndSetIfChanged(ref _gpuTemp, value); 62 | } 63 | public float GpuTotalRam 64 | { 65 | get => _gpuTotalRam; 66 | set => this.RaiseAndSetIfChanged(ref _gpuTotalRam, value); 67 | } 68 | public float GpuUsedRam 69 | { 70 | get => _gpuUsedRam; 71 | set => this.RaiseAndSetIfChanged(ref _gpuUsedRam, value); 72 | } 73 | public float GpuUsedPercentRam 74 | { 75 | get => _gpuUsedPercentRam; 76 | set => this.RaiseAndSetIfChanged(ref _gpuUsedPercentRam, value); 77 | } 78 | public long GetByteNet 79 | { 80 | get => _netByteReceived; 81 | set => this.RaiseAndSetIfChanged(ref _netByteReceived, value); 82 | } 83 | public long GetTotalByteNet 84 | { 85 | get => _netTotalByteReceived; 86 | set => this.RaiseAndSetIfChanged(ref _netTotalByteReceived, value); 87 | } 88 | public long SentByteNet 89 | { 90 | get => _netByteSend; 91 | set => this.RaiseAndSetIfChanged(ref _netByteSend, value); 92 | } 93 | public long SentTotalByteNet 94 | { 95 | get => _netTotalByteSend; 96 | set => this.RaiseAndSetIfChanged(ref _netTotalByteSend, value); 97 | } 98 | public string NetUnit 99 | { 100 | get => _netUnit; 101 | set => this.RaiseAndSetIfChanged(ref _netUnit, value); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /SysMonAvalonia/Data/DeviceIoData.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using SysMonAvalonia.Models; 3 | 4 | namespace SysMonAvalonia.Data 5 | { 6 | public class DeviceIoData : ReactiveObject 7 | { 8 | private string _model; 9 | private string _letter; 10 | private long _totalSize; 11 | private long _usedSize; 12 | private byte _percentUsed; 13 | private byte _health; 14 | private bool _isHealth; 15 | private float _totalWrite; 16 | private bool _isTotalWrite; 17 | private float _writeIO; 18 | private float _readIO; 19 | private readonly ChartModel _chartModel = new(); 20 | 21 | public short Index { get; set; } 22 | 23 | public string Model 24 | { 25 | get => _model; 26 | set => this.RaiseAndSetIfChanged(ref _model, value); 27 | } 28 | public string Letter 29 | { 30 | get => _letter; 31 | set => this.RaiseAndSetIfChanged(ref _letter, value); 32 | } 33 | public long TotalSize 34 | { 35 | get => _totalSize; 36 | set => this.RaiseAndSetIfChanged(ref _totalSize, value); 37 | } 38 | public long UsedSize 39 | { 40 | get => _usedSize; 41 | set => this.RaiseAndSetIfChanged(ref _usedSize, value); 42 | } 43 | public byte PercentUsed 44 | { 45 | get => _percentUsed; 46 | set => this.RaiseAndSetIfChanged(ref _percentUsed, value); 47 | } 48 | public byte Health 49 | { 50 | get => _health; 51 | set => this.RaiseAndSetIfChanged(ref _health, value); 52 | } 53 | public bool IsHealth 54 | { 55 | get => _isHealth; 56 | set => this.RaiseAndSetIfChanged(ref _isHealth, value); 57 | } 58 | public float TotalWrite 59 | { 60 | get => _totalWrite; 61 | set => this.RaiseAndSetIfChanged(ref _totalWrite, value); 62 | } 63 | public bool IsTotalWrite 64 | { 65 | get => _isTotalWrite; 66 | set => this.RaiseAndSetIfChanged(ref _isTotalWrite, value); 67 | } 68 | public float WriteIO 69 | { 70 | get => _writeIO; 71 | set => this.RaiseAndSetIfChanged(ref _writeIO, value); 72 | } 73 | public float ReadIO 74 | { 75 | get => _readIO; 76 | set => this.RaiseAndSetIfChanged(ref _readIO, value); 77 | } 78 | 79 | public ChartModel DeviceChart 80 | { 81 | get => _chartModel; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /SysMonAvalonia/Data/ForecastData.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace SysMonAvalonia.Data 4 | { 5 | public class ForecastData : ReactiveObject 6 | { 7 | private string _dateTime; 8 | private string _icon; 9 | private sbyte _tempMin; 10 | private sbyte _tempMax; 11 | private string _phase; 12 | 13 | public string DateTime 14 | { 15 | get => _dateTime; 16 | set => this.RaiseAndSetIfChanged(ref _dateTime, value); 17 | } 18 | public string Icon 19 | { 20 | get => _icon; 21 | set => this.RaiseAndSetIfChanged(ref _icon, value); 22 | } 23 | public sbyte TempMin 24 | { 25 | get => _tempMin; 26 | set => this.RaiseAndSetIfChanged(ref _tempMin, value); 27 | } 28 | public sbyte TempMax 29 | { 30 | get => _tempMax; 31 | set => this.RaiseAndSetIfChanged(ref _tempMax, value); 32 | } 33 | public string Phase 34 | { 35 | get => _phase; 36 | set => this.RaiseAndSetIfChanged(ref _phase, value); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SysMonAvalonia/Data/SettingData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Newtonsoft.Json; 4 | using Weather.Providers; 5 | 6 | namespace SysMonAvalonia.Data 7 | { 8 | [JsonObject(MemberSerialization.OptIn)] 9 | public class SettingData 10 | { 11 | public enum NetUnit : int 12 | { 13 | Megabits = 0, 14 | Megabytes = 1 15 | } 16 | public enum Theme : int 17 | { 18 | Dark = 0, 19 | Light = 1 20 | } 21 | [JsonObject(MemberSerialization.OptIn)] 22 | public class WidgetProperties 23 | { 24 | [JsonProperty("IsStartup")] 25 | public bool IsStartup { get; set; } 26 | [JsonProperty("X")] 27 | public int X { get; set; } 28 | [JsonProperty("Y")] 29 | public int Y { get; set; } 30 | 31 | public WidgetProperties() 32 | { 33 | IsStartup = false; 34 | X = 0; 35 | Y = 0; 36 | } 37 | } 38 | 39 | private readonly string SettingFile; 40 | [JsonProperty("Language")] 41 | public string Language { get; set; } 42 | public CultureInfo Culture { get; set; } 43 | [JsonProperty("Theme")] 44 | public Theme Style { get; set; } 45 | [JsonProperty("WeatherProvider")] 46 | public Providers Provider { get; set; } 47 | [JsonProperty("WeatherWidget")] 48 | public WidgetProperties WeatherWidget { get; set; } = new(); 49 | [JsonProperty("DeviceIoWidget")] 50 | public WidgetProperties DeviceIoWidget { get; set; } = new(); 51 | [JsonProperty("ComboWidget")] 52 | public WidgetProperties ComboWidget { get; set; } = new(); 53 | [JsonProperty("WeatherInterval")] 54 | public int WeatherInterval { get; set; } 55 | [JsonProperty("WeatherLastUpdate")] 56 | public DateTime WeatherLastUpdate { get; set; } 57 | [JsonProperty("WeatherApiKey")] 58 | public string WeatherApiKey { get; set; } 59 | [JsonProperty("WeatherID")] 60 | public string WeatherID { get; set; } 61 | [JsonProperty("WeatherCity")] 62 | public string WeatherCity { get; set; } 63 | [JsonProperty("NetworkAdapter")] 64 | public string AdapterName { get; set; } 65 | public string AdapterID { get; set; } 66 | [JsonProperty("NetworkUnit")] 67 | public NetUnit NetworkUnit { get; set; } 68 | public static SettingData CurrentSetting { get; set; } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /SysMonAvalonia/Data/WeatherData.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace SysMonAvalonia.Data 4 | { 5 | public class WeatherData : ReactiveObject 6 | { 7 | private string _currentIcon; 8 | private string _currentPhase; 9 | private sbyte _currentTemp; 10 | private sbyte _minTemp; 11 | private sbyte _maxTemp; 12 | private sbyte _apparTemp; 13 | private string _windAbbr; 14 | private short _windSpeed; 15 | private double _windDegree; 16 | private string _windUnit; 17 | private byte _cloudCover; 18 | private bool _isCloudyCover; 19 | private byte _precipitation; 20 | private bool _isPreciptation; 21 | private byte _humidity; 22 | private short _pressure; 23 | private byte _uvIndex; 24 | private string _sunset; 25 | private string _sunrise; 26 | private string _city; 27 | private string _lastUpdate; 28 | 29 | public string CurrentIcon 30 | { 31 | get => _currentIcon; 32 | set => this.RaiseAndSetIfChanged(ref _currentIcon, value); 33 | } 34 | public string CurrentPhase 35 | { 36 | get => _currentPhase; 37 | set => this.RaiseAndSetIfChanged(ref _currentPhase, value); 38 | } 39 | public sbyte CurrentTemp 40 | { 41 | get => _currentTemp; 42 | set => this.RaiseAndSetIfChanged(ref _currentTemp, value); 43 | } 44 | public sbyte MinTemp 45 | { 46 | get => _minTemp; 47 | set => this.RaiseAndSetIfChanged(ref _minTemp, value); 48 | } 49 | public sbyte MaxTemp 50 | { 51 | get => _maxTemp; 52 | set => this.RaiseAndSetIfChanged(ref _maxTemp, value); 53 | } 54 | public sbyte ApparTemp 55 | { 56 | get => _apparTemp; 57 | set => this.RaiseAndSetIfChanged(ref _apparTemp, value); 58 | } 59 | public string WindAbbr 60 | { 61 | get => _windAbbr; 62 | set => this.RaiseAndSetIfChanged(ref _windAbbr, value); 63 | } 64 | public short WindSpeed 65 | { 66 | get => _windSpeed; 67 | set => this.RaiseAndSetIfChanged(ref _windSpeed, value); 68 | } 69 | public double WindDegree 70 | { 71 | get => _windDegree; 72 | set => this.RaiseAndSetIfChanged(ref _windDegree, value); 73 | } 74 | public string WindUnit 75 | { 76 | get => _windUnit; 77 | set => this.RaiseAndSetIfChanged(ref _windUnit, value); 78 | } 79 | public byte CloudCover 80 | { 81 | get => _cloudCover; 82 | set => this.RaiseAndSetIfChanged(ref _cloudCover, value); 83 | } 84 | public bool IsCloudyCover 85 | { 86 | get => _isCloudyCover; 87 | set => this.RaiseAndSetIfChanged(ref _isCloudyCover, value); 88 | } 89 | public byte Precipitation 90 | { 91 | get => _precipitation; 92 | set => this.RaiseAndSetIfChanged(ref _precipitation, value); 93 | } 94 | public bool IsPreciptation 95 | { 96 | get => _isPreciptation; 97 | set => this.RaiseAndSetIfChanged(ref _isPreciptation, value); 98 | } 99 | public byte Humidity 100 | { 101 | get => _humidity; 102 | set => this.RaiseAndSetIfChanged(ref _humidity, value); 103 | } 104 | public short Pressure 105 | { 106 | get => _pressure; 107 | set => this.RaiseAndSetIfChanged(ref _pressure, value); 108 | } 109 | public byte UVIndex 110 | { 111 | get => _uvIndex; 112 | set => this.RaiseAndSetIfChanged(ref _uvIndex, value); 113 | } 114 | public string Sunset 115 | { 116 | get => _sunset; 117 | set => this.RaiseAndSetIfChanged(ref _sunset, value); 118 | } 119 | public string Sunrise 120 | { 121 | get => _sunrise; 122 | set => this.RaiseAndSetIfChanged(ref _sunrise, value); 123 | } 124 | public string City 125 | { 126 | get => _city; 127 | set => this.RaiseAndSetIfChanged(ref _city, value); 128 | } 129 | public string LastUpdate 130 | { 131 | get => _lastUpdate; 132 | set => this.RaiseAndSetIfChanged(ref _lastUpdate, value); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /SysMonAvalonia/Localization/Language.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using Avalonia; 5 | using Avalonia.Platform; 6 | using Newtonsoft.Json; 7 | 8 | namespace SysMonAvalonia.Localization 9 | { 10 | public class Language 11 | { 12 | public string Close { get; set; } 13 | public string Settings { get; set; } 14 | public string Mb { get; set; } 15 | public string Gb { get; set; } 16 | public string Tb { get; set; } 17 | public string Mbit { get; set; } 18 | public string Mbyte { get; set; } 19 | public string Health { get; set; } 20 | public string Write { get; set; } 21 | public string ReadIO { get; set; } 22 | public string WriteIO { get; set; } 23 | public string CpuHeader { get; set; } 24 | public string GpuHeader { get; set; } 25 | public string RamHeader { get; set; } 26 | public string Adapters { get; set; } 27 | public string ApparTempDesc { get; set; } 28 | public string WindSpeedDesc { get; set; } 29 | public string CloudCoverDesc { get; set; } 30 | public string ChanceOfRain { get; set; } 31 | public string HumidityDesc { get; set; } 32 | public string Pressure { get; set; } 33 | public string PressureDesc { get; set; } 34 | public string UVIndexDesc { get; set; } 35 | public string UVIndexLow { get; set; } 36 | public string UVIndexMedium { get; set; } 37 | public string UVIndexHigh { get; set; } 38 | public string UVIndexVeryHigh { get; set; } 39 | public string UVIndexExtrem { get; set; } 40 | public string WindUnitKmH { get; set; } 41 | public string WindUnitMH { get; set; } 42 | public string WindUnitMS { get; set; } 43 | public string WindDirDesc0 { get; set; } 44 | public string WindDirDesc22 { get; set; } 45 | public string WindDirDesc45 { get; set; } 46 | public string WindDirDesc67 { get; set; } 47 | public string WindDirDesc90 { get; set; } 48 | public string WindDirDesc112 { get; set; } 49 | public string WindDirDesc135 { get; set; } 50 | public string WindDirDesc157 { get; set; } 51 | public string WindDirDesc180 { get; set; } 52 | public string WindDirDesc202 { get; set; } 53 | public string WindDirDesc225 { get; set; } 54 | public string WindDirDesc247 { get; set; } 55 | public string WindDirDesc270 { get; set; } 56 | public string WindDirDesc292 { get; set; } 57 | public string WindDirDesc315 { get; set; } 58 | public string WindDirDesc337 { get; set; } 59 | public string WaterTempDesc { get; set; } 60 | public string SunsetDesc { get; set; } 61 | public string SunriseDesc { get; set; } 62 | public string CityDesc { get; set; } 63 | public string LastUpdateDesc { get; set; } 64 | public string Hourly { get; set; } 65 | public string Daily { get; set; } 66 | public string Update { get; set; } 67 | public string Providers { get; set; } 68 | public string Time { get; set; } 69 | public string GenTabSetting { get; set; } 70 | public string Network { get; set; } 71 | public string LangSetting { get; set; } 72 | public string Russia { get; set; } 73 | public string English { get; set; } 74 | public string WidgSetting { get; set; } 75 | public string DiscsSetting { get; set; } 76 | public string ComboSetting { get; set; } 77 | public string WeatherSetting { get; set; } 78 | public string ApiKeySettings { get; set; } 79 | public string EnterCityWM { get; set; } 80 | public string AutostartHeaderSetting { get; set; } 81 | public string AutostartTogle { get; set; } 82 | public string LocationSetting { get; set; } 83 | public string Themes { get; set; } 84 | public string Dark { get; set; } 85 | public string Light { get; set; } 86 | public string NetUnit { get; set; } 87 | public string MbitSettings { get; set; } 88 | public string MbyteSettings { get; set; } 89 | public string Cancel { get; set; } 90 | public static Language Locale { get; set; } 91 | 92 | public static void Load(CultureInfo culture) 93 | { 94 | IAssetLoader asset = AvaloniaLocator.Current.GetService(); 95 | 96 | string lngFile = culture.ThreeLetterISOLanguageName.ToLower() == "rus" ? "ru.json" : "en.json"; 97 | 98 | using (StreamReader reader = 99 | new StreamReader(asset.Open(new Uri($"avares://SysMonAvalonia/Assets/Locale/{lngFile}")))) 100 | { 101 | try 102 | { 103 | Locale = JsonConvert.DeserializeObject(reader.ReadToEnd()); 104 | } 105 | catch 106 | { 107 | Locale = new(); 108 | } 109 | } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /SysMonAvalonia/Models/ChartModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using LiveChartsCore; 3 | using LiveChartsCore.Defaults; 4 | using LiveChartsCore.Drawing; 5 | using LiveChartsCore.SkiaSharpView; 6 | using LiveChartsCore.SkiaSharpView.Painting; 7 | 8 | namespace SysMonAvalonia.Models 9 | { 10 | public class ChartModel 11 | { 12 | private ObservableCollection _observablePoints; 13 | private LineSeries _lineSeries; 14 | 15 | public ISeries[] Series { get; set; } 16 | public Axis[] XAxis { get; set; } 17 | public Axis[] YAxis { get; set; } 18 | public SolidColorPaint? Fill { 19 | set => _lineSeries.Fill = value; 20 | } 21 | public double Value 22 | { 23 | set => AddPoint(value); 24 | } 25 | 26 | public ChartModel() 27 | { 28 | _observablePoints = new(); 29 | 30 | FillPoints(); 31 | 32 | _lineSeries = new LineSeries 33 | { 34 | Values = _observablePoints, 35 | Stroke = null, 36 | GeometryFill = null, 37 | GeometryStroke = null, 38 | GeometrySize = 0, 39 | DataPadding = new LvcPoint(0, 0) 40 | }; 41 | 42 | Series = new[] { _lineSeries }; 43 | 44 | XAxis = new[] 45 | { 46 | new Axis { IsVisible = false } 47 | }; 48 | 49 | YAxis = new[] 50 | { 51 | new Axis 52 | { 53 | IsVisible = false, 54 | MinLimit = 0, 55 | MaxLimit = 100 56 | } 57 | }; 58 | } 59 | 60 | private void AddPoint(double point) 61 | { 62 | if (point > YAxis[0].MaxLimit) YAxis[0].MaxLimit = point; 63 | 64 | _observablePoints.Add(new ObservableValue(point)); 65 | _observablePoints.RemoveAt(0); 66 | } 67 | 68 | public void ClearPoints() 69 | { 70 | _observablePoints.Clear(); 71 | } 72 | 73 | public void FillPoints(double point = 0) 74 | { 75 | for (byte b = 0; b < 60; b++) 76 | { 77 | _observablePoints.Add(new ObservableValue(point)); 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /SysMonAvalonia/Models/ComboModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SysMonAvalonia.Data; 3 | using Hardware; 4 | using Hardware.Windows.Network; 5 | using SysMonAvalonia.Localization; 6 | 7 | namespace SysMonAvalonia.Models 8 | { 9 | public class ComboModel : IDisposable 10 | { 11 | public ComboData ComboData { get; } 12 | 13 | public ComboModel() 14 | { 15 | this.ComboData = new(); 16 | 17 | Computer.Open(); 18 | 19 | NetworkInfo.SpeedUpdate(); 20 | 21 | ComboData.GetTotalByteNet = NetworkInfo.ByteReceived; 22 | ComboData.SentTotalByteNet = NetworkInfo.ByteSend; 23 | 24 | ComboData.NetUnit = SettingData.CurrentSetting.NetworkUnit == SettingData.NetUnit.Megabits 25 | ? Language.Locale.Mbit 26 | : Language.Locale.Mbyte; 27 | } 28 | 29 | public void ComputerDataUpdate() 30 | { 31 | Computer.Update(); 32 | 33 | ComboData.CpuUsedPercent = Computer.CPUPercent; 34 | ComboData.CpuTemp = Computer.CPUTemp; 35 | 36 | ComboData.GpuUsedPercent = Computer.GPUPercent; 37 | ComboData.GpuTemp = Computer.GPUTemp; 38 | ComboData.GpuTotalRam = Computer.GPUTotalRam; 39 | ComboData.GpuUsedRam = Computer.GPUUsedRam; 40 | ComboData.GpuUsedPercentRam = Computer.GPUPercentRam; 41 | 42 | ComboData.RamTotal = Computer.RamTotal; 43 | ComboData.RamUsed = Computer.RamUsed; 44 | ComboData.RamPercent = Computer.RamPercent; 45 | 46 | NetworkInfo.SpeedUpdate(); 47 | 48 | ComboData.GetByteNet = NetworkInfo.ByteReceived - ComboData.GetTotalByteNet; 49 | ComboData.SentByteNet = NetworkInfo.ByteSend - ComboData.SentTotalByteNet; 50 | 51 | ComboData.GetTotalByteNet = NetworkInfo.ByteReceived; 52 | ComboData.SentTotalByteNet = NetworkInfo.ByteSend; 53 | } 54 | 55 | public void Dispose() 56 | { 57 | Computer.Close(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SysMonAvalonia/Models/DeviceIoModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reactive.Linq; 7 | using Avalonia; 8 | using Avalonia.Controls; 9 | using DynamicData; 10 | using Hardware.Windows.DeviceIoInfo; 11 | using LiveChartsCore.SkiaSharpView.Painting; 12 | using ReactiveUI; 13 | using SysMonAvalonia.Data; 14 | 15 | namespace SysMonAvalonia.Models 16 | { 17 | public class DeviceIoModel : IDisposable 18 | { 19 | private readonly SourceList _deviceList; 20 | public ReadOnlyObservableCollection DeviceCollection; 21 | 22 | public DeviceIoModel() 23 | { 24 | _deviceList = new(); 25 | _deviceList.Connect().ObserveOn(RxApp.MainThreadScheduler).Bind(out DeviceCollection).Subscribe(); 26 | } 27 | 28 | public void UpdateDeviceCollection() 29 | { 30 | if (DeviceInfo.IsUpdateDiscs()) 31 | { 32 | List devices = DeviceInfo.LogicalDrives; 33 | 34 | if (_deviceList.Count > devices.Count) 35 | RemoveOldDeviceInCollection(devices); 36 | 37 | foreach (Device dev in devices) 38 | { 39 | if (ExistDeviceInCollection(dev)) continue; 40 | 41 | DeviceIoData device = new(); 42 | device.Index = dev.Index; 43 | device.Model = dev.Model; 44 | device.Letter = dev.Letter; 45 | device.DeviceChart.Fill = Application.Current.FindResource("DeviceChartFill") as SolidColorPaint; 46 | 47 | _deviceList.Add(device); 48 | } 49 | } 50 | } 51 | 52 | public void UpdateDeviceSpace() 53 | { 54 | try 55 | { 56 | DeviceInfo.UpdateSizeOfDiscs(); 57 | } 58 | catch (DriveNotFoundException) 59 | { 60 | UpdateDeviceCollection(); 61 | DeviceInfo.UpdateSizeOfDiscs(); 62 | } 63 | 64 | foreach (DeviceIoData devData in _deviceList.Items) 65 | { 66 | devData.TotalSize = DeviceInfo.LogicalDrives[devData.Index].TotalSpace; 67 | devData.UsedSize = DeviceInfo.LogicalDrives[devData.Index].UsedSpace; 68 | devData.PercentUsed = DeviceInfo.LogicalDrives[devData.Index].PercentUsedSpace; 69 | } 70 | } 71 | 72 | public void UpdateDeviceInfo() 73 | { 74 | DeviceInfo.UpdateInfoOfDiscs(); 75 | 76 | foreach (DeviceIoData devData in _deviceList.Items) 77 | { 78 | devData.Health = DeviceInfo.LogicalDrives[devData.Index].Health; 79 | devData.TotalWrite = DeviceInfo.LogicalDrives[devData.Index].TotalWrite; 80 | 81 | devData.IsHealth = devData.Health != 0; 82 | devData.IsTotalWrite = devData.TotalWrite != 0; 83 | } 84 | } 85 | 86 | public void UpdatePerformance() 87 | { 88 | foreach (DeviceIoData dId in _deviceList.Items) 89 | { 90 | DeviceInfo.PerfomanceDiskUpdate(dId.Index); 91 | 92 | dId.ReadIO = DeviceInfo.ReadIo; 93 | dId.WriteIO = DeviceInfo.WriteIo; 94 | dId.DeviceChart.Value = DeviceInfo.ReadIo + DeviceInfo.WriteIo; 95 | } 96 | } 97 | 98 | private bool ExistDeviceInCollection(Device device) 99 | { 100 | return _deviceList.Items.Any(did => did.Model.Contains(device.Model) && did.TotalSize == device.TotalSpace); 101 | } 102 | 103 | private void RemoveOldDeviceInCollection(IReadOnlyCollection device) 104 | { 105 | short index = 0; 106 | 107 | foreach (DeviceIoData item in _deviceList.Items) 108 | { 109 | if (!device.Any(dev => dev.Model.Contains(item.Model) && dev.TotalSpace == item.TotalSize)) 110 | _deviceList.RemoveAt(index); 111 | 112 | item.Index = index; 113 | 114 | index++; 115 | } 116 | } 117 | 118 | public void Dispose() 119 | { 120 | _deviceList.Dispose(); 121 | DeviceInfo.Close(); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /SysMonAvalonia/Models/ForecastModel.cs: -------------------------------------------------------------------------------- 1 | namespace SysMonAvalonia.Models 2 | { 3 | public class ForecastModel 4 | { 5 | public string DateTime { get; set; } 6 | public string Icon { get; set; } 7 | public sbyte TempMax { get; set; } 8 | public sbyte TempMin { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SysMonAvalonia/Models/SettingModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using Newtonsoft.Json; 6 | using Newtonsoft.Json.Linq; 7 | using SysMonAvalonia.Data; 8 | using SysMonAvalonia.Services; 9 | using Weather; 10 | using Weather.Providers; 11 | using Hardware.Windows.Network; 12 | 13 | namespace SysMonAvalonia.Models 14 | { 15 | public class SettingModel 16 | { 17 | public List NetworkAdapters 18 | { 19 | get => NetworkInfo.GetInterface(); 20 | } 21 | 22 | public bool AutostartEnable 23 | { 24 | get => AppService.FindTaskService(AppDomain.CurrentDomain.FriendlyName); 25 | set 26 | { 27 | if (value) 28 | AppService.CreateTaskService($"{AppContext.BaseDirectory}{AppDomain.CurrentDomain.FriendlyName}.exe"); 29 | else 30 | AppService.DeleteTaskService(AppDomain.CurrentDomain.FriendlyName); 31 | } 32 | } 33 | 34 | public static List FindCities(string query) 35 | { 36 | if (query == String.Empty) return null; 37 | 38 | IProvider _weatherProvider; 39 | 40 | List cityList = new(); 41 | 42 | switch (SettingData.CurrentSetting.Provider) 43 | { 44 | case Providers.AccuWeather: _weatherProvider = new AccuWeather(); break; 45 | case Providers.Gismeteo: _weatherProvider = new Gismeteo(); break; 46 | case Providers.OpenWeatherMap: _weatherProvider = new OpenWeatherMap(); break; 47 | case Providers.WorldWeatherOnline: _weatherProvider = new WorldWeatherOnline(); break; 48 | case Providers.Wunderground: _weatherProvider = new Wunderground(); break; 49 | default: return cityList; 50 | } 51 | 52 | return _weatherProvider.GetLocation(query, SettingData.CurrentSetting.Culture, SettingData.CurrentSetting.WeatherApiKey); 53 | } 54 | 55 | public static void Load() 56 | { 57 | if (SettingData.CurrentSetting != null) return; 58 | 59 | string settingFile; 60 | /*#if DEBUG 61 | settingFile = AppContext.BaseDirectory + @"\Settings.json"; 62 | #else*/ 63 | settingFile = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + @"\Settings.json"; 64 | //#endif 65 | 66 | string settingStr; 67 | 68 | try 69 | { 70 | settingStr = File.ReadAllText(settingFile); 71 | } 72 | catch 73 | { 74 | SettingData.CurrentSetting = new(); 75 | SettingData.CurrentSetting.Culture = CultureInfo.CurrentCulture; 76 | SettingData.CurrentSetting.Language = 77 | CultureInfo.CurrentCulture.ThreeLetterISOLanguageName.Contains("rus") ? "ru-RU" : "en-US"; 78 | 79 | return; 80 | } 81 | 82 | SettingData.CurrentSetting = JsonConvert.DeserializeObject(settingStr); 83 | SettingData.CurrentSetting.Culture = SettingData.CurrentSetting.Language != null 84 | ? CultureInfo.GetCultureInfo(SettingData.CurrentSetting.Language) 85 | : CultureInfo.CurrentCulture; 86 | } 87 | 88 | public static void Save() 89 | { 90 | string settingFile; 91 | /*#if DEBUG 92 | settingFile = AppContext.BaseDirectory + @"\Settings.json"; 93 | #else*/ 94 | settingFile = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + @"\Settings.json"; 95 | //#endif 96 | File.WriteAllText(settingFile, JsonConvert.SerializeObject(JObject.FromObject(SettingData.CurrentSetting))); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /SysMonAvalonia/NLog.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SysMonAvalonia/Program.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.ReactiveUI; 3 | using NLog; 4 | using Projektanker.Icons.Avalonia; 5 | using Projektanker.Icons.Avalonia.FontAwesome; 6 | 7 | namespace SysMonAvalonia 8 | { 9 | class Program 10 | { 11 | // Initialization code. Don't use any Avalonia, third-party APIs or any 12 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 13 | // yet and stuff might break. 14 | public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); 15 | 16 | // Avalonia configuration, don't remove; also used by visual designer. 17 | public static AppBuilder BuildAvaloniaApp() 18 | => AppBuilder.Configure() 19 | .UsePlatformDetect() 20 | .LogToTrace() 21 | .WithIcons(container => container.Register()) 22 | .UseReactiveUI(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SysMonAvalonia/Services/AppService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using Avalonia.Controls; 5 | using Avalonia.Controls.ApplicationLifetimes; 6 | using Avalonia.Markup.Xaml.Styling; 7 | using SysMonAvalonia.Views; 8 | using SysMonAvalonia.Data; 9 | using Microsoft.Win32.TaskScheduler; 10 | using SysMonAvalonia.Models; 11 | 12 | namespace SysMonAvalonia.Services 13 | { 14 | public static class AppService 15 | { 16 | private static SettingView _settingWindow; 17 | 18 | public static void ShowSettings() 19 | { 20 | _settingWindow = new SettingView(); 21 | _settingWindow.Show(); 22 | } 23 | 24 | public static void CloseSettings() 25 | { 26 | if (_settingWindow != null) _settingWindow.Close(); 27 | } 28 | 29 | public static bool CreateTaskService(string path) 30 | { 31 | bool isActive = false; 32 | 33 | TaskService task = TaskService.Instance; 34 | LogonTrigger logonTrigger = new(); 35 | TaskDefinition taskDefinition = task.NewTask(); 36 | 37 | try 38 | { 39 | logonTrigger.Delay = TimeSpan.FromSeconds(15); 40 | 41 | taskDefinition.RegistrationInfo.Description = "Auto start " + Path.GetFileNameWithoutExtension(path); 42 | taskDefinition.Principal.RunLevel = TaskRunLevel.Highest; 43 | taskDefinition.Triggers.Add(logonTrigger); 44 | taskDefinition.Actions.Add(new ExecAction(path)); 45 | 46 | isActive = task.RootFolder 47 | .RegisterTaskDefinition(Path.GetFileNameWithoutExtension(path), taskDefinition).IsActive; 48 | } 49 | catch { } 50 | finally 51 | { 52 | taskDefinition.Dispose(); 53 | logonTrigger.Dispose(); 54 | task.Dispose(); 55 | } 56 | 57 | return isActive; 58 | } 59 | 60 | public static void DeleteTaskService(string name) 61 | { 62 | TaskService task = TaskService.Instance; 63 | 64 | task.RootFolder.DeleteFolder(name, false); 65 | 66 | task.Dispose(); 67 | } 68 | 69 | public static bool FindTaskService(string name) 70 | { 71 | bool isExist = false; 72 | 73 | TaskService task = TaskService.Instance; 74 | 75 | try 76 | { 77 | isExist = task.FindTask(name) != null; 78 | } 79 | catch 80 | { 81 | } 82 | finally 83 | { 84 | task.Dispose(); 85 | } 86 | 87 | return isExist; 88 | } 89 | 90 | public static void ShutdownApp() 91 | { 92 | if (App.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 93 | desktop.Shutdown(); 94 | } 95 | 96 | public static void ChangeStyles() 97 | { 98 | string localStyle = SettingData.CurrentSetting.Style == SettingData.Theme.Dark ? "Dark.xaml" : "Light.xaml"; 99 | string fluentStyle = SettingData.CurrentSetting.Style == SettingData.Theme.Dark ? "FluentDark.xaml" : "FluentLight.xaml"; 100 | 101 | StyleInclude fluentStyleInclude = new(baseUri: new Uri("avares://Avalonia.Themes.Fluent")); 102 | fluentStyleInclude.Source = new Uri(fluentStyle, UriKind.Relative); 103 | 104 | App.Current.Styles.Add(fluentStyleInclude); 105 | 106 | StyleInclude localStyleInclude = new(baseUri: new Uri("avares://SysMonAvalonia/Assets/Styles/")); 107 | localStyleInclude.Source = new Uri(localStyle, UriKind.Relative); 108 | 109 | App.Current.Styles.Add(localStyleInclude); 110 | } 111 | 112 | public static void ShowWidgets(IClassicDesktopStyleApplicationLifetime desktop) 113 | { 114 | desktop.Exit += (sender, args) => SettingModel.Save(); 115 | 116 | List widgetList = new(); 117 | 118 | if (SettingData.CurrentSetting.DeviceIoWidget.IsStartup) 119 | { 120 | DeviceIoWidgetView deviceIoWidget = new(); 121 | deviceIoWidget.WindowStartupLocation = WindowStartupLocation.Manual; 122 | deviceIoWidget.Position = new(SettingData.CurrentSetting.DeviceIoWidget.X, 123 | SettingData.CurrentSetting.DeviceIoWidget.Y); 124 | 125 | widgetList.Add(deviceIoWidget); 126 | } 127 | 128 | if (SettingData.CurrentSetting.WeatherWidget.IsStartup) 129 | { 130 | WeatherWidgetView weatherWidget = new(); 131 | weatherWidget.WindowStartupLocation = WindowStartupLocation.Manual; 132 | weatherWidget.Position = new(SettingData.CurrentSetting.WeatherWidget.X, 133 | SettingData.CurrentSetting.WeatherWidget.Y); 134 | 135 | widgetList.Add(weatherWidget); 136 | } 137 | 138 | if (SettingData.CurrentSetting.ComboWidget.IsStartup) 139 | { 140 | ComboWidgetView comboWidget = new(); 141 | comboWidget.WindowStartupLocation = WindowStartupLocation.Manual; 142 | comboWidget.Position = new(SettingData.CurrentSetting.ComboWidget.X, 143 | SettingData.CurrentSetting.ComboWidget.Y); 144 | 145 | widgetList.Add(comboWidget); 146 | } 147 | 148 | foreach (Window widget in widgetList) 149 | { 150 | if (desktop.MainWindow == null) 151 | { 152 | desktop.MainWindow = widget; 153 | continue; 154 | } 155 | 156 | widget.Show(); 157 | } 158 | 159 | if (desktop.MainWindow == null) 160 | { 161 | desktop.MainWindow = new DeviceIoWidgetView(); 162 | SettingData.CurrentSetting.DeviceIoWidget.IsStartup = true; 163 | } 164 | } 165 | } 166 | } -------------------------------------------------------------------------------- /SysMonAvalonia/SysMonAvalonia.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | WinExe 4 | net6.0 5 | enable 6 | app.manifest 7 | true 8 | true 9 | Assets\icon.ico 10 | SysMonAvalonia 11 | SysMonAvalonia 12 | true 13 | 14 | 15 | AnyCPU 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Always 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | MSBuild:Compile 49 | 50 | 51 | MSBuild:Compile 52 | 53 | 54 | 55 | 56 | WeatherWidgetView.axaml 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /SysMonAvalonia/SysMonAvalonia.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | <_LastSelectedProfileId>D:\GitHub\SysMonAvalonia\SysMonAvalonia\Properties\PublishProfiles\FolderProfile.pubxml 5 | false 6 | 7 | 8 | 9 | Designer 10 | 11 | 12 | -------------------------------------------------------------------------------- /SysMonAvalonia/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Controls.Templates; 3 | using SysMonAvalonia.ViewModels; 4 | using System; 5 | 6 | namespace SysMonAvalonia 7 | { 8 | public class ViewLocator : IDataTemplate 9 | { 10 | public bool SupportsRecycling => false; 11 | 12 | public IControl Build(object data) 13 | { 14 | var name = data.GetType().FullName!.Replace("ViewModel", "View"); 15 | var type = Type.GetType(name); 16 | 17 | if (type != null) 18 | { 19 | return (Control)Activator.CreateInstance(type)!; 20 | } 21 | else 22 | { 23 | return new TextBlock { Text = "Not Found: " + name }; 24 | } 25 | } 26 | 27 | public bool Match(object data) 28 | { 29 | return data is ViewModelBase; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SysMonAvalonia/ViewModels/ComboWidgetViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive; 3 | using System.Reactive.Linq; 4 | using Avalonia.Controls; 5 | using LiveChartsCore.SkiaSharpView.Painting; 6 | using ReactiveUI; 7 | using SysMonAvalonia.Models; 8 | using SysMonAvalonia.Data; 9 | using SysMonAvalonia.Services; 10 | using NLog; 11 | 12 | namespace SysMonAvalonia.ViewModels 13 | { 14 | public class ComboWidgetViewModel 15 | { 16 | private ComboModel _comboModel; 17 | private ComboData _comboData; 18 | private IDisposable _timer; 19 | 20 | public ComboData ComboData 21 | { 22 | get => _comboData; 23 | } 24 | public ChartModel CpuChartModel { get; } 25 | public ChartModel RamChartModel { get; } 26 | public ChartModel GpuChartModel { get; } 27 | public ChartModel NetDownChartModel { get; } 28 | public ChartModel NetUpChartModel { get; } 29 | 30 | public ReactiveCommand ShowSettingsCommand { get; } = 31 | ReactiveCommand.Create(() => AppService.ShowSettings()); 32 | 33 | public ReactiveCommand ShutdownCommand { get; } = ReactiveCommand.Create(() => AppService.ShutdownApp() ); 34 | 35 | public ReactiveCommand ClosingCommand { get; } 36 | 37 | public ReactiveCommand MoveWidgetCommand { get; } = ReactiveCommand.Create(e => 38 | { 39 | if (e != null) 40 | { 41 | SettingData.CurrentSetting.ComboWidget.X = e.Point.X; 42 | SettingData.CurrentSetting.ComboWidget.Y = e.Point.Y; 43 | } 44 | }); 45 | 46 | public ComboWidgetViewModel() 47 | { 48 | _comboModel = new(); 49 | _comboData = _comboModel.ComboData; 50 | _comboModel.ComputerDataUpdate(); 51 | 52 | CpuChartModel = new(); 53 | CpuChartModel.Fill = App.Current.FindResource("CpuChartFill") as SolidColorPaint; 54 | 55 | RamChartModel = new(); 56 | RamChartModel.Fill = App.Current.FindResource("RamChartFill") as SolidColorPaint; 57 | RamChartModel.ClearPoints(); 58 | RamChartModel.FillPoints(_comboData.RamPercent); 59 | 60 | GpuChartModel = new(); 61 | GpuChartModel.Fill = App.Current.FindResource("GpuChartFill") as SolidColorPaint; 62 | 63 | NetDownChartModel = new(); 64 | NetDownChartModel.Fill = App.Current.FindResource("NetDownChartFill") as SolidColorPaint; 65 | 66 | NetUpChartModel = new(); 67 | NetUpChartModel.Fill = App.Current.FindResource("NetUpChartFill") as SolidColorPaint; 68 | 69 | _comboData.WhenAnyValue(x => x.CpuUsedPercent).Subscribe(percent => CpuChartModel.Value = percent); 70 | _comboData.WhenAnyValue(x => x.RamPercent).Subscribe(percent => RamChartModel.Value = percent); 71 | _comboData.WhenAnyValue(x => x.GpuUsedPercent).Subscribe(percent => GpuChartModel.Value = percent); 72 | _comboData.WhenAnyValue(x => x.GetByteNet).Subscribe(getByte => NetDownChartModel.Value = getByte); 73 | _comboData.WhenAnyValue(x => x.SentByteNet).Subscribe(sentByte => NetUpChartModel.Value = sentByte); 74 | 75 | _timer = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1)) 76 | .Subscribe(x => _comboModel.ComputerDataUpdate()); 77 | 78 | ClosingCommand = ReactiveCommand.Create(e => 79 | { 80 | _timer.Dispose(); 81 | _comboModel.Dispose(); 82 | }); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /SysMonAvalonia/ViewModels/DeviceIoWidgetViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Reactive; 4 | using System.Reactive.Linq; 5 | using Avalonia.Controls; 6 | using LiveChartsCore; 7 | using LiveChartsCore.SkiaSharpView; 8 | using ReactiveUI; 9 | using SysMonAvalonia.Models; 10 | using SysMonAvalonia.Data; 11 | using SysMonAvalonia.Services; 12 | 13 | namespace SysMonAvalonia.ViewModels 14 | { 15 | public class DeviceIoWidgetViewModel : ViewModelBase 16 | { 17 | private readonly DeviceIoModel _deviceIoModel; 18 | private readonly ChartModel _chartModel; 19 | private IDisposable _timer; 20 | 21 | private byte _updCountCollection; 22 | private byte _updCountSpace; 23 | private byte _updCountInfo; 24 | 25 | public ReactiveCommand ShutdownCommand { get; } = ReactiveCommand.Create(() => AppService.ShutdownApp()); 26 | 27 | public ReactiveCommand ShowSettingsCommand { get; } = 28 | ReactiveCommand.Create(() => AppService.ShowSettings()); 29 | 30 | public ReactiveCommand ClosingCommand { get; } 31 | public ReactiveCommand MoveWidgetCommand { get; } 32 | 33 | public ReadOnlyObservableCollection DeviceCollection => _deviceIoModel.DeviceCollection; 34 | 35 | public ISeries[] Series 36 | { 37 | get => _chartModel.Series; 38 | } 39 | public Axis[] XAxis 40 | { 41 | get => _chartModel.XAxis; 42 | } 43 | public Axis[] YAxis 44 | { 45 | get => _chartModel.YAxis; 46 | } 47 | 48 | public double ChartValue 49 | { 50 | set => _chartModel.Value = value; 51 | } 52 | 53 | public DeviceIoWidgetViewModel() 54 | { 55 | _updCountCollection = 0; 56 | _updCountInfo = 0; 57 | _updCountSpace = 0; 58 | 59 | _deviceIoModel = new(); 60 | _chartModel = new(); 61 | 62 | MoveWidgetCommand = ReactiveCommand.Create(e => 63 | { 64 | if (e != null) 65 | { 66 | SettingData.CurrentSetting.DeviceIoWidget.X = e.Point.X; 67 | SettingData.CurrentSetting.DeviceIoWidget.Y = e.Point.Y; 68 | } 69 | }); 70 | 71 | ClosingCommand = ReactiveCommand.Create(e => 72 | { 73 | _timer?.Dispose(); 74 | _deviceIoModel.Dispose(); 75 | return Unit.Default; 76 | }); 77 | 78 | _timer = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1)).Subscribe(x => UpdateTimer()); 79 | } 80 | 81 | private void UpdateTimer() 82 | { 83 | if (_updCountCollection == 0) 84 | { 85 | _deviceIoModel.UpdateDeviceCollection(); 86 | 87 | _updCountCollection = 180; 88 | } 89 | 90 | _deviceIoModel.UpdatePerformance(); 91 | 92 | if (_updCountSpace == 0) 93 | { 94 | _deviceIoModel.UpdateDeviceSpace(); 95 | _updCountSpace = 60; 96 | } 97 | 98 | if (_updCountInfo == 0) 99 | { 100 | _deviceIoModel.UpdateDeviceInfo(); 101 | _updCountInfo = 120; 102 | } 103 | 104 | _updCountCollection--; 105 | _updCountSpace--; 106 | _updCountInfo--; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /SysMonAvalonia/ViewModels/SettingViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reactive; 4 | using ReactiveUI; 5 | using SysMonAvalonia.Data; 6 | using SysMonAvalonia.Models; 7 | using SysMonAvalonia.Localization; 8 | using Weather; 9 | using Hardware.Windows.Network; 10 | using SysMonAvalonia.Services; 11 | 12 | namespace SysMonAvalonia.ViewModels 13 | { 14 | public class SettingViewModel : ViewModelBase 15 | { 16 | private SettingModel _settingModel; 17 | private List _cityCollection; 18 | private string _textFind; 19 | private bool _isOpenPopup; 20 | private int _selectCity; 21 | private int _selectNetworkAdapter; 22 | 23 | public SettingData CurrentSettingData { get; } 24 | public string[] LanguageList { get; } 25 | public string[] ThemeList { get; } 26 | public string[] WeatherProviderList { get; } 27 | public string[] NetworkUnitList { get; } 28 | public List CityCollection 29 | { 30 | get => _cityCollection; 31 | set => this.RaiseAndSetIfChanged(ref _cityCollection, value); 32 | } 33 | public List NetworkAdapterCollection 34 | { 35 | get => _settingModel.NetworkAdapters; 36 | } 37 | public string TextFind 38 | { 39 | get => _textFind; 40 | set => this.RaiseAndSetIfChanged(ref _textFind, value); 41 | } 42 | public bool IsOpenPopup 43 | { 44 | get => _isOpenPopup; 45 | set => this.RaiseAndSetIfChanged(ref _isOpenPopup, value); 46 | } 47 | public int SelectCity 48 | { 49 | get => _selectCity; 50 | set => this.RaiseAndSetIfChanged(ref _selectCity, value); 51 | } 52 | public int SelectNetworkAdapter 53 | { 54 | get => _selectNetworkAdapter; 55 | set => this.RaiseAndSetIfChanged(ref _selectNetworkAdapter, value); 56 | } 57 | 58 | public bool IsAutoStart 59 | { 60 | get => _settingModel.AutostartEnable; 61 | set => _settingModel.AutostartEnable = value; 62 | } 63 | 64 | public ReactiveCommand CloseCommand { get; } = ReactiveCommand.Create(() => 65 | { 66 | SettingModel.Save(); 67 | AppService.CloseSettings(); 68 | }); 69 | 70 | public SettingViewModel() 71 | { 72 | _settingModel = new(); 73 | 74 | CurrentSettingData = SettingData.CurrentSetting; 75 | LanguageList = new[] { Language.Locale.English, Language.Locale.Russia }; 76 | ThemeList = new[] { Language.Locale.Dark, Language.Locale.Light }; 77 | WeatherProviderList = new[] { "AccuWeather", "Gismeteo", "OpenWeatherMap", "WorldWeatherOnline", "Weather.com" }; 78 | NetworkUnitList = new[] { Language.Locale.MbitSettings, Language.Locale.MbyteSettings }; 79 | IsOpenPopup = false; 80 | 81 | this.WhenAnyValue(x => x.TextFind).Subscribe(text => 82 | { 83 | if (text != null && text.Length > 3) CityCollection = SettingModel.FindCities(text); 84 | 85 | if (CityCollection == null || CityCollection.Count == 0) IsOpenPopup = false; 86 | else IsOpenPopup = true; 87 | }); 88 | 89 | this.WhenAnyValue(x => x.SelectCity).Subscribe(index => 90 | { 91 | if (CityCollection == null) return; 92 | 93 | SettingData.CurrentSetting.WeatherCity = CityCollection[index].City; 94 | SettingData.CurrentSetting.WeatherID = CityCollection[index].ID; 95 | 96 | IsOpenPopup = false; 97 | }); 98 | 99 | this.WhenAnyValue(x => x.SelectNetworkAdapter).Subscribe(index => 100 | { 101 | List adapterList = NetworkAdapterCollection; 102 | 103 | if (adapterList == null) return; 104 | 105 | SettingData.CurrentSetting.AdapterID = adapterList[index].ID; 106 | SettingData.CurrentSetting.AdapterName = adapterList[index].Name; 107 | }); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /SysMonAvalonia/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace SysMonAvalonia.ViewModels 7 | { 8 | public class ViewModelBase : ReactiveObject 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SysMonAvalonia/ViewModels/WeatherWidgetViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.ComponentModel; 4 | using System.Reactive; 5 | using System.Reactive.Linq; 6 | using System.Threading.Tasks; 7 | using Avalonia.Controls; 8 | using ReactiveUI; 9 | using SysMonAvalonia.Models; 10 | using SysMonAvalonia.Data; 11 | using SysMonAvalonia.Services; 12 | 13 | namespace SysMonAvalonia.ViewModels 14 | { 15 | public class WeatherWidgetViewModel : ViewModelBase 16 | { 17 | private readonly WeatherModel _weatherModel; 18 | 19 | public ReactiveCommand ShutdownCommand { get; } = ReactiveCommand.Create(() => AppService.ShutdownApp()); 20 | public ReactiveCommand ShowSettingsCommand { get; } = ReactiveCommand.Create(() => AppService.ShowSettings()); 21 | public ReactiveCommand UpdateCommand { get; } 22 | public ReactiveCommand MoveCommand { get; } 23 | public ReactiveCommand ClosingCommand { get; } 24 | 25 | public WeatherData? CurrentWeather => _weatherModel.CurrentWeather; 26 | public ReadOnlyObservableCollection ForecastHourlyCollection => _weatherModel.HourlyForecasts; 27 | public ReadOnlyObservableCollection ForecastDailyCollection => _weatherModel.DailyForecasts; 28 | 29 | private IDisposable _timer; 30 | 31 | public WeatherWidgetViewModel() 32 | { 33 | UpdateCommand = ReactiveCommand.Create(WeatherRefresh); 34 | MoveCommand = ReactiveCommand.Create(e => 35 | { 36 | if (e != null) 37 | { 38 | SettingData.CurrentSetting.WeatherWidget.X = e.Point.X; 39 | SettingData.CurrentSetting.WeatherWidget.Y = e.Point.Y; 40 | } 41 | }); 42 | ClosingCommand = ReactiveCommand.Create(e => 43 | { 44 | _timer?.Dispose(); 45 | return Unit.Default; 46 | }); 47 | 48 | _weatherModel = new(); 49 | 50 | _timer = Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(SettingData.CurrentSetting.WeatherInterval)) 51 | .Subscribe(x => _weatherModel.WeatherRefresh()); 52 | } 53 | 54 | private async void WeatherRefresh() 55 | { 56 | await Task.Run(() => _weatherModel.WeatherRefresh()); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SysMonAvalonia/Views/ComboWidgetView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using Avalonia.Markup.Xaml; 5 | 6 | namespace SysMonAvalonia.Views 7 | { 8 | public partial class ComboWidgetView : Window 9 | { 10 | public ComboWidgetView() 11 | { 12 | InitializeComponent(); 13 | #if DEBUG 14 | this.AttachDevTools(); 15 | #endif 16 | } 17 | 18 | private void InitializeComponent() 19 | { 20 | AvaloniaXamlLoader.Load(this); 21 | } 22 | 23 | private void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e) 24 | { 25 | if (e.GetCurrentPoint(null).Properties.IsLeftButtonPressed) this.BeginMoveDrag(e); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SysMonAvalonia/Views/DeviceIoWidgetView.axaml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 70 | 78 | 87 | 96 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /SysMonAvalonia/Views/DeviceIoWidgetView.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | using Avalonia.Controls; 4 | using Avalonia.Controls.ApplicationLifetimes; 5 | using Avalonia.Input; 6 | using Avalonia.Interactivity; 7 | using Avalonia.Markup.Xaml; 8 | 9 | namespace SysMonAvalonia.Views 10 | { 11 | public partial class DeviceIoWidgetView : Window 12 | { 13 | public DeviceIoWidgetView() 14 | { 15 | InitializeComponent(); 16 | #if DEBUG 17 | this.AttachDevTools(); 18 | #endif 19 | } 20 | 21 | private void InitializeComponent() 22 | { 23 | AvaloniaXamlLoader.Load(this); 24 | } 25 | 26 | private void Widget_OnPointerPressed(object? sender, PointerPressedEventArgs e) 27 | { 28 | if (e.GetCurrentPoint(null).Properties.IsLeftButtonPressed) 29 | this.BeginMoveDrag(e); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SysMonAvalonia/Views/SettingView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace SysMonAvalonia.Views 6 | { 7 | public partial class SettingView : Window 8 | { 9 | public SettingView() 10 | { 11 | InitializeComponent(); 12 | #if DEBUG 13 | this.AttachDevTools(); 14 | #endif 15 | } 16 | 17 | private void InitializeComponent() 18 | { 19 | AvaloniaXamlLoader.Load(this); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SysMonAvalonia/Views/WeatherWidgetView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using Avalonia.Markup.Xaml; 5 | 6 | namespace SysMonAvalonia.Views 7 | { 8 | public partial class WeatherWidgetView : Window 9 | { 10 | public WeatherWidgetView() 11 | { 12 | InitializeComponent(); 13 | #if DEBUG 14 | this.AttachDevTools(); 15 | #endif 16 | } 17 | 18 | private void InitializeComponent() 19 | { 20 | AvaloniaXamlLoader.Load(this); 21 | } 22 | 23 | private void Widget_OnPointerPressed(object? sender, PointerPressedEventArgs e) 24 | { 25 | if (e.GetCurrentPoint(null).Properties.IsLeftButtonPressed) 26 | this.BeginMoveDrag(e); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SysMonAvalonia/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 54 | 62 | 63 | 64 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /SysMonAvalonia/nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Weather/Helper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | using NLog; 6 | 7 | namespace Weather 8 | { 9 | static class Helper 10 | { 11 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 12 | 13 | public static async Task GetNetContent(string url) 14 | { 15 | string content = null; 16 | 17 | using (HttpClientHandler handler = new()) 18 | { 19 | if (handler.SupportsAutomaticDecompression) handler.AutomaticDecompression = DecompressionMethods.GZip | 20 | DecompressionMethods.Deflate; 21 | 22 | using (HttpClient client = new(handler)) 23 | { 24 | client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.102 Safari/537.36"); 25 | client.Timeout = TimeSpan.FromSeconds(6); 26 | client.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip"); 27 | 28 | try { content = await client.GetStringAsync(url); } 29 | catch (Exception ex) 30 | { Logger.Error(ex, $"HttpClient: {ex.Message}"); } 31 | } 32 | } 33 | 34 | return content; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Weather/LocationData.cs: -------------------------------------------------------------------------------- 1 | namespace Weather 2 | { 3 | public class LocationData 4 | { 5 | public string ID { get; set; } 6 | public string City { get; set; } 7 | public string Country { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Weather/NLog.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Weather/Providers/IProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | 4 | namespace Weather.Providers 5 | { 6 | public interface IProvider 7 | { 8 | public List GetLocation(string query, CultureInfo culture, string apiKey); 9 | public WeatherData GetCurrentWeatherData(string id, CultureInfo culture, string apiKey); 10 | } 11 | } -------------------------------------------------------------------------------- /Weather/Providers/Providers.cs: -------------------------------------------------------------------------------- 1 | namespace Weather.Providers 2 | { 3 | public enum Providers : int 4 | { 5 | None = -1, 6 | AccuWeather = 0, 7 | Gismeteo = 1, 8 | OpenWeatherMap = 2, 9 | WorldWeatherOnline = 3, 10 | Wunderground = 4 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Weather/Weather.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | PreserveNewest 14 | 15 | 16 | 17 | 18 | Always 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Weather/WeatherData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Weather 8 | { 9 | public class WeatherData 10 | { 11 | public sbyte Temperature { set; get; } 12 | public sbyte ApparentTemperature { set; get; } 13 | public sbyte HighTemperature { set; get; } 14 | public sbyte LowTemperature { set; get; } 15 | public short WindSpeed { set; get; } 16 | public double WindDirection { set; get; } 17 | public byte CloudCover { set; get; } 18 | public byte PrecipChange { set; get; } 19 | public WindUnitEnum WindUnit { set; get; } 20 | public byte Humidity { set; get; } 21 | public short Pressure { set; get; } 22 | public byte UVIndex { set; get; } 23 | public byte SkyCode { set; get; } 24 | public string Text { set; get; } 25 | public DateTime Date { set; get; } 26 | public DateTime Sunrise { set; get; } 27 | public DateTime Sunset { set; get; } 28 | public string City { get; set; } 29 | public List ForecastDaily { set; get; } 30 | public List ForecastHourly { set; get; } 31 | 32 | private readonly string _serializePath; 33 | 34 | public WeatherData() 35 | { 36 | #if DEBUG 37 | _serializePath = AppContext.BaseDirectory + @"\WeatherData.json"; 38 | #else 39 | _serializePath = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + @"\WeatherData.json"; 40 | #endif 41 | 42 | Temperature = 0; 43 | ApparentTemperature = 0; 44 | HighTemperature = 0; 45 | LowTemperature = 0; 46 | WindSpeed = 0; 47 | WindDirection = 0; 48 | CloudCover = 120; 49 | PrecipChange = 120; 50 | WindUnit = WindUnitEnum.Ms; 51 | Humidity = 0; 52 | Pressure = 0; 53 | UVIndex = 0; 54 | SkyCode = 0; 55 | Text = null; 56 | ForecastDaily = null; 57 | ForecastHourly = null; 58 | } 59 | 60 | public void Serialize() 61 | { 62 | dynamic jObject = new JObject(); 63 | jObject.Temperature = Temperature; 64 | jObject.ApparentTemperature = ApparentTemperature; 65 | jObject.HightTemperature = HighTemperature; 66 | jObject.LowTemperature = LowTemperature; 67 | jObject.WindSpeed = WindSpeed; 68 | jObject.CloudCover = CloudCover; 69 | jObject.PrecipChange = PrecipChange; 70 | jObject.WindUnit = WindUnit; 71 | jObject.WindDirection = WindDirection; 72 | jObject.Humidity = Humidity; 73 | jObject.Pressure = Pressure; 74 | jObject.UVIndex = UVIndex; 75 | jObject.SkyCode = SkyCode; 76 | jObject.Text = Text; 77 | jObject.Date = Date; 78 | jObject.Sunrise = Sunrise; 79 | jObject.Sunset = Sunset; 80 | jObject.City = City; 81 | jObject.ForecastHourly = JArray.FromObject(ForecastHourly); 82 | jObject.ForecastDaily = JArray.FromObject(ForecastDaily); 83 | 84 | try 85 | { 86 | string json = JsonConvert.SerializeObject(jObject); 87 | 88 | File.WriteAllText(_serializePath, json); 89 | } 90 | catch 91 | { 92 | 93 | } 94 | } 95 | 96 | public static WeatherData Deserialize() 97 | { 98 | dynamic jObject; 99 | 100 | try 101 | { 102 | jObject = JsonConvert.DeserializeObject(File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + @"\WeatherData.json")); 103 | } 104 | catch 105 | { 106 | return null; 107 | } 108 | 109 | WeatherData weatherData = new WeatherData(); 110 | 111 | try { weatherData.Temperature = jObject.Temperature.ToObject(); } catch { /* ignored */ } 112 | try { weatherData.ApparentTemperature = jObject.ApparentTemperature.ToObject(); } catch { /* ignored */ } 113 | try { weatherData.HighTemperature = jObject.HightTemperature.ToObject(); } catch { /* ignored */ } 114 | try { weatherData.LowTemperature = jObject.LowTemperature.ToObject(); } catch { /* ignored */ } 115 | try { weatherData.WindSpeed = jObject.WindSpeed.ToObject(); } catch { /* ignored */ } 116 | try { weatherData.WindUnit = jObject.WindUnit.ToObject(); } catch { /* ignored */ } 117 | try { weatherData.WindDirection = jObject.WindDirection.ToObject(); } catch { /* ignored */ } 118 | try { weatherData.CloudCover = jObject.CloudCover.ToObject(); } catch { /* ignored */ } 119 | try { weatherData.PrecipChange = jObject.PrecipChange.ToObject(); } catch { /* ignored */ } 120 | try { weatherData.Humidity = jObject.Humidity.ToObject(); } catch { /* ignored */ } 121 | try { weatherData.Pressure = jObject.Pressure.ToObject(); } catch { /* ignored */ } 122 | try { weatherData.UVIndex = jObject.UVIndex.ToObject(); } catch { /* ignored */ } 123 | try { weatherData.SkyCode = jObject.SkyCode.ToObject(); } catch { /* ignored */ } 124 | try { weatherData.Text = jObject.Text.ToObject(); } catch { /* ignored */ } 125 | try { weatherData.Date = jObject.Date.ToObject(); } catch { /* ignored */ } 126 | try { weatherData.Sunrise = jObject.Sunrise.ToObject(); } catch { /* ignored */ } 127 | try { weatherData.Sunset = jObject.Sunset.ToObject(); } catch { /* ignored */ } 128 | try { weatherData.City = jObject.City.ToObject(); } catch { /* ignored */ } 129 | try { weatherData.ForecastHourly = ((JArray)jObject.ForecastHourly).ToObject>(); } catch { /* ignored */ } 130 | try { weatherData.ForecastDaily = ((JArray)jObject.ForecastDaily).ToObject>(); } catch { /* ignored */ } 131 | 132 | return weatherData; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Weather/WindUnitEnum.cs: -------------------------------------------------------------------------------- 1 | namespace Weather 2 | { 3 | public enum WindUnitEnum : byte 4 | { 5 | Mh = 0, 6 | KmH = 1, 7 | Ms = 2 8 | } 9 | } --------------------------------------------------------------------------------