├── .gitattributes ├── .gitignore ├── README.md ├── Standard ├── Helpers │ ├── BitHelper.cs │ ├── ColorHelper.cs │ ├── EnumHelper.cs │ ├── FileHelper.cs │ └── ZipHelper.cs └── Standard.csproj ├── StandardUnitTest ├── BitHelperUnitTest.cs └── StandardUnitTest.csproj ├── Utils.Standard ├── Helpers │ ├── BitHelper.cs │ ├── EnumHelper.cs │ ├── FileHelper.cs │ └── ZipHelper.cs └── Utils.Standard.csproj ├── Utils.sln ├── Utils ├── App.config ├── Helpers │ ├── AppConfigHelper.cs │ ├── CheckNameHelper.cs │ ├── ExplorerSizeHelper.cs │ └── ImageHelper │ │ └── Gif │ │ └── GifHelper.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Utils.csproj └── WindowsApi │ ├── Lib │ └── Interop.RDPCOMAPILib.dll │ ├── ScreenSharing │ ├── AttendeeConnectInfoEventArgs.cs │ ├── AttendeeDisConnectEventArgs.cs │ ├── AttendeeInfo.cs │ └── ScreenSharing.cs │ ├── Theme │ └── Theme.cs │ ├── WLAN │ ├── IWlan.cs │ ├── WlanHelpers.cs │ ├── WlanInterface.cs │ ├── WlanManager.cs │ └── WlanNotificationStructs.cs │ ├── WMI │ ├── Drive │ │ └── Drive.cs │ ├── Monitor │ │ └── Monitor.cs │ └── USBDeviceWatcher │ │ ├── UsbDeviceInfo.cs │ │ └── UsbDeviceWatcher.cs │ └── Win32 │ ├── Advapi32 │ ├── Advapi32Base.cs │ └── Advapi32Extension.cs │ ├── Common │ ├── ExecuteResult.cs │ └── Win32ErrorCodes.cs │ ├── Kernel32 │ ├── Kernel32Base.cs │ └── Kernel32Extension.cs │ ├── Shell32 │ ├── Shell32Base.Struct.cs │ ├── Shell32Base.cs │ └── Shell32Extension.cs │ ├── User32 │ ├── User32Base.cs │ └── User32Extension.cs │ ├── Winmm │ ├── WinmmBase.cs │ └── WinmmExtension.cs │ └── Wlanapi │ ├── WlanapiBase.Enums.cs │ ├── WlanapiBase.Struct.cs │ └── WlanapiBase.cs └── UtilsDemo ├── App.config ├── Program.cs ├── Properties └── AssemblyInfo.cs └── UtilsDemo.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 基础功能实现 2 | 3 | Standard2.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
类名方法参数描述
BitHelperSetBit(byte[] data, int bitIndex, bool value)传入指定字节数组,Bit的指定位置和对应值
(byte data, int bitIndex, bool value)传入指定字节,Bit的指定位置和对应值
(bool)GetBit(byte[] data, int bitIndex)传入指定字节数组,Bit的指定位置和对应值,返回bool值,1:true;0:false
(byte data, int bitIndex)传入指定字节,Bit的指定位置和对应值,返回bool值,1:true;0:false
FileHelperCheckFileOrDirectoryNameValidity(string name)检测文件或者文件夹名称是否合法
-------------------------------------------------------------------------------- /Standard/Helpers/BitHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Standard.Helpers 9 | { 10 | public static class BitHelper 11 | { 12 | public static void SetBit(byte[] data, int bitIndex, bool value) 13 | { 14 | if (data == null || bitIndex < 0 || bitIndex >= data.Length * 8) 15 | { 16 | throw new ArgumentException("Invalid parameters."); 17 | } 18 | 19 | int byteIndex = bitIndex / 8; 20 | int bitPosition = bitIndex % 8; 21 | 22 | if (value) 23 | { 24 | // Set the bit at bitPosition in data[byteIndex] 25 | data[byteIndex] |= (byte)(1 << bitPosition); 26 | } 27 | else 28 | { 29 | // Clear the bit at bitPosition in data[byteIndex] 30 | data[byteIndex] &= (byte)~(1 << bitPosition); 31 | } 32 | } 33 | 34 | public static byte SetBit(byte data, int bitIndex, bool value) 35 | { 36 | if (bitIndex < 0 || bitIndex >= 8) 37 | { 38 | throw new ArgumentException("Invalid parameters."); 39 | } 40 | 41 | if (value) 42 | { 43 | // Set the bit at bitPosition in data[byteIndex] 44 | data |= (byte)(1 << bitIndex); 45 | } 46 | else 47 | { 48 | // Clear the bit at bitPosition in data[byteIndex] 49 | data &= (byte)~(1 << bitIndex); 50 | } 51 | 52 | return data; 53 | } 54 | 55 | public static bool GetBit(byte[] data, int bitIndex) 56 | { 57 | if (data == null || bitIndex < 0 || bitIndex >= data.Length * 8) 58 | { 59 | throw new ArgumentException("Invalid parameters."); 60 | } 61 | 62 | int byteIndex = bitIndex / 8; 63 | int bitPosition = bitIndex % 8; 64 | 65 | return GetBit(data[byteIndex], bitPosition); 66 | } 67 | 68 | public static bool GetBit(byte data, int bitIndex) 69 | { 70 | if (bitIndex < 0 || bitIndex >= 8) 71 | { 72 | throw new ArgumentException("Invalid parameters."); 73 | } 74 | 75 | bool bit = (data & (1 << bitIndex)) != 0; 76 | return bit; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Standard/Helpers/ColorHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Text; 5 | 6 | namespace Standard.Helpers 7 | { 8 | public static class ColorHelper 9 | { 10 | /// 11 | /// 生成指定数量的高区分度颜色 12 | /// 13 | /// 调整 count 参数即可适应不同需求 14 | /// seed 参数控制随机性,方便调试和一致性需求 15 | /// 16 | public static List GenerateDistinctColors(int count, int seed = 0) 17 | { 18 | Random random = seed == 0 ? new Random() : new Random(seed); 19 | List colors = new List(); 20 | 21 | for (int i = 0; i < count; i++) 22 | { 23 | // 计算色相(均匀分布) 24 | double hue = (i * (360.0 / count)) % 360; 25 | 26 | // 高饱和度(80%~100%) 27 | double saturation = random.Next(80, 101); 28 | 29 | // 低亮度(20%~40%):颜色更暗但保留鲜艳度 30 | double lightness = random.Next(40, 41); 31 | 32 | // 转换为RGB颜色 33 | Color color = HSLToRGB(hue, saturation, lightness); 34 | colors.Add(color); 35 | } 36 | 37 | return colors; 38 | } 39 | 40 | /// 41 | /// HSL转RGB核心函数 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | private static Color HSLToRGB(double h, double s, double l) 48 | { 49 | h %= 360; 50 | s = Math.Min(100, Math.Max(0, s)); 51 | l = Math.Min(100, Math.Max(0, l)); 52 | 53 | double c = (1 - Math.Abs(2 * l / 100 - 1)) * (s / 100); 54 | double hPrime = h / 60; 55 | double x = c * (1 - Math.Abs(hPrime % 2 - 1)); 56 | double r1, g1, b1; 57 | 58 | if (0 <= hPrime && hPrime < 1) 59 | { 60 | r1 = c; g1 = x; b1 = 0; 61 | } 62 | else if (1 <= hPrime && hPrime < 2) 63 | { 64 | r1 = x; g1 = c; b1 = 0; 65 | } 66 | else if (2 <= hPrime && hPrime < 3) 67 | { 68 | r1 = 0; g1 = c; b1 = x; 69 | } 70 | else if (3 <= hPrime && hPrime < 4) 71 | { 72 | r1 = 0; g1 = x; b1 = c; 73 | } 74 | else if (4 <= hPrime && hPrime < 5) 75 | { 76 | r1 = x; g1 = 0; b1 = c; 77 | } 78 | else 79 | { 80 | r1 = c; g1 = 0; b1 = x; 81 | } 82 | 83 | double m = l / 100 - c / 2; 84 | byte r = (byte)Math.Round((r1 + m) * 255); 85 | byte g = (byte)Math.Round((g1 + m) * 255); 86 | byte b = (byte)Math.Round((b1 + m) * 255); 87 | 88 | return Color.FromArgb(255, r, g, b); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Standard/Helpers/EnumHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Text; 5 | 6 | namespace Standard.Helpers 7 | { 8 | public static class EnumHelper 9 | { 10 | public static ObservableCollection GetEnumList() where TEnum : Enum 11 | { 12 | var cols = new ObservableCollection(); 13 | var items = Enum.GetValues(typeof(TEnum)); 14 | foreach (var item in items) 15 | { 16 | cols.Add((TEnum)item); 17 | } 18 | return cols; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Standard/Helpers/FileHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Standard.Helpers 8 | { 9 | public static class FileHelper 10 | { 11 | public static bool CheckFileOrDirectoryNameValidity(string name) 12 | { 13 | string[] strList = new string[] { " ", "/", "\"", @"\", @"\/", ":", "*", "?", "<", ">", "|", "\r\n" }; 14 | 15 | return !string.IsNullOrEmpty(name) && !strList.Any(p => name.Contains(p)); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Standard/Helpers/ZipHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO.Compression; 4 | using System.Text; 5 | 6 | namespace Standard.Helpers 7 | { 8 | public static class ZipHelper 9 | { 10 | public static bool Create() 11 | { 12 | //ZipFile.CreateFromDirectory 13 | return true; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Standard/Standard.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /StandardUnitTest/BitHelperUnitTest.cs: -------------------------------------------------------------------------------- 1 | namespace StandardUnitTest 2 | { 3 | public class BitHelperUnitTest 4 | { 5 | [SetUp] 6 | public void Setup() 7 | { 8 | 9 | } 10 | 11 | [Test] 12 | public void SetBit() 13 | { 14 | byte[] data1 = [0x00,0x00]; 15 | Standard.Helpers.BitHelper.SetBit(data1, 8, true); 16 | Assert.That(data1[1], Is.EqualTo(0x01)); 17 | 18 | byte data2 = 0x00; 19 | data2 = Standard.Helpers.BitHelper.SetBit(data2, 0, true); 20 | Assert.That(data2, Is.EqualTo(0x01)); 21 | } 22 | 23 | [Test] 24 | public void GetBit() 25 | { 26 | byte[] data1 = [0x00, 0x00]; 27 | bool result = Standard.Helpers.BitHelper.GetBit(data1, 8); 28 | Assert.That(result, Is.EqualTo(false)); 29 | 30 | byte data2 = 0x00; 31 | result = Standard.Helpers.BitHelper.GetBit(data2, 0); 32 | Assert.That(result, Is.EqualTo(false)); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /StandardUnitTest/StandardUnitTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Utils.Standard/Helpers/BitHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Utils.Standard.Helpers 6 | { 7 | public static class BitHelper 8 | { 9 | public static void SetBit(byte[] data, int bitIndex, bool value) 10 | { 11 | if (data == null || bitIndex < 0 || bitIndex >= data.Length * 8) 12 | { 13 | throw new ArgumentException("Invalid parameters."); 14 | } 15 | 16 | int byteIndex = bitIndex / 8; 17 | int bitPosition = bitIndex % 8; 18 | 19 | if (value) 20 | { 21 | // Set the bit at bitPosition in data[byteIndex] 22 | data[byteIndex] |= (byte)(1 << bitPosition); 23 | } 24 | else 25 | { 26 | // Clear the bit at bitPosition in data[byteIndex] 27 | data[byteIndex] &= (byte)~(1 << bitPosition); 28 | } 29 | } 30 | 31 | public static byte SetBit(byte data, int bitIndex, bool value) 32 | { 33 | if (bitIndex < 0 || bitIndex >= 8) 34 | { 35 | throw new ArgumentException("Invalid parameters."); 36 | } 37 | 38 | if (value) 39 | { 40 | // Set the bit at bitPosition in data[byteIndex] 41 | data |= (byte)(1 << bitIndex); 42 | } 43 | else 44 | { 45 | // Clear the bit at bitPosition in data[byteIndex] 46 | data &= (byte)~(1 << bitIndex); 47 | } 48 | 49 | return data; 50 | } 51 | 52 | public static bool GetBit(byte[] data, int bitIndex) 53 | { 54 | if (data == null || bitIndex < 0 || bitIndex >= data.Length * 8) 55 | { 56 | throw new ArgumentException("Invalid parameters."); 57 | } 58 | 59 | int byteIndex = bitIndex / 8; 60 | int bitPosition = bitIndex % 8; 61 | 62 | return GetBit(data[byteIndex], bitPosition); 63 | } 64 | 65 | public static bool GetBit(byte data, int bitIndex) 66 | { 67 | if (bitIndex < 0 || bitIndex >= 8) 68 | { 69 | throw new ArgumentException("Invalid parameters."); 70 | } 71 | 72 | bool bit = (data & (1 << bitIndex)) != 0; 73 | return bit; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Utils.Standard/Helpers/EnumHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Text; 5 | 6 | namespace Utils.Standard.Helpers 7 | { 8 | public static class EnumHelper 9 | { 10 | public static ObservableCollection GetEnumList() where TEnum : Enum 11 | { 12 | var cols = new ObservableCollection(); 13 | var items = Enum.GetValues(typeof(TEnum)); 14 | foreach (var item in items) 15 | { 16 | cols.Add((TEnum)item); 17 | } 18 | return cols; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Utils.Standard/Helpers/FileHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.Standard.Helpers 8 | { 9 | public static class FileHelper 10 | { 11 | public static bool CheckFileOrDirectoryNameValidity(string name) 12 | { 13 | string[] strList = new string[] { " ", "/", "\"", @"\", @"\/", ":", "*", "?", "<", ">", "|", "\r\n" }; 14 | 15 | return !string.IsNullOrEmpty(name) && !strList.Any(p => name.Contains(p)); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Utils.Standard/Helpers/ZipHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO.Compression; 4 | using System.Text; 5 | 6 | namespace Utils.Standard.Helpers 7 | { 8 | public static class ZipHelper 9 | { 10 | public static bool Create() 11 | { 12 | //ZipFile.CreateFromDirectory 13 | return true; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Utils.Standard/Utils.Standard.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Utils.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34616.47 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Utils\Utils.csproj", "{52B9C6B5-DA34-4B13-A2BA-5A13F97D0386}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtilsDemo", "UtilsDemo\UtilsDemo.csproj", "{6A1B5E4B-0650-4E1F-AB48-2DEAFE40D6E8}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Standard", "Standard\Standard.csproj", "{372B45ED-4642-4EAC-80FC-B151A0B50732}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandardUnitTest", "StandardUnitTest\StandardUnitTest.csproj", "{30C53753-E025-485A-873C-640B1E44C792}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils.Standard", "Utils.Standard\Utils.Standard.csproj", "{209AF7BD-A1D8-4C47-BDA7-71BB285255FD}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {52B9C6B5-DA34-4B13-A2BA-5A13F97D0386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {52B9C6B5-DA34-4B13-A2BA-5A13F97D0386}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {52B9C6B5-DA34-4B13-A2BA-5A13F97D0386}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {52B9C6B5-DA34-4B13-A2BA-5A13F97D0386}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {6A1B5E4B-0650-4E1F-AB48-2DEAFE40D6E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {6A1B5E4B-0650-4E1F-AB48-2DEAFE40D6E8}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {6A1B5E4B-0650-4E1F-AB48-2DEAFE40D6E8}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {6A1B5E4B-0650-4E1F-AB48-2DEAFE40D6E8}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {372B45ED-4642-4EAC-80FC-B151A0B50732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {372B45ED-4642-4EAC-80FC-B151A0B50732}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {372B45ED-4642-4EAC-80FC-B151A0B50732}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {372B45ED-4642-4EAC-80FC-B151A0B50732}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {30C53753-E025-485A-873C-640B1E44C792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {30C53753-E025-485A-873C-640B1E44C792}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {30C53753-E025-485A-873C-640B1E44C792}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {30C53753-E025-485A-873C-640B1E44C792}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {209AF7BD-A1D8-4C47-BDA7-71BB285255FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {209AF7BD-A1D8-4C47-BDA7-71BB285255FD}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {209AF7BD-A1D8-4C47-BDA7-71BB285255FD}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {209AF7BD-A1D8-4C47-BDA7-71BB285255FD}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {7B9E596A-8B3F-4589-95C8-0FD2836BC353} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /Utils/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Utils/Helpers/AppConfigHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.Helpers 9 | { 10 | public class AppConfigHelper 11 | { 12 | static Configuration _config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 13 | 14 | public static string GetAppSettingsValue(string key) 15 | { 16 | return _config.AppSettings.Settings[key].Value; 17 | } 18 | 19 | public static void UpdateAppSettingsValue(string key, string value) 20 | { 21 | _config.AppSettings.Settings[key].Value = value; 22 | _config.Save(ConfigurationSaveMode.Modified); 23 | ConfigurationManager.RefreshSection("appSettings"); 24 | } 25 | 26 | public static void AddAppSettingsValue(string newKey, string newValue) 27 | { 28 | _config.AppSettings.Settings.Add(newKey, newValue); 29 | _config.Save(ConfigurationSaveMode.Modified); 30 | ConfigurationManager.RefreshSection("appSettings"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Utils/Helpers/CheckNameHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.Helpers 8 | { 9 | public static class CheckNameHelper 10 | { 11 | /// 12 | /// 文件或文件夹名称 13 | /// 14 | /// 15 | /// 16 | public static bool CheckFileOrDirectory(string name) 17 | { 18 | bool isValid = true; 19 | string[] strList = new string[] { " ", "/", "\"", @"\", @"\/", ":", "*", "?", "<", ">", "|", "\r\n" }; 20 | 21 | if (string.IsNullOrEmpty(name)) 22 | { 23 | isValid = false; 24 | } 25 | else 26 | { 27 | foreach (string errStr in strList) 28 | { 29 | if (name.Contains(errStr)) 30 | { 31 | isValid = false; 32 | break; 33 | } 34 | } 35 | } 36 | 37 | return isValid; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Utils/Helpers/ExplorerSizeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.Helpers 9 | { 10 | public class ExplorerSizeHelper 11 | { 12 | /// 13 | /// 获取文件大小 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static bool GetFileSize(string filePath, out long fileLength) 19 | { 20 | fileLength = -1; 21 | if (File.Exists(filePath)) 22 | { 23 | FileInfo fileInfo = new FileInfo(filePath); 24 | fileLength = fileInfo.Length; 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | /// 31 | /// 获取文件夹及子目录文件大小 32 | /// 33 | /// 34 | /// 35 | /// 36 | public static bool GetDirectorySize(string directoryPath, out long directoryLength) 37 | { 38 | directoryLength= -1; 39 | if (Directory.Exists(directoryPath)) 40 | { 41 | //一级目录 42 | DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath); 43 | foreach (var item in directoryInfo.GetFiles()) 44 | { 45 | directoryLength += item.Length; 46 | } 47 | //子目录 48 | foreach (var item in directoryInfo.GetDirectories()) 49 | { 50 | if (GetDirectorySize(item.FullName,out long dirLength)) 51 | { 52 | directoryLength += dirLength; 53 | } 54 | } 55 | 56 | return true; 57 | } 58 | return false; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Utils/Helpers/ImageHelper/Gif/GifHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Media.Animation; 9 | using System.Windows.Media.Imaging; 10 | 11 | namespace Utils.Helpers 12 | { 13 | public static class GifHelper 14 | { 15 | /// 16 | /// 用Image播放GIF 17 | /// 18 | /// GIF图片URI 19 | /// GIF图片播放一次的秒数 20 | /// 承载GIF的Image控件 21 | /// 错误信息 22 | /// 23 | public static bool GifToImageByAnimate(Uri gif, int gifPlaySeconds,Image imageControl,out string errorMsg) 24 | { 25 | errorMsg = string.Empty; 26 | //确实是GIF 27 | if (!gif.IsFile || !gif.AbsolutePath.EndsWith(".gif")) 28 | { 29 | errorMsg = "Is not gif file!"; 30 | return false; 31 | } 32 | try 33 | { 34 | List frameList = new List(); 35 | //将gif解码 36 | GifBitmapDecoder decoder = new GifBitmapDecoder(gif 37 | ,BitmapCreateOptions.PreservePixelFormat 38 | ,BitmapCacheOption.Default); 39 | if (!Equals(decoder, null) && decoder.Frames != null) 40 | { 41 | //将每一帧添加到列表 42 | frameList.AddRange(decoder.Frames); 43 | ObjectAnimationUsingKeyFrames objKeyAnimate = new ObjectAnimationUsingKeyFrames 44 | { 45 | Duration = new Duration(TimeSpan.FromSeconds(gifPlaySeconds)) 46 | }; 47 | foreach (var item in frameList) 48 | { 49 | DiscreteObjectKeyFrame k1_img1 = new DiscreteObjectKeyFrame(item); 50 | objKeyAnimate.KeyFrames.Add(k1_img1); 51 | } 52 | //添加第一帧为图片的开始画面 53 | imageControl.Source = frameList[0]; 54 | //循环动画 55 | Storyboard board = new Storyboard 56 | { 57 | RepeatBehavior = RepeatBehavior.Forever, 58 | FillBehavior = FillBehavior.HoldEnd 59 | }; 60 | board.Children.Add(objKeyAnimate); 61 | //将动画设置给ImageControl 62 | Storyboard.SetTarget(objKeyAnimate, imageControl); 63 | Storyboard.SetTargetProperty(objKeyAnimate, new PropertyPath(nameof(Image.Source))); 64 | //开始动画 65 | board.Begin(); 66 | return true; 67 | } 68 | return false; 69 | } 70 | catch (Exception ex) 71 | { 72 | errorMsg = ex.Message; 73 | return false; 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Utils/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | namespace Utils 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Utils/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Utils")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Utils")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("52b9c6b5-da34-4b13-a2ba-5a13f97d0386")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Utils/Utils.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {52B9C6B5-DA34-4B13-A2BA-5A13F97D0386} 8 | Library 9 | Utils 10 | Utils 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | False 42 | True 43 | WindowsApi\Lib\Interop.RDPCOMAPILib.dll 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | PreserveNewest 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Lib/Interop.RDPCOMAPILib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LcFireRabbit/Utils/249e975d54751d46d826506b8ba3194a4cdc00a7/Utils/WindowsApi/Lib/Interop.RDPCOMAPILib.dll -------------------------------------------------------------------------------- /Utils/WindowsApi/ScreenSharing/AttendeeConnectInfoEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public class AttendeeConnectInfoEventArgs : AttendeeInfo 10 | { 11 | public AttendeeConnectInfoEventArgs(string name, string ip, int id, bool isContol) 12 | { 13 | RemoteName = name; 14 | PeerIP = ip; 15 | ID = id; 16 | IsControl = isContol; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Utils/WindowsApi/ScreenSharing/AttendeeDisConnectEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public class AttendeeDisConnectEventArgs 10 | { 11 | public int ID { get; set; } 12 | 13 | public AttendeeDisConnectEventArgs(int id) 14 | { 15 | ID = id; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Utils/WindowsApi/ScreenSharing/AttendeeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public class AttendeeInfo 10 | { 11 | public string RemoteName { get; set; } 12 | public string PeerIP { get; set; } 13 | public int ID { get; set; } 14 | public bool IsControl { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Utils/WindowsApi/ScreenSharing/ScreenSharing.cs: -------------------------------------------------------------------------------- 1 | using RDPCOMAPILib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Utils.WindowsApi 11 | { 12 | public class ScreenSharing 13 | { 14 | #region 属性 15 | /// 16 | /// ScreenSharingService 17 | /// 18 | public static ScreenSharing Instance = new Lazy(() => new ScreenSharing()).Value; 19 | 20 | /// 21 | /// 连接字符串 22 | /// 23 | public string ConnectString { get; private set; } 24 | 25 | /// 26 | /// 是否正在分享 27 | /// 28 | private bool _isOpen; 29 | public bool IsOpen 30 | { 31 | get => _isOpen; 32 | set 33 | { 34 | if (value != _isOpen) 35 | { 36 | _isOpen = value; 37 | if (_isOpen) 38 | { 39 | OnRdpShareOpen?.Invoke(nameof(ScreenSharing), null); 40 | } 41 | else 42 | { 43 | OnRdpShareClose?.Invoke(nameof(ScreenSharing), null); 44 | } 45 | } 46 | } 47 | } 48 | 49 | /// 50 | /// 是否暂停 51 | /// 52 | public bool IsPause { get; private set; } 53 | 54 | /// 55 | /// 是否加密 56 | /// 57 | public bool IsEncrypt { get; private set; } 58 | 59 | /// 60 | /// 错误信息 61 | /// 62 | public RDPErrorType ErrorMessage { get; private set; } 63 | 64 | /// 65 | /// 远程桌面错误类型 66 | /// 67 | public enum RDPErrorType 68 | { 69 | NoNetworkReady = 1, 70 | UnKnow = 0 71 | } 72 | #endregion 73 | 74 | #region 事件 75 | public event EventHandler OnAttendeeConnected; 76 | public event EventHandler OnAttendeeDisconnected; 77 | public event EventHandler OnGraphicsStreamPaused; 78 | public event EventHandler OnGraphicsStreamResumed; 79 | public event EventHandler OnRdpShareOpen; 80 | public event EventHandler OnRdpShareClose; 81 | #endregion 82 | 83 | #region 字段 84 | private string _authID = "Coder"; 85 | 86 | private string _groupName = "ScreenSharing"; 87 | 88 | private RDPSession m_pRdpSession = null; 89 | 90 | private CTRL_LEVEL _attendeeControlLevel; 91 | 92 | private List _attendees; 93 | 94 | private IRDPSRAPIInvitation _rDPSRAPIInvitation; 95 | 96 | protected object _lock = new object(); 97 | #endregion 98 | 99 | #region 构造 100 | private ScreenSharing() 101 | { 102 | _attendees = new List(); 103 | } 104 | #endregion 105 | 106 | #region 事件注册方法 107 | /// 108 | /// 错误 109 | /// 110 | /// 111 | private void OnError(object ErrorInfo) 112 | { 113 | ///待议 114 | } 115 | 116 | /// 117 | /// 远程桌面恢复 118 | /// 119 | private void GraphicsStreamResumed() 120 | { 121 | IsPause = false; 122 | OnGraphicsStreamResumed?.Invoke(this, null); 123 | } 124 | 125 | /// 126 | /// 远程桌面暂停 127 | /// 128 | private void GraphicsStreamPaused() 129 | { 130 | IsPause = true; 131 | OnGraphicsStreamPaused?.Invoke(this, null); 132 | } 133 | 134 | /// 135 | /// 连接着申请权限 136 | /// 137 | /// 138 | /// 139 | private void OnControlLevelChangeRequest(object pAttendee, CTRL_LEVEL RequestedLevel) 140 | { 141 | ///待议 -纠结点(1.完全由主机赋予 2.与会者可以申请) 142 | ///判断设置的与会者权限赋值方式 143 | } 144 | 145 | /// 146 | /// 连接者连入 147 | /// 148 | /// 149 | private void AttendeeConnected(object pAttendee) 150 | { 151 | IRDPSRAPIAttendee rDPSRAPIAttendee = pAttendee as IRDPSRAPIAttendee; 152 | 153 | rDPSRAPIAttendee.ControlLevel = _attendeeControlLevel; 154 | 155 | _attendees.Add(rDPSRAPIAttendee); 156 | 157 | OnAttendeeConnected?.Invoke(this, new AttendeeConnectInfoEventArgs(rDPSRAPIAttendee.RemoteName, rDPSRAPIAttendee.ConnectivityInfo.PeerIP, rDPSRAPIAttendee.Id, rDPSRAPIAttendee.ControlLevel == CTRL_LEVEL.CTRL_LEVEL_INTERACTIVE)); 158 | } 159 | 160 | /// 161 | /// 连接者断开 162 | /// 163 | /// 164 | private void AttendeeDisconnected(object pDisconnectInfo) 165 | { 166 | IRDPSRAPIAttendeeDisconnectInfo pDiscInfo = pDisconnectInfo as IRDPSRAPIAttendeeDisconnectInfo; 167 | 168 | RemoveAndDisposeAttendee(pDiscInfo.Attendee); 169 | 170 | while (Marshal.ReleaseComObject(pDiscInfo) > 0) ; 171 | } 172 | #endregion 173 | 174 | #region 私有方法 175 | /// 176 | /// 注册所需要的事件 177 | /// 178 | private void RegistEvent() 179 | { 180 | m_pRdpSession = new RDPSession(); 181 | 182 | m_pRdpSession.OnAttendeeConnected += new _IRDPSessionEvents_OnAttendeeConnectedEventHandler(AttendeeConnected); 183 | 184 | m_pRdpSession.OnAttendeeDisconnected += new _IRDPSessionEvents_OnAttendeeDisconnectedEventHandler(AttendeeDisconnected); 185 | 186 | m_pRdpSession.OnControlLevelChangeRequest += new _IRDPSessionEvents_OnControlLevelChangeRequestEventHandler(OnControlLevelChangeRequest); 187 | 188 | m_pRdpSession.OnGraphicsStreamPaused += new _IRDPSessionEvents_OnGraphicsStreamPausedEventHandler(GraphicsStreamPaused); 189 | 190 | m_pRdpSession.OnGraphicsStreamResumed += new _IRDPSessionEvents_OnGraphicsStreamResumedEventHandler(GraphicsStreamResumed); 191 | 192 | m_pRdpSession.OnError += new _IRDPSessionEvents_OnErrorEventHandler(OnError); 193 | 194 | try 195 | { 196 | m_pRdpSession.Open(); 197 | } 198 | catch (Exception ex) 199 | { 200 | Close(); 201 | ErrorMessage = RDPErrorType.NoNetworkReady; 202 | } 203 | } 204 | 205 | /// 206 | /// 判读对象是否为空,为空抛出异常 207 | /// 208 | /// 检查对象 209 | /// 异常信息 210 | private void ObjIsNull(object parameter, string errorMsg) 211 | { 212 | if (object.Equals(parameter, null)) 213 | { 214 | throw new Exception(errorMsg); 215 | } 216 | } 217 | 218 | /// 219 | /// 为私有列表消除对象并释放对象 220 | /// 221 | /// 222 | private void RemoveAndDisposeAttendee(IRDPSRAPIAttendee attendee) 223 | { 224 | for (int i = 0; i < _attendees.Count; i++) 225 | { 226 | if (_attendees[i].Id == attendee.Id) 227 | { 228 | OnAttendeeDisconnected?.Invoke(this, new AttendeeDisConnectEventArgs(attendee.Id)); 229 | 230 | int id = _attendees[i].Id; 231 | 232 | IRDPSRAPIAttendee rDPSRAPI = _attendees[i]; 233 | 234 | while (Marshal.FinalReleaseComObject(rDPSRAPI) > 0) ; 235 | 236 | _attendees.RemoveAt(i); 237 | } 238 | } 239 | } 240 | 241 | /// 242 | /// 得到对应的私有对象 243 | /// 244 | /// 245 | /// 246 | private IRDPSRAPIAttendee GetRealAttendee(int id) 247 | { 248 | for (int i = 0; i < _attendees.Count; i++) 249 | { 250 | if (_attendees[i].Id == id) 251 | { 252 | return _attendees[i]; 253 | } 254 | } 255 | return null; 256 | } 257 | 258 | /// 259 | /// 将连接字符串以xml形式保存 260 | /// 261 | /// 262 | private void WriteToFile(string InviteString) 263 | { 264 | string exePath = Environment.CurrentDirectory; 265 | using (StreamWriter sw = File.CreateText(exePath + "\\inv.xml")) 266 | { 267 | sw.WriteLine(InviteString); 268 | } 269 | } 270 | 271 | /// 272 | /// 删除链接字符串文件 273 | /// 274 | private void DeleteConnectFile() 275 | { 276 | string exePath = Environment.CurrentDirectory; 277 | if (File.Exists(exePath + "\\inv.xml")) 278 | { 279 | File.Delete(exePath + "\\inv.xml"); 280 | } 281 | } 282 | 283 | /// 284 | /// 是否是Windows7 285 | /// 286 | /// 287 | private bool IsWindows7() 288 | { 289 | Version currentVersion = Environment.OSVersion.Version; 290 | 291 | if (currentVersion >= new Version(6, 1) && currentVersion < new Version(6, 2)) 292 | { 293 | return true; 294 | } 295 | 296 | return false; 297 | } 298 | #endregion 299 | 300 | #region 公有方法 301 | /// 302 | /// 创建会话 303 | /// 304 | /// 会话连接密码 305 | /// 会话最多加入人数 306 | /// 会话连接字符串 307 | public void CreateInvitation(string password, int attendeeLimit, bool isControl) 308 | { 309 | lock (_lock) 310 | { 311 | ///判空 312 | if (!object.Equals(m_pRdpSession, null)) 313 | return; 314 | 315 | RegistEvent(); 316 | 317 | if (m_pRdpSession != null) 318 | { 319 | if (isControl) 320 | { 321 | _attendeeControlLevel = CTRL_LEVEL.CTRL_LEVEL_INTERACTIVE; 322 | } 323 | else 324 | { 325 | _attendeeControlLevel = CTRL_LEVEL.CTRL_LEVEL_VIEW; 326 | } 327 | 328 | _rDPSRAPIInvitation = m_pRdpSession.Invitations.CreateInvitation(_authID, _groupName, password, attendeeLimit); 329 | 330 | ConnectString = _rDPSRAPIInvitation.ConnectionString; 331 | 332 | //WriteToFile(LinkString); 333 | 334 | IsPause = false; 335 | 336 | IsEncrypt = password != string.Empty; 337 | 338 | IsOpen = true; 339 | } 340 | } 341 | } 342 | 343 | /// 344 | /// 暂停会话 345 | /// 346 | public void Pause() 347 | { 348 | if (object.Equals(m_pRdpSession, null)) 349 | return; 350 | 351 | m_pRdpSession.Pause(); 352 | } 353 | 354 | /// 355 | /// 恢复会话 356 | /// 357 | public void Resume() 358 | { 359 | if (object.Equals(m_pRdpSession, null)) 360 | return; 361 | 362 | m_pRdpSession.Resume(); 363 | } 364 | 365 | /// 366 | /// 关闭会话(PC) 367 | /// 368 | public void Close() 369 | { 370 | lock (_lock) 371 | { 372 | if (object.Equals(m_pRdpSession, null)) 373 | return; 374 | 375 | foreach (var p in _attendees) 376 | { 377 | p.TerminateConnection(); 378 | } 379 | 380 | if (_attendees.Count > 0) 381 | { 382 | foreach (var p in _attendees) 383 | { 384 | while (Marshal.FinalReleaseComObject(p) > 0) ; 385 | } 386 | } 387 | 388 | _attendees.Clear(); 389 | 390 | m_pRdpSession.Close(); 391 | 392 | if (IsWindows7()) 393 | { 394 | while (Marshal.FinalReleaseComObject(_rDPSRAPIInvitation) > 0) ; 395 | 396 | while (Marshal.FinalReleaseComObject(m_pRdpSession) > 0) ; 397 | } 398 | 399 | m_pRdpSession = null; 400 | 401 | GC.Collect(); 402 | 403 | //DeleteConnectFile(); 404 | 405 | IsOpen = false; 406 | } 407 | } 408 | 409 | /// 410 | /// 获取连接者列表 411 | /// 412 | /// 413 | public List GetAttendeeInfos() 414 | { 415 | List attendeeInfos = new List(); 416 | 417 | for (int i = 0; i < _attendees.Count; i++) 418 | { 419 | attendeeInfos.Add(new AttendeeInfo() 420 | { 421 | ID = _attendees[i].Id, 422 | RemoteName = _attendees[i].RemoteName, 423 | PeerIP = _attendees[i].ConnectivityInfo.PeerIP, 424 | IsControl = _attendees[i].ControlLevel == CTRL_LEVEL.CTRL_LEVEL_INTERACTIVE 425 | }); 426 | } 427 | 428 | return attendeeInfos; 429 | } 430 | 431 | /// 432 | /// 单独修改某个连接的控制权限 433 | /// 434 | /// 与会者对象 435 | /// 想要赋予的权限 436 | public void SetInterActiveControlLevel(int id) 437 | { 438 | ///判空 439 | if (object.Equals(m_pRdpSession, null)) 440 | return; 441 | 442 | IRDPSRAPIAttendee realAttendee = GetRealAttendee(id); 443 | 444 | if (object.Equals(realAttendee, null)) 445 | return; 446 | 447 | realAttendee.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_INTERACTIVE; 448 | } 449 | 450 | public void SetViewControlLevel(int id) 451 | { 452 | ///判空 453 | if (object.Equals(m_pRdpSession, null)) 454 | return; 455 | 456 | IRDPSRAPIAttendee realAttendee = GetRealAttendee(id); 457 | 458 | if (object.Equals(realAttendee, null)) 459 | return; 460 | 461 | realAttendee.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_VIEW; 462 | } 463 | 464 | /// 465 | /// 关闭某个指定的与会者连接 466 | /// 467 | /// 468 | public void CloseAttendeeConnect(int id) 469 | { 470 | ///判空 471 | if (object.Equals(m_pRdpSession, null)) 472 | return; 473 | 474 | IRDPSRAPIAttendee realAttendee = GetRealAttendee(id); 475 | 476 | if (object.Equals(realAttendee, null)) 477 | return; 478 | 479 | realAttendee.TerminateConnection(); 480 | } 481 | #endregion 482 | } 483 | } 484 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Theme/Theme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public class Theme 10 | { 11 | /// 12 | /// 获取当前操作系统 是浅色还是暗色 13 | /// 14 | /// 15 | public static bool IsLight() 16 | { 17 | bool isLightMode = true; 18 | try 19 | { 20 | var v = Microsoft.Win32.Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", "1"); 21 | if (v != null && v.ToString() == "0") 22 | isLightMode = false; 23 | } 24 | catch { } 25 | return isLightMode; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Utils/WindowsApi/WLAN/IWlan.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public interface IWlan 10 | { 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /Utils/WindowsApi/WLAN/WlanHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | internal class WlanHelpers 11 | { 12 | internal static WlanConnectionNotificationData? ParseWlanConnectionNotification(ref WlanNotificationData notifyData) 13 | { 14 | int expectedSize = Marshal.SizeOf(typeof(WlanConnectionNotificationData)); 15 | if (notifyData.DataSize < expectedSize) 16 | return null; 17 | 18 | WlanConnectionNotificationData connNotifyData = (WlanConnectionNotificationData)Marshal.PtrToStructure(notifyData.DataPtr, typeof(WlanConnectionNotificationData)); 19 | 20 | if (connNotifyData.WlanReasonCode == WlanReasonCode.Success) 21 | { 22 | long profileXmlPtrValue = notifyData.DataPtr.ToInt64() + Marshal.OffsetOf(typeof(WlanConnectionNotificationData), "profileXml").ToInt64(); 23 | connNotifyData.ProfileXml = Marshal.PtrToStringUni(new IntPtr(profileXmlPtrValue)); 24 | } 25 | 26 | return connNotifyData; 27 | } 28 | 29 | /// 30 | /// Gets a string that describes a specified reason code. NOTE: Not used! 31 | /// 获取描述指定原因代码的字符串。注意:未使用! 32 | /// 33 | /// The reason code. 34 | /// The string. 35 | internal static string GetStringForReasonCode(WlanReasonCode reasonCode) 36 | { 37 | // the 1024 size here is arbitrary; the WlanReasonCodeToString docs fail to specify a recommended size 38 | // 这里的1024大小是任意的;WlanReasonCodeToString文档无法指定建议的大小 39 | StringBuilder sb = new StringBuilder(1024); 40 | 41 | if (WlanapiBase.WlanReasonCodeToString(reasonCode, sb.Capacity, sb, IntPtr.Zero) != 0) 42 | { 43 | // Not sure if we get junk in the stringbuilder buffer from WlanReasonCodeToString, clearing it to be sure. 44 | // 不确定是否从WlanReasonCodeToString在stringbuilder缓冲区中得到垃圾,请清除它以确定。 45 | sb.Clear(); 46 | sb.Append("Failed to retrieve reason code, probably too small buffer."); 47 | } 48 | 49 | return sb.ToString(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Utils/WindowsApi/WLAN/WlanManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | /// 11 | /// System WLAN Manager 12 | /// 13 | public class WlanManager 14 | { 15 | #region Fields 16 | /// 17 | /// 客户端在此会话中使用的句柄 18 | /// 19 | internal IntPtr _clientHandle; 20 | 21 | /// 22 | /// 将在此会话中使用的 WLAN API 版本 23 | /// 24 | internal uint _negotiatedVersion; 25 | 26 | /// 27 | /// 通知事件回调 28 | /// 29 | internal WlanapiBase.WlanNotificationCallbackDelegate _wlanNotificationCallback; 30 | 31 | /// 32 | /// 无线网卡列表 33 | /// 34 | private Dictionary _ifaces = new Dictionary(); 35 | #endregion 36 | 37 | #region Properties 38 | /// 39 | /// 没有WIFI 40 | /// 41 | public bool NoWifiAvailable { get; set; } 42 | 43 | /// 44 | /// Gets the WLAN interfaces. 45 | /// 获取WLAN接口 46 | /// 47 | /// Possible Win32 exceptions: 48 | /// 可能的Win32异常: 49 | /// 50 | /// ERROR_INVALID_PARAMETER: A parameter is incorrect. This error is returned if the hClientHandle or ppInterfaceList parameter is NULL. This error is returned if the pReserved is not NULL. This error is also returned if the hClientHandle parameter is not valid. 51 | /// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table. 52 | /// RPC_STATUS: Various error codes. 53 | /// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results. 54 | /// 55 | /// The WLAN interfaces. 56 | public WlanInterface[] Interfaces 57 | { 58 | get 59 | { 60 | if (NoWifiAvailable) 61 | return null; 62 | 63 | WlanapiBase.ThrowIfError(WlanapiBase.WlanEnumInterfaces(_clientHandle, IntPtr.Zero, out IntPtr ifaceList)); 64 | 65 | try 66 | { 67 | WlanInterfaceInfoListHeader header = (WlanInterfaceInfoListHeader)Marshal.PtrToStructure(ifaceList, typeof(WlanInterfaceInfoListHeader)); 68 | 69 | Int64 listIterator = ifaceList.ToInt64() + Marshal.SizeOf(header); 70 | WlanInterface[] interfaces = new WlanInterface[header.NumberOfItems]; 71 | List currentIfaceGuids = new List(); 72 | 73 | for (int i = 0; i < header.NumberOfItems; ++i) 74 | { 75 | WlanInterfaceInfo info = (WlanInterfaceInfo)Marshal.PtrToStructure(new IntPtr(listIterator), typeof(WlanInterfaceInfo)); 76 | 77 | listIterator += Marshal.SizeOf(info); 78 | currentIfaceGuids.Add(info.InterfaceGuid); 79 | 80 | WlanInterface wlanIface; 81 | if (_ifaces.ContainsKey(info.InterfaceGuid)) 82 | wlanIface = _ifaces[info.InterfaceGuid]; 83 | else 84 | wlanIface = new WlanInterface(this, info); 85 | 86 | interfaces[i] = wlanIface; 87 | _ifaces[info.InterfaceGuid] = wlanIface; 88 | } 89 | 90 | // Remove stale interfaces 91 | Queue deadIfacesGuids = new Queue(); 92 | foreach (Guid ifaceGuid in _ifaces.Keys) 93 | { 94 | if (!currentIfaceGuids.Contains(ifaceGuid)) 95 | deadIfacesGuids.Enqueue(ifaceGuid); 96 | } 97 | 98 | while (deadIfacesGuids.Count != 0) 99 | { 100 | Guid deadIfaceGuid = deadIfacesGuids.Dequeue(); 101 | _ifaces.Remove(deadIfaceGuid); 102 | } 103 | 104 | return interfaces; 105 | } 106 | finally 107 | { 108 | WlanapiBase.WlanFreeMemory(ifaceList); 109 | } 110 | } 111 | } 112 | #endregion 113 | 114 | #region Constructor 115 | public WlanManager() 116 | { 117 | int errorCode = 0; 118 | //限制条件 119 | OperatingSystem osVersion = Environment.OSVersion; 120 | bool isWinXP = osVersion.Platform == PlatformID.Win32NT && osVersion.Version.Major == 5 && osVersion.Version.Minor != 0; 121 | // wlanapi not supported in sp1 (or sp2 without hotfix) 122 | if (isWinXP && osVersion.ServicePack == "Service Pack 1") 123 | { 124 | errorCode = Win32ErrorCodes.ERROR_SERVICE_NOT_ACTIVE; 125 | } 126 | else 127 | { 128 | //连接WLAN服务 129 | try 130 | { 131 | errorCode = WlanapiBase.WlanOpenHandle(WlanapiBase.WLAN_CLIENT_VERSION_XP_SP2, IntPtr.Zero, out _negotiatedVersion, out _clientHandle); 132 | } 133 | catch 134 | { 135 | errorCode = Win32ErrorCodes.ERROR_SERVICE_NOT_ACTIVE; 136 | } 137 | } 138 | //判断是否开启成功 139 | if (errorCode != Win32ErrorCodes.ERROR_SUCCESS) 140 | { 141 | NoWifiAvailable = true; 142 | return; 143 | } 144 | //注册WLAN的通知 145 | try 146 | { 147 | // Interop callback 148 | _wlanNotificationCallback = new WlanapiBase.WlanNotificationCallbackDelegate(OnWlanNotification); 149 | 150 | WlanapiBase.ThrowIfError(WlanapiBase.WlanRegisterNotification(_clientHandle, 151 | WlanNotificationSource.WLAN_NOTIFICATION_SOURCE_ALL, false, 152 | _wlanNotificationCallback, IntPtr.Zero, IntPtr.Zero, out WlanNotificationSource prevSrc)); 153 | } 154 | catch 155 | { 156 | WlanapiBase.WlanCloseHandle(_clientHandle, IntPtr.Zero); 157 | throw new Exception(); 158 | } 159 | } 160 | 161 | ~WlanManager() 162 | { 163 | // Free the handle when deconstructing the client. There won't be a handle if its xp sp 2 without wlanapi installed 164 | // 释放实例 165 | try 166 | { 167 | WlanapiBase.WlanCloseHandle(_clientHandle, IntPtr.Zero); 168 | } 169 | catch 170 | { } 171 | } 172 | #endregion 173 | 174 | #region Fuc 175 | /// 176 | /// 当无线通知时 177 | /// 178 | /// 179 | /// 180 | private void OnWlanNotification(ref WlanNotificationData notifyData, IntPtr context) 181 | { 182 | if (NoWifiAvailable) 183 | return; 184 | 185 | WlanInterface wlanIface = _ifaces.ContainsKey(notifyData.InterfaceGuid) ? _ifaces[notifyData.InterfaceGuid] : null; 186 | 187 | switch (notifyData.NotificationSource) 188 | { 189 | case WlanNotificationSource.WLAN_NOTIFICATION_SOURCE_ACM: 190 | switch ((WlanNotificationCodeAcm)notifyData.NotificationCode) 191 | { 192 | case WlanNotificationCodeAcm.ConnectionStart: 193 | case WlanNotificationCodeAcm.ConnectionComplete: 194 | case WlanNotificationCodeAcm.ConnectionAttemptFail: 195 | case WlanNotificationCodeAcm.Disconnecting: 196 | case WlanNotificationCodeAcm.Disconnected: 197 | WlanConnectionNotificationData? connNotifyData = WlanHelpers.ParseWlanConnectionNotification(ref notifyData); 198 | 199 | if (connNotifyData.HasValue && wlanIface != null) 200 | wlanIface.OnWlanConnection(notifyData, connNotifyData.Value); 201 | 202 | break; 203 | case WlanNotificationCodeAcm.ScanFail: 204 | int expectedSize = Marshal.SizeOf(typeof(int)); 205 | 206 | if (notifyData.DataSize >= expectedSize) 207 | { 208 | int reasonInt = Marshal.ReadInt32(notifyData.DataPtr); 209 | 210 | // Want to make sure this doesn't crash if windows sends a reasoncode not defined in the enum. 211 | // 希望确保在windows发送枚举中未定义的推理码时不会崩溃。 212 | if (Enum.IsDefined(typeof(WlanReasonCode), reasonInt)) 213 | { 214 | WlanReasonCode reasonCode = (WlanReasonCode)reasonInt; 215 | 216 | if (wlanIface != null) 217 | wlanIface.OnWlanReason(notifyData, reasonCode); 218 | } 219 | } 220 | break; 221 | } 222 | break; 223 | case WlanNotificationSource.WLAN_NOTIFICATION_SOURCE_MSM: 224 | switch ((WlanNotificationCodeMsm)notifyData.NotificationCode) 225 | { 226 | case WlanNotificationCodeMsm.Associating: 227 | case WlanNotificationCodeMsm.Associated: 228 | case WlanNotificationCodeMsm.Authenticating: 229 | case WlanNotificationCodeMsm.Connected: 230 | case WlanNotificationCodeMsm.RoamingStart: 231 | case WlanNotificationCodeMsm.RoamingEnd: 232 | case WlanNotificationCodeMsm.Disassociating: 233 | case WlanNotificationCodeMsm.Disconnected: 234 | case WlanNotificationCodeMsm.PeerJoin: 235 | case WlanNotificationCodeMsm.PeerLeave: 236 | case WlanNotificationCodeMsm.AdapterRemoval: 237 | WlanConnectionNotificationData? connNotifyData = WlanHelpers.ParseWlanConnectionNotification(ref notifyData); 238 | 239 | if (connNotifyData.HasValue && wlanIface != null) 240 | wlanIface.OnWlanConnection(notifyData, connNotifyData.Value); 241 | 242 | break; 243 | } 244 | break; 245 | } 246 | 247 | if (wlanIface != null) 248 | wlanIface.OnWlanNotification(notifyData); 249 | } 250 | #endregion 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /Utils/WindowsApi/WLAN/WlanNotificationStructs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | internal struct WlanConnectionNotificationEventData 10 | { 11 | public WlanNotificationData NotifyData; 12 | public WlanConnectionNotificationData ConnNotifyData; 13 | } 14 | 15 | internal struct WlanReasonNotificationData 16 | { 17 | public WlanNotificationData NotifyData; 18 | public WlanReasonCode ReasonCode; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Utils/WindowsApi/WMI/Drive/Drive.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Management; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class Drive 11 | { 12 | /// 13 | /// 分区是否在外部磁盘上 14 | /// 15 | /// 分区盘符 16 | /// 17 | public static bool IsDriveOnExternalDisk(string driveLetter) 18 | { 19 | bool retVal = false; 20 | driveLetter = driveLetter.TrimEnd('\\'); 21 | 22 | // browse all USB WMI physical disks 23 | foreach (ManagementObject drive 24 | in new ManagementObjectSearcher("select DeviceID, MediaType,InterfaceType from Win32_DiskDrive") 25 | .Get() 26 | .Cast()) 27 | { 28 | // associate physical disks with partitions 29 | ManagementObjectCollection partitionCollection = new ManagementObjectSearcher(String.Format("associators of {{Win32_DiskDrive.DeviceID='{0}'}} " + "where AssocClass = Win32_DiskDriveToDiskPartition", drive["DeviceID"])).Get(); 30 | 31 | foreach (ManagementObject partition in partitionCollection.Cast()) 32 | { 33 | if (partition != null) 34 | { 35 | // associate partitions with logical disks (drive letter volumes) 36 | ManagementObjectCollection logicalCollection = new ManagementObjectSearcher(String.Format("associators of {{Win32_DiskPartition.DeviceID='{0}'}} " + "where AssocClass= Win32_LogicalDiskToPartition", partition["DeviceID"])).Get(); 37 | 38 | foreach (ManagementObject logical in logicalCollection.Cast()) 39 | { 40 | if (logical != null) 41 | { 42 | // finally find the logical disk entry 43 | ManagementObjectCollection.ManagementObjectEnumerator volumeEnumerator = new ManagementObjectSearcher(String.Format("select DeviceID from Win32_LogicalDisk " + "where Name='{0}'", logical["Name"])).Get().GetEnumerator(); 44 | 45 | volumeEnumerator.MoveNext(); 46 | 47 | ManagementObject volume = (ManagementObject)volumeEnumerator.Current; 48 | 49 | if (driveLetter.ToLowerInvariant().Equals(volume["DeviceID"].ToString().ToLowerInvariant()) && 50 | (drive["MediaType"].ToString().ToLowerInvariant().Contains("external") || drive["InterfaceType"].ToString().ToLowerInvariant().Contains("usb"))) 51 | { 52 | retVal = true; 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | return retVal; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Utils/WindowsApi/WMI/Monitor/Monitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Management; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class Monitor 11 | { 12 | public static int GetDesktopMonitorNumber() 13 | { 14 | int number = 0; 15 | try 16 | { 17 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DesktopMonitor"); 18 | 19 | foreach (ManagementObject queryObj in searcher.Get()) 20 | { 21 | number++; 22 | } 23 | } 24 | catch (ManagementException e) 25 | { 26 | Console.WriteLine(e.Message); 27 | } 28 | 29 | return number; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Utils/WindowsApi/WMI/USBDeviceWatcher/UsbDeviceWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Management; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Utils.WindowsApi 11 | { 12 | public class UsbDeviceWatcher 13 | { 14 | /// 15 | /// Keyboard 16 | /// 17 | private static readonly Guid Keyboard = new Guid("{4d36e96b-e325-11ce-bfc1-08002be10318}"); 18 | 19 | /// 20 | /// Mouse 21 | /// 22 | private static readonly Guid Mouse = new Guid("{4d36e96f-e325-11ce-bfc1-08002be10318}"); 23 | 24 | /// 25 | /// USB存储设备上线 26 | /// 27 | public event EventHandler UsbStorageInserted; 28 | /// 29 | /// USB存储设备下线 30 | /// 31 | public event EventHandler UsbStorageRemoved; 32 | 33 | /// 34 | /// HID鼠标上线 35 | /// 36 | public event EventHandler HIDMouseInserted; 37 | /// 38 | /// HID鼠标下线无需求,可以通过验证PnpDeviceId来确定设备 39 | /// 40 | //public event EventHandler HIDMouseRemoved; 41 | 42 | /// 43 | /// HID键盘上线 44 | /// 45 | public event EventHandler HIDKeyboardInserted; 46 | /// 47 | /// HID键盘下线,无需求,可以通过验证PnpDeviceId来确定设备 48 | /// 49 | //public event EventHandler HIDKeyboardRemoved; 50 | 51 | 52 | private ManagementEventWatcher _insertWatcher; 53 | 54 | private ManagementEventWatcher _removeWatcher; 55 | 56 | public class UsbStorageCreatEventArgs : EventArgs 57 | { 58 | public StringCollection DiskRoot { get; set; } 59 | 60 | public DriveType DriveType { get; set; } 61 | 62 | public string PNPDeviceID { get; set; } 63 | 64 | /// 65 | /// 通过得到的设备描述,来查询需要的信息 66 | /// 67 | /// 68 | /// 69 | public UsbStorageCreatEventArgs(string text, string dependent) 70 | { 71 | DiskRoot = UsbDeviceInfo.WMI_GetDiskRoot(dependent); 72 | 73 | DriveType = UsbDeviceInfo.WMI_GetDiskType(dependent); 74 | 75 | PNPDeviceID = text; 76 | } 77 | } 78 | 79 | public class UsbStorageDeleteEventArgs : EventArgs 80 | { 81 | /// 82 | /// 设备的唯一标识 83 | /// 84 | public string PNPDeviceID { get; set; } 85 | 86 | public UsbStorageDeleteEventArgs(string text) 87 | { 88 | PNPDeviceID = text; 89 | } 90 | } 91 | 92 | /// 93 | /// 获取UsbDeviceWatcher的实例 94 | /// 95 | public static UsbDeviceWatcher Instance = new Lazy(() => new UsbDeviceWatcher()).Value; 96 | 97 | /// 98 | /// 单例模式 99 | /// 100 | private UsbDeviceWatcher() 101 | { 102 | AddUSBEventWatcher(); 103 | } 104 | 105 | /// 106 | /// 添加USB设备监视 107 | /// 108 | /// 109 | private bool AddUSBEventWatcher() 110 | { 111 | try 112 | { 113 | var scope = new ManagementScope("root\\CIMV2"); 114 | var insert = new WqlEventQuery("__InstanceCreationEvent", TimeSpan.FromSeconds(1), "TargetInstance isa 'Win32_USBControllerDevice'"); 115 | var remove = new WqlEventQuery("__InstanceDeletionEvent", TimeSpan.FromSeconds(1), "TargetInstance isa 'Win32_USBControllerDevice'"); 116 | 117 | _insertWatcher = new ManagementEventWatcher(scope, insert); 118 | _removeWatcher = new ManagementEventWatcher(scope, remove); 119 | 120 | ///WMI服务USB加载响应事件 121 | _insertWatcher.EventArrived += OnUSBInserted; 122 | ///WMI服务USB移除响应事件 123 | _removeWatcher.EventArrived += OnUSBRemoved; 124 | 125 | ///开启监听 126 | _insertWatcher.Start(); 127 | _removeWatcher.Start(); 128 | 129 | return true; 130 | } 131 | catch (Exception) 132 | { 133 | Dispose(); 134 | return false; 135 | } 136 | } 137 | 138 | /// 139 | /// 注销Usb设备监视 140 | /// 141 | public void Dispose() 142 | { 143 | if (_insertWatcher != null) 144 | { 145 | _insertWatcher.Stop(); 146 | _insertWatcher.Dispose(); 147 | } 148 | if (_removeWatcher != null) 149 | { 150 | _removeWatcher.Stop(); 151 | _removeWatcher.Dispose(); 152 | } 153 | } 154 | 155 | /// 156 | /// Usb设备下线处理方法 157 | /// 158 | /// 159 | /// 160 | private void OnUSBRemoved(object sender, EventArrivedEventArgs e) 161 | { 162 | string dependent = UsbDeviceInfo.WhoUsbControllerDevice(e).Dependent; 163 | string text = dependent.Replace("\\\\", "\\"); 164 | 165 | ///Usb存储类设备标志 166 | if (text.StartsWith("USBSTOR\\")) 167 | { 168 | UsbStorageRemoved?.Invoke(this, new UsbStorageDeleteEventArgs(text)); 169 | } 170 | } 171 | 172 | /// 173 | /// Usb设备上线处理方法 174 | /// 175 | /// 176 | /// 177 | private void OnUSBInserted(object sender, EventArrivedEventArgs e) 178 | { 179 | string dependent = UsbDeviceInfo.WhoUsbControllerDevice(e).Dependent; 180 | string text = dependent.Replace("\\\\", "\\"); 181 | 182 | ///Usb存储类设备标志 183 | if (text.StartsWith("USBSTOR\\")) 184 | { 185 | UsbStorageInserted?.Invoke(this, new UsbStorageCreatEventArgs(text, dependent)); 186 | } 187 | else if (text.StartsWith("HID\\")) 188 | { 189 | PnPEntityInfo[] pnPEntityInfos = UsbDeviceInfo.WhoPnPEntity(text); 190 | 191 | for (int i = 0; !(pnPEntityInfos == null) && i < pnPEntityInfos.Length; i++) 192 | { 193 | ///通过guid去判定当前上线设备是什么类别的设备 194 | if (pnPEntityInfos[i].ClassGuid == Mouse) 195 | { 196 | HIDMouseInserted?.Invoke(this, pnPEntityInfos[i]); 197 | } 198 | else if (pnPEntityInfos[i].ClassGuid == Keyboard) 199 | { 200 | HIDKeyboardInserted?.Invoke(this, pnPEntityInfos[i]); 201 | } 202 | } 203 | } 204 | } 205 | 206 | /// 207 | /// 获取U盘在线状态 208 | /// 209 | public bool UDiskIsOnline 210 | { 211 | get 212 | { 213 | return false; 214 | } 215 | } 216 | 217 | /// 218 | /// 获取键盘在线状态 219 | /// 220 | public bool KeyboardIsOnline 221 | { 222 | get 223 | { 224 | return false; 225 | } 226 | } 227 | 228 | /// 229 | /// 获取鼠标在线状态 230 | /// 231 | public bool MouseIsOnline 232 | { 233 | get 234 | { 235 | return false; 236 | } 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Advapi32/Advapi32Base.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class Advapi32Base 11 | { 12 | private const string Advapi32 = "Advapi32.dll"; 13 | 14 | // 如果进程的访问令牌中没有关联某权限,则AdjustTokenPrivileges函数调用将会返回错误码ERROR_NOT_ALL_ASSIGNED(值为1300) 15 | public const int ERROR_NOT_ALL_ASSIGNED = 1300; 16 | 17 | #region TokenAccess 18 | internal const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000; 19 | internal const uint STANDARD_RIGHTS_READ = 0x00020000; 20 | internal const uint TOKEN_ASSIGN_PRIMARY = 0x0001; 21 | internal const uint TOKEN_DUPLICATE = 0x0002; 22 | internal const uint TOKEN_IMPERSONATE = 0x0004; 23 | internal const uint TOKEN_QUERY = 0x0008; 24 | internal const uint TOKEN_QUERY_SOURCE = 0x0010; 25 | internal const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; 26 | internal const uint TOKEN_ADJUST_GROUPS = 0x0040; 27 | internal const uint TOKEN_ADJUST_DEFAULT = 0x0080; 28 | internal const uint TOKEN_ADJUST_SESSIONID = 0x0100; 29 | internal const uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); 30 | internal const uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | 31 | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | 32 | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | 33 | TOKEN_ADJUST_SESSIONID); 34 | #endregion 35 | 36 | #region PrivilegeAttributes 37 | internal const uint SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001; 38 | internal const uint SE_PRIVILEGE_ENABLED = 0x00000002; 39 | internal const uint SE_PRIVILEGE_REMOVED = 0x00000004; 40 | internal const uint SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000; 41 | #endregion 42 | 43 | #region PrivilegeConstants 44 | internal const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege"; 45 | internal const string SE_AUDIT_NAME = "SeAuditPrivilege"; 46 | internal const string SE_BACKUP_NAME = "SeBackupPrivilege"; 47 | internal const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege"; 48 | internal const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege"; 49 | internal const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege"; 50 | internal const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege"; 51 | internal const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege"; 52 | internal const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege"; 53 | internal const string SE_DEBUG_NAME = "SeDebugPrivilege"; 54 | internal const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege"; 55 | internal const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege"; 56 | internal const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege"; 57 | internal const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"; 58 | internal const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege"; 59 | internal const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege"; 60 | internal const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege"; 61 | internal const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege"; 62 | internal const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege"; 63 | internal const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"; 64 | internal const string SE_RELABEL_NAME = "SeRelabelPrivilege"; 65 | internal const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"; 66 | internal const string SE_RESTORE_NAME = "SeRestorePrivilege"; 67 | internal const string SE_SECURITY_NAME = "SeSecurityPrivilege"; 68 | internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; 69 | internal const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege"; 70 | internal const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege"; 71 | internal const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege"; 72 | internal const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege"; 73 | internal const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"; 74 | internal const string SE_TCB_NAME = "SeTcbPrivilege"; 75 | internal const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege"; 76 | internal const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"; 77 | internal const string SE_UNDOCK_NAME = "SeUndockPrivilege"; 78 | internal const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"; 79 | #endregion 80 | 81 | #region Struct 82 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 83 | public struct LUID 84 | { 85 | public int LowPart; 86 | public uint HighPart; 87 | } 88 | 89 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 90 | public struct LUID_AND_ATTRIBUTES 91 | { 92 | public LUID Luid; 93 | public uint Attributes; 94 | } 95 | 96 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 97 | public struct TOKEN_PRIVILEGES 98 | { 99 | public int PrivilegeCount; 100 | public LUID_AND_ATTRIBUTES Privilege; 101 | } 102 | #endregion 103 | 104 | #region P/Invoke Functions 105 | //提升进程权限的Windows API 106 | [DllImport(Advapi32, CharSet = CharSet.Auto, SetLastError = true)] 107 | [return: MarshalAs(UnmanagedType.Bool)] 108 | internal static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccesss, out IntPtr TokenHandle); 109 | 110 | [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] 111 | [return: MarshalAs(UnmanagedType.Bool)] 112 | internal static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid); 113 | 114 | [DllImport(Advapi32, SetLastError = true)] 115 | internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); 116 | 117 | [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] 118 | [return: MarshalAs(UnmanagedType.Bool)] 119 | internal static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, [MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, uint ReturnLength); 120 | 121 | [DllImport(Advapi32, ExactSpelling = true, SetLastError = true)] 122 | internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref User32Base.TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); 123 | 124 | [DllImport(Advapi32, SetLastError = true, CharSet = CharSet.Unicode)] 125 | [return: MarshalAs(UnmanagedType.VariantBool)] 126 | internal static extern bool InitializeSecurityDescriptor(out object pSecurityDescriptor, uint dwRevision); 127 | 128 | [DllImport(Advapi32, SetLastError = true, CharSet = CharSet.Unicode)] 129 | [return: MarshalAs(UnmanagedType.VariantBool)] 130 | internal static extern bool SetSecurityDescriptorDacl(ref object pSecurityDescriptor, [MarshalAs(UnmanagedType.VariantBool)] bool bDaclPresent, object pDacl, [MarshalAs(UnmanagedType.VariantBool)] bool bDaclDefaulted); 131 | #endregion 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Advapi32/Advapi32Extension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class Advapi32Extension : Advapi32Base 11 | { 12 | /// 13 | /// 授予权限 14 | /// 参数取值为文件PrivilegeAPI中的类PrivilegeConstants中的字段 15 | /// 16 | /// PrivilegeConstants类中的字段 17 | /// 18 | public static bool GrantPrivilege(string privilegeName) 19 | { 20 | try 21 | { 22 | LUID locallyUniqueIdentifier = new LUID(); 23 | if (LookupPrivilegeValue(null, privilegeName, ref locallyUniqueIdentifier)) 24 | { 25 | TOKEN_PRIVILEGES tokenPrivileges = new TOKEN_PRIVILEGES(); 26 | tokenPrivileges.PrivilegeCount = 1; 27 | 28 | LUID_AND_ATTRIBUTES luidAndAtt = new LUID_AND_ATTRIBUTES(); 29 | // luidAndAtt.Attributes should be SE_PRIVILEGE_ENABLED to enable privilege 30 | luidAndAtt.Attributes = SE_PRIVILEGE_ENABLED; 31 | luidAndAtt.Luid = locallyUniqueIdentifier; 32 | tokenPrivileges.Privilege = luidAndAtt; 33 | 34 | IntPtr tokenHandle = IntPtr.Zero; 35 | try 36 | { 37 | if (OpenProcessToken(Kernel32Base.GetCurrentProcess(), 38 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandle)) 39 | { 40 | if (AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 1024, IntPtr.Zero, 0)) 41 | { 42 | // 当前用户没有关联该权限 43 | // 需要在windows系统(本地安全策略——本地策略——用户权限分配)中设置为该权限添加当前用户 44 | if (Marshal.GetLastWin32Error() != ERROR_NOT_ALL_ASSIGNED) 45 | { 46 | return true; 47 | } 48 | } 49 | } 50 | } 51 | finally 52 | { 53 | if (tokenHandle != IntPtr.Zero) 54 | { 55 | Kernel32Base.CloseHandle(tokenHandle); 56 | } 57 | } 58 | } 59 | return false; 60 | } 61 | catch (Exception) 62 | { 63 | return false; 64 | } 65 | } 66 | 67 | /// 68 | /// 撤销权限 69 | /// 参数取值为文件PrivilegeAPI中的类PrivilegeConstants中的字段 70 | /// 71 | /// PrivilegeConstants类中的字段 72 | /// 73 | public static bool RevokePrivilege(string privilegeName) 74 | { 75 | try 76 | { 77 | LUID locallyUniqueIdentifier = new LUID(); 78 | 79 | if (LookupPrivilegeValue(null, privilegeName, ref locallyUniqueIdentifier)) 80 | { 81 | TOKEN_PRIVILEGES tokenPrivileges = new TOKEN_PRIVILEGES(); 82 | tokenPrivileges.PrivilegeCount = 1; 83 | 84 | LUID_AND_ATTRIBUTES luidAndAtt = new LUID_AND_ATTRIBUTES(); 85 | // luidAndAtt.Attributes should be none (not set) to disable privilege 86 | luidAndAtt.Luid = locallyUniqueIdentifier; 87 | tokenPrivileges.Privilege = luidAndAtt; 88 | 89 | IntPtr tokenHandle = IntPtr.Zero; 90 | try 91 | { 92 | if (OpenProcessToken(Kernel32Base.GetCurrentProcess(), 93 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandle)) 94 | { 95 | if (AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 1024, IntPtr.Zero, 0)) 96 | { 97 | // 当前用户没有关联该权限 98 | // 需要在windows系统(本地安全策略——本地策略——用户权限分配)中设置为该权限添加当前用户 99 | if (Marshal.GetLastWin32Error() != ERROR_NOT_ALL_ASSIGNED) 100 | { 101 | return true; 102 | } 103 | } 104 | } 105 | } 106 | finally 107 | { 108 | if (tokenHandle != IntPtr.Zero) 109 | { 110 | Kernel32Base.CloseHandle(tokenHandle); 111 | } 112 | } 113 | } 114 | return false; 115 | } 116 | catch (Exception) 117 | { 118 | return false; 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Common/ExecuteResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public enum ExecuteResult 10 | { 11 | Success=0, 12 | Failed=1, 13 | ReStart=2, 14 | } 15 | 16 | public class Common 17 | { 18 | /// 19 | /// 判断Windows系统是否为旧版本 20 | /// 21 | /// 22 | public static bool IsOldOsVersion() 23 | { 24 | OperatingSystem os = Environment.OSVersion; 25 | return os.Platform != PlatformID.Win32NT || os.Version.Major < 6; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Kernel32/Kernel32Base.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class Kernel32Base 11 | { 12 | private const string Kernel32 = "kernel32.dll"; 13 | 14 | #region Struct 15 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 16 | public struct TimeZoneInformation 17 | { 18 | [MarshalAs(UnmanagedType.I4)] 19 | internal int bias; // 以分钟为单位 20 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] 21 | internal string standardName; // 标准时间的名称 22 | internal SystemTime standardDate; 23 | [MarshalAs(UnmanagedType.I4)] 24 | internal int standardBias; // 标准偏移 25 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] 26 | internal string daylightName; // 夏令时的名称 27 | internal SystemTime daylightDate; 28 | [MarshalAs(UnmanagedType.I4)] 29 | internal int daylightBias; // 夏令时偏移 30 | } 31 | 32 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 33 | public struct DynamicTimeZoneInformation 34 | { 35 | [MarshalAs(UnmanagedType.I4)] 36 | internal int bias; // 偏移,以分钟为单位 37 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] 38 | internal string standardName; // 标准时间的名称 39 | internal SystemTime standardDate; 40 | [MarshalAs(UnmanagedType.I4)] 41 | internal int standardBias; // 标准偏移 42 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] 43 | internal string daylightName; // 夏令时的名称 44 | internal SystemTime daylightDate; 45 | [MarshalAs(UnmanagedType.I4)] 46 | internal int daylightBias; // 夏令时偏移 47 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x80)] 48 | internal string timeZoneKeyName; // 时区名 49 | [MarshalAs(UnmanagedType.Bool)] 50 | internal bool dynamicDaylightTimeDisabled; // 是否自动调整时钟的夏令时 51 | } 52 | 53 | [StructLayout(LayoutKind.Sequential)] 54 | public struct SystemTime 55 | { 56 | [MarshalAs(UnmanagedType.U2)] 57 | internal ushort year; // 年 58 | [MarshalAs(UnmanagedType.U2)] 59 | internal ushort month; // 月 60 | [MarshalAs(UnmanagedType.U2)] 61 | internal ushort dayOfWeek; // 星期 62 | [MarshalAs(UnmanagedType.U2)] 63 | internal ushort day; // 日 64 | [MarshalAs(UnmanagedType.U2)] 65 | internal ushort hour; // 时 66 | [MarshalAs(UnmanagedType.U2)] 67 | internal ushort minute; // 分 68 | [MarshalAs(UnmanagedType.U2)] 69 | internal ushort second; // 秒 70 | [MarshalAs(UnmanagedType.U2)] 71 | internal ushort milliseconds; // 毫秒 72 | } 73 | 74 | [StructLayout(LayoutKind.Sequential)] 75 | internal class SecurityAttributes 76 | { 77 | public SecurityAttributes(object securityDescriptor) 78 | { 79 | this.lpSecurityDescriptor = securityDescriptor; 80 | } 81 | 82 | uint nLegnth = 12; 83 | object lpSecurityDescriptor; 84 | [MarshalAs(UnmanagedType.VariantBool)] 85 | bool bInheritHandle = true; 86 | } 87 | #endregion 88 | 89 | #region P/Invoke Functions 90 | //General 91 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 92 | [return: MarshalAs(UnmanagedType.VariantBool)] 93 | internal static extern bool CloseHandle(uint hHandle); 94 | 95 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 96 | internal static extern uint GetLastError(); 97 | 98 | //Semaphore 99 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 100 | internal static extern uint CreateSemaphore(SecurityAttributes auth, int initialCount, int maximumCount, string name); 101 | 102 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 103 | internal static extern uint WaitForSingleObject(uint hHandle, uint dwMilliseconds); 104 | 105 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 106 | [return: MarshalAs(UnmanagedType.VariantBool)] 107 | internal static extern bool ReleaseSemaphore(uint hHandle, int lReleaseCount, out int lpPreviousCount); 108 | 109 | //Memory Mapped Files 110 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 111 | internal static extern IntPtr CreateFileMapping(uint hFile, SecurityAttributes lpAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName); 112 | 113 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 114 | internal static extern IntPtr OpenFileMapping(uint dwDesiredAccess, bool bInheritHandle, string lpName); 115 | 116 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 117 | internal static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap); 118 | 119 | [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] 120 | [return: MarshalAs(UnmanagedType.VariantBool)] 121 | internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); 122 | 123 | //PrivateProfile 124 | [DllImport(Kernel32, CharSet = CharSet.Unicode)] 125 | internal static extern int WritePrivateProfileString(string section, string key, string val, string filePath); 126 | 127 | [DllImport(Kernel32, CharSet = CharSet.Unicode)] 128 | internal static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); 129 | 130 | [DllImport(Kernel32, EntryPoint = "GetPrivateProfileString")] 131 | internal static extern uint GetPrivateProfileStringA(string section, string key, string def, Byte[] retVal, int size, string filePath); 132 | 133 | //读取和设置时区 134 | // 针对于旧Windows系统,如Windows XP 135 | [DllImport(Kernel32, CharSet = CharSet.Auto)] 136 | internal static extern int GetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation); 137 | 138 | [DllImport(Kernel32, CharSet = CharSet.Auto)] 139 | internal static extern bool SetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation); 140 | 141 | // 针对于新Windows系统,如Windows 7, Windows8, Windows10 142 | [DllImport(Kernel32, CharSet = CharSet.Auto)] 143 | internal static extern int GetDynamicTimeZoneInformation(ref DynamicTimeZoneInformation lpDynamicTimeZoneInformation); 144 | 145 | [DllImport(Kernel32, CharSet = CharSet.Auto)] 146 | internal static extern bool SetDynamicTimeZoneInformation(ref DynamicTimeZoneInformation lpDynamicTimeZoneInformation); 147 | 148 | // 提升进程权限的Windows API 149 | [DllImport(Kernel32, CharSet = CharSet.Auto, SetLastError = true)] 150 | internal static extern IntPtr GetCurrentProcess(); 151 | 152 | [DllImport(Kernel32, CharSet = CharSet.Auto, SetLastError = true)] 153 | [return: MarshalAs(UnmanagedType.Bool)] 154 | internal static extern Boolean CloseHandle(IntPtr hObject); 155 | 156 | // 系统时间相关 157 | [DllImport(Kernel32)] 158 | internal static extern void GetLocalTime(ref SystemTime lpSystemTime); 159 | 160 | [DllImport(Kernel32)] 161 | internal static extern bool SetLocalTime(ref SystemTime lpSystemTime); 162 | 163 | [DllImport(Kernel32)] 164 | internal static extern void GetSystemTime(ref SystemTime lpSystemTime); 165 | 166 | [DllImport(Kernel32)] 167 | internal static extern bool SetSystemTime(ref SystemTime lpSystemTime); 168 | #endregion 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Kernel32/Kernel32Extension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class Kernel32Extension:Kernel32Base 11 | { 12 | #region 公共方法 13 | /// 14 | /// 写INI文件 15 | /// 16 | /// INI文件地址 17 | /// 节名称 18 | /// 键值 19 | /// 值 20 | public static void WriteINIValue(string FilePath, string Section, string Key, string Value) 21 | { 22 | if (!Directory.Exists(FilePath)) 23 | { 24 | Directory.CreateDirectory(Path.GetDirectoryName(FilePath)); 25 | } 26 | int n = WritePrivateProfileString(Section, Key, Value, FilePath); 27 | } 28 | 29 | /// 30 | /// 读INI文件 31 | /// 32 | /// INI文件地址 33 | /// 节名称 34 | /// 键值 35 | /// 36 | public static string ReadINIValue(string FilePath, string Section, string Key) 37 | { 38 | StringBuilder temp = new StringBuilder(4096); 39 | GetPrivateProfileString(Section, Key, "", temp, 4096, FilePath); 40 | return temp.ToString(); 41 | } 42 | 43 | /// 44 | /// 获取本地时区 45 | /// 46 | /// 47 | public static string GetLocalTimeZone() 48 | { 49 | // 检测当前系统是否为旧系统 50 | if (Common.IsOldOsVersion()) 51 | { 52 | TimeZoneInformation tzi = new TimeZoneInformation(); 53 | GetTimeZoneInformation(ref tzi); 54 | return TimeZoneInfo2CustomString(tzi); 55 | } 56 | DynamicTimeZoneInformation dtzi = new DynamicTimeZoneInformation(); 57 | GetDynamicTimeZoneInformation(ref dtzi); 58 | return DynamicTimeZoneInfo2CustomString(dtzi); 59 | } 60 | 61 | /// 62 | /// 设置本地时区 63 | /// 参数取值"China Standard Time",即可设置为中国时区 64 | /// 65 | /// 66 | /// 67 | public static bool SetLocalTimeZone(string timeZoneName_en) 68 | { 69 | if (Advapi32Extension.GrantPrivilege(Advapi32Base.SE_TIME_ZONE_NAME)) 70 | { 71 | DynamicTimeZoneInformation dtzi = TimeZoneName2DynamicTimeZoneInformation(timeZoneName_en); 72 | bool success = false; 73 | // 检测当前系统是否为旧系统 74 | if (Common.IsOldOsVersion()) 75 | { 76 | TimeZoneInformation tzi = DynamicTimeZoneInformation2TimeZoneInformation(dtzi); 77 | success = SetTimeZoneInformation(ref tzi); 78 | } 79 | else 80 | { 81 | success = SetDynamicTimeZoneInformation(ref dtzi); 82 | } 83 | if (success) 84 | { 85 | TimeZoneInfo.ClearCachedData(); // 清除缓存 86 | } 87 | if (!Advapi32Extension.RevokePrivilege(Advapi32Base.SE_TIME_ZONE_NAME)) 88 | { 89 | // 撤权失败 90 | } 91 | return success; 92 | } 93 | // 授权失败 94 | return false; 95 | } 96 | 97 | /// 98 | /// 获取本地时间 99 | /// 100 | /// 101 | public static DateTime GetLocalTime() 102 | { 103 | SystemTime sysTime = new SystemTime(); 104 | GetLocalTime(ref sysTime); 105 | return SystemTime2DateTime(sysTime); 106 | } 107 | 108 | /// 109 | /// 设置本地时间 110 | /// 111 | /// 112 | /// 113 | public static bool SetLocalTime(SystemTime dateTime) 114 | { 115 | bool success = SetLocalTime(ref dateTime); 116 | return success; 117 | } 118 | 119 | /// 120 | /// 获取系统时间 121 | /// 122 | /// 123 | public static DateTime GetSystemTime() 124 | { 125 | SystemTime sysTime = new SystemTime(); 126 | GetSystemTime(ref sysTime); 127 | return SystemTime2DateTime(sysTime); 128 | } 129 | 130 | /// 131 | /// 设置系统时间(UTC) 132 | /// 133 | /// 134 | /// 135 | public static bool SetSystemTime(DateTime dateTime) 136 | { 137 | SystemTime sysTime = DateTime2SystemTime(dateTime); 138 | bool success = SetSystemTime(ref sysTime); 139 | return success; 140 | } 141 | 142 | /// 143 | /// 将SystemTime转换为DateTime 144 | /// 145 | /// 146 | /// 147 | public static DateTime SystemTime2DateTime(SystemTime sysTime) 148 | { 149 | return new DateTime(sysTime.year, sysTime.month, sysTime.day, sysTime.hour, sysTime.minute, sysTime.second, sysTime.milliseconds); 150 | } 151 | 152 | /// 153 | /// 将DateTime转换为SystemTime 154 | /// 155 | /// 156 | /// 157 | public static SystemTime DateTime2SystemTime(DateTime dateTime) 158 | { 159 | SystemTime sysTime = new SystemTime 160 | { 161 | year = Convert.ToUInt16(dateTime.Year), 162 | month = Convert.ToUInt16(dateTime.Month), 163 | day = Convert.ToUInt16(dateTime.Day), 164 | hour = Convert.ToUInt16(dateTime.Hour), 165 | minute = Convert.ToUInt16(dateTime.Minute), 166 | second = Convert.ToUInt16(dateTime.Second), 167 | milliseconds = Convert.ToUInt16(dateTime.Millisecond) 168 | }; 169 | return sysTime; 170 | } 171 | #endregion 172 | 173 | #region 私有方法 174 | /// 175 | /// 将TimeZoneInformation转换为自定义string 176 | /// 177 | /// 178 | /// 179 | private static string TimeZoneInfo2CustomString(TimeZoneInformation tzi) 180 | { 181 | return tzi.standardName + "(" + tzi.bias + ")"; 182 | } 183 | 184 | /// 185 | /// 将DynamicTimeZoneInformation转换为自定义string 186 | /// 187 | /// 188 | /// 189 | private static string DynamicTimeZoneInfo2CustomString(DynamicTimeZoneInformation dtzi) 190 | { 191 | return dtzi.standardName + "(" + dtzi.bias + ")"; 192 | } 193 | 194 | /// 195 | /// 根据时区名获取对应的DynamicTimeZoneInformation 196 | /// 197 | /// 198 | /// 199 | private static DynamicTimeZoneInformation TimeZoneName2DynamicTimeZoneInformation(string timeZoneName) 200 | { 201 | TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName); 202 | 203 | DynamicTimeZoneInformation dtzi = new DynamicTimeZoneInformation 204 | { 205 | standardName = timeZoneInfo.StandardName, 206 | standardDate = new SystemTime(), 207 | daylightName = timeZoneInfo.DaylightName, 208 | daylightDate = new SystemTime(), 209 | timeZoneKeyName = timeZoneInfo.Id, 210 | dynamicDaylightTimeDisabled = false, 211 | bias = -Convert.ToInt32(timeZoneInfo.BaseUtcOffset.TotalMinutes) 212 | }; 213 | return dtzi; 214 | } 215 | 216 | /// 217 | /// 将DynamicTimeZoneInformation转换为TimeZoneInformation 218 | /// 219 | /// 220 | /// 221 | private static TimeZoneInformation DynamicTimeZoneInformation2TimeZoneInformation(DynamicTimeZoneInformation dtzi) 222 | { 223 | return new TimeZoneInformation 224 | { 225 | bias = dtzi.bias, 226 | standardName = dtzi.standardName, 227 | standardDate = dtzi.standardDate, 228 | standardBias = dtzi.standardBias, 229 | daylightName = dtzi.daylightName, 230 | daylightDate = dtzi.daylightDate, 231 | daylightBias = dtzi.daylightBias 232 | }; 233 | } 234 | #endregion 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Shell32/Shell32Base.Struct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace Utils.WindowsApi 10 | { 11 | public partial class Shell32Base 12 | { 13 | /// 14 | /// 文件信息标识枚举类,所有枚举定义值前省略SHGFI投标,比如Icon 完整名称应为SHGFI_ICON 15 | /// 16 | [Flags] 17 | public enum SHFileInfoFlags : uint 18 | { 19 | /// 20 | /// 允许有叠加图案的文件图标,该标识必须和Icon同时使用 21 | /// 22 | AddOveylays = 0x20, // SHGFI_AddOverlays = 0x000000020 23 | /// 24 | /// 只获取由参数FileAttribute指定的文件信息,并将其写入SHFileInfo结构的dwAttributes属性,如果不指定该标识,将同时获取所有文件信息。该标志不能和Icon标识同时使用 25 | /// 26 | Attr_Specified = 0x20000, // SHGFI_SpecifiedAttributes = 0x000020000 27 | /// 28 | /// 将获取的文件属性复制到SHFileInfo结构的dwAttributes属性中 29 | /// 30 | Attributes = 0x800, // SHGFI_Attributes = 0x000000800 31 | /// 32 | /// 获取文件的显示名称(长文件名称),将其复制到SHFileInfo结构的dwAttributes属性中 33 | /// 34 | DisplayName = 0x200, // SHGFI_DisplayName = 0x000000200 35 | /// 36 | /// 如果文件是可执行文件,将检索其信息,并将信息作为返回值返回 37 | /// 38 | ExeType = 0x2000, // SHGFI_EXEType = 0x000002000 39 | /// 40 | /// 获得图标和索引,将图标句柄返回到SHFileInfo结构的hIcon属性中,索引返回到iIcon属性中 41 | /// 42 | Icon = 0x100, // SHGFI_Icon = 0x000000100 43 | /// 44 | /// 检索包含图标的文件,并将文件名,图标句柄,图标索引号,放回到SHFileInfo结构中 45 | /// 46 | IconLocation = 0x1000, // SHGFI_IconLocation = 0x000001000 47 | /// 48 | /// 获得大图标,该标识必须和Icon标识同时使用 49 | /// 50 | LargeIcon = 0x0, // SHGFI_LargeIcon = 0x000000000 51 | /// 52 | /// 获取链接覆盖文件图标,该标识必须和Icon标识同时使用。 53 | /// 54 | LinkOverlay = 0x8000, // SHGFI_LinkOverlay = 0x000008000 55 | /// 56 | /// 获取文件打开时的图标,该标识必须和Icon或SysIconIndex同时使用 57 | /// 58 | OpenIcon = 0x2, // SHGFI_OpenIcon = 0x000000002 59 | /// 60 | /// 获取链接覆盖文件图标索引,该标识必须和Icon标识同时使用。 61 | /// 62 | OverlayIndex = 0x40, // SHGFI_OverlayIndex = 0x000000040 63 | /// 64 | /// 指示传入的路径是一个ITEMIDLIST结构的文件地址而不是一个路径名。 65 | /// 66 | Pidl = 0x8, // SHGFI_PIDL = 0x000000008 67 | /// 68 | /// 获取系统的高亮显示图标,该标识必须和Icon标识同时使用。 69 | /// 70 | Selected = 0x10000, // SHGFI_SelectedState = 0x000010000 71 | /// 72 | /// 获取 Shell-sized icon ,该标志必须和Icon标识同时使用。 73 | /// 74 | ShellIconSize = 0x4, // SHGFI_ShellIconSize = 0x000000004 75 | /// 76 | /// 获得小图标,该标识必须和Icon或SysIconIndex同时使用。 77 | /// 78 | SmallIcon = 0x1, // SHGFI_SmallIcon = 0x000000001 79 | /// 80 | /// 获取系统图像列表图标索引,返回系统图像列表句柄 81 | /// 82 | SysIconIndex = 0x4000, // SHGFI_SysIconIndex = 0x000004000 83 | /// 84 | /// 获得文件类型,类型字符串被写入SHFileInfo结构的szTypeName属性中 85 | /// 86 | TypeName = 0x400, // SHGFI_TypeName = 0x000000400 87 | /// 88 | /// 指示如果由pszPath指定的路径不存在,SHGetFileInfo方法变不会试图去操作文件。指示返回与文件类型相关的信息。该标识不能和Attributes、ExeType和Pidl同时使用 89 | /// 90 | UseFileAttributes = 0x10 // SHGFI_UserFileAttributes = 0x000000010, 91 | } 92 | 93 | /// 94 | /// 文件属性枚举 95 | /// 96 | [Flags] 97 | public enum FileAttribute 98 | { 99 | ReadOnly = 0x00000001, 100 | Hidden = 0x00000002, 101 | System = 0x00000004, 102 | Directory = 0x00000010, //路径信息 103 | Archive = 0x00000020, 104 | Device = 0x00000040, 105 | Normal = 0x00000080, //普通文件信息 106 | Temporary = 0x00000100, 107 | Sparse_File = 0x00000200, 108 | Reparse_Point = 0x00000400, 109 | Compressed = 0x00000800, 110 | Offline = 0x00001000, 111 | Not_Content_Indexed = 0x00002000, 112 | Encrypted = 0x00004000 113 | } 114 | 115 | /// 116 | /// 定义返回的文件信息结构 117 | /// 118 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 119 | public struct SHFileInfo 120 | { 121 | /// 122 | /// 文件的图标句柄 123 | /// 124 | public IntPtr hIcon; 125 | /// 126 | /// 图标的系统索引号 127 | /// 128 | public IntPtr iIcon; 129 | /// 130 | /// 文件的属性值,由FileAttribute指定的属性。 131 | /// 132 | public uint dwAttributes; 133 | /// 134 | /// 文件的显示名,如果是64位系统,您可能需要制定SizeConst=258而非260才能够显示完整的 TypeName 135 | /// 136 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 137 | public string szDisplayName; 138 | /// 139 | /// 文件的类型名 140 | /// 141 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] 142 | public string szTypeName; 143 | } 144 | 145 | /// 146 | /// 系统图标大小标识 147 | /// 148 | public enum IMAGELIST_SIZE_FLAG : int 149 | { 150 | /// 151 | /// Size(32,32) 152 | /// 153 | SHIL_LARGE = 0x0, 154 | /// 155 | /// Size(16,16) 156 | /// 157 | SHIL_SMALL = 0x1, 158 | /// 159 | /// Size(48,48) 160 | /// 161 | SHIL_EXTRALARGE = 0x2, 162 | /// 163 | /// Size(16,16) 164 | /// 165 | SHIL_SYSSMALL = 0x3, 166 | /// 167 | /// Size(256,256) 168 | /// 169 | SHIL_JUMBO = 0x4, 170 | /// 171 | /// 保留使用:目前测试效果为Size(256,256) 172 | /// 173 | SHIL_LAST = 0x4, 174 | } 175 | 176 | 177 | [ComImportAttribute()] 178 | [GuidAttribute("192B9D83-50FC-457B-90A0-2B82A8B5DAE1")] 179 | [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 180 | public interface IImageList 181 | { 182 | [PreserveSig] 183 | int Add(IntPtr hbmImage, IntPtr hbmMask, ref int pi); 184 | 185 | [PreserveSig] 186 | int ReplaceIcon(int i, IntPtr hicon, ref int pi); 187 | 188 | [PreserveSig] 189 | int SetOverlayImage(int iImage, int iOverlay); 190 | 191 | [PreserveSig] 192 | int Replace(int i, IntPtr hbmImage, IntPtr hbmMask); 193 | 194 | [PreserveSig] 195 | int AddMasked(IntPtr hbmImage, int crMask, ref int pi); 196 | 197 | [PreserveSig] 198 | int Draw(ref IMAGELISTDRAWPARAMS pimldp); 199 | 200 | [PreserveSig] 201 | int Remove(int i); 202 | 203 | [PreserveSig] 204 | int GetIcon(int i, int flags, ref IntPtr picon); 205 | 206 | [PreserveSig] 207 | int GetImageInfo(int i, ref IMAGEINFO pImageInfo); 208 | 209 | [PreserveSig] 210 | int Copy(int iDst, IImageList punkSrc, int iSrc, int uFlags); 211 | 212 | [PreserveSig] 213 | int Merge(int i1, IImageList punk2, int i2, int dx, int dy, ref Guid riid, ref IntPtr ppv); 214 | 215 | [PreserveSig] 216 | int Clone(ref Guid riid, ref IntPtr ppv); 217 | 218 | [PreserveSig] 219 | int GetImageRect(int i, ref RECT prc); 220 | 221 | [PreserveSig] 222 | int GetIconSize(ref int cx, ref int cy); 223 | 224 | [PreserveSig] 225 | int SetIconSize(int cx, int cy); 226 | 227 | [PreserveSig] 228 | int GetImageCount(ref int pi); 229 | 230 | [PreserveSig] 231 | int SetImageCount(int uNewCount); 232 | 233 | [PreserveSig] 234 | int SetBkColor(int clrBk, ref int pclr); 235 | 236 | [PreserveSig] 237 | int GetBkColor(ref int pclr); 238 | 239 | [PreserveSig] 240 | int BeginDrag(int iTrack, int dxHotspot, int dyHotspot); 241 | 242 | [PreserveSig] 243 | int EndDrag(); 244 | 245 | [PreserveSig] 246 | int DragEnter(IntPtr hwndLock, int x, int y); 247 | 248 | [PreserveSig] 249 | int DragLeave(IntPtr hwndLock); 250 | 251 | [PreserveSig] 252 | int DragMove(int x, int y); 253 | 254 | [PreserveSig] 255 | int SetDragCursorImage(ref IImageList punk, int iDrag, int dxHotspot, int dyHotspot); 256 | 257 | [PreserveSig] 258 | int DragShowNolock(int fShow); 259 | 260 | [PreserveSig] 261 | int GetDragImage(ref POINT ppt, ref POINT pptHotspot, ref Guid riid, ref IntPtr ppv); 262 | 263 | [PreserveSig] 264 | int GetItemFlags(int i, ref int dwFlags); 265 | 266 | [PreserveSig] 267 | int GetOverlayImage(int iOverlay, ref int piIndex); 268 | }; 269 | 270 | [StructLayout(LayoutKind.Sequential)] 271 | public struct IMAGELISTDRAWPARAMS 272 | { 273 | public int cbSize; 274 | public IntPtr himl; 275 | public int i; 276 | public IntPtr hdcDst; 277 | public int x; 278 | public int y; 279 | public int cx; 280 | public int cy; 281 | public int xBitmap; // x offest from the upperleft of bitmap 282 | public int yBitmap; // y offset from the upperleft of bitmap 283 | public int rgbBk; 284 | public int rgbFg; 285 | public int fStyle; 286 | public int dwRop; 287 | public int fState; 288 | public int Frame; 289 | public int crEffect; 290 | } 291 | 292 | [StructLayout(LayoutKind.Sequential)] 293 | public struct IMAGEINFO 294 | { 295 | public IntPtr hbmImage; 296 | public IntPtr hbmMask; 297 | public int Unused1; 298 | public int Unused2; 299 | public RECT rcImage; 300 | } 301 | 302 | [StructLayout(LayoutKind.Sequential)] 303 | public struct RECT 304 | { 305 | public int left, top, right, bottom; 306 | } 307 | 308 | [StructLayout(LayoutKind.Sequential)] 309 | public struct POINT 310 | { 311 | int x; 312 | int y; 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Shell32/Shell32Base.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Utils.WindowsApi 10 | { 11 | public partial class Shell32Base 12 | { 13 | private const string Shell32 = "shell32.dll"; 14 | 15 | /// 16 | /// 引用shell32文件的SHGetFileInfo API方法 17 | /// 18 | /// 指定的文件名,如果为""则返回文件夹的 19 | /// 文件属性 20 | /// 返回获得的文件信息,是一个记录类型 21 | /// 文件的类型名 22 | /// 文件信息标识 23 | /// -1失败 24 | [DllImport(Shell32, EntryPoint = "SHGetFileInfo", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)] 25 | public static extern IntPtr SHGetFileInfo(string pszPath, FileAttribute dwFileAttributes, ref SHFileInfo sfi, uint cbFileInfo, SHFileInfoFlags uFlags); 26 | 27 | /// 28 | /// 返回系统设置的图标 29 | /// 30 | /// 文件名,指定从exe文件或dll文件引入icon 31 | /// 文件的图表中的第几个,指定icon的索引如果为0则从指定的文件中引入第1个icon 32 | /// 返回的大图标的指针,大图标句柄如果为null则为没有大图标 33 | /// 返回的小图标的指针,小图标句柄如果为null则为没有小图标 34 | /// ico个数,找几个图标 35 | /// 15 | /// 当读取文件图标失败的默认图标索引号 16 | /// 17 | public static readonly long ErrorFileIndex = -2; 18 | /// 19 | /// 当读取文件夹图标失败的默认图标索引号 20 | /// 21 | public static readonly long ErrorFolderIndex = -4; 22 | /// 23 | /// 当读取磁盘驱动器图标失败的默认图标索引号 24 | /// 25 | public static readonly long ErrorDriverIndex = -8; 26 | /// 27 | /// 当读取可执行文件图标失败的默认图标索引号 28 | /// 29 | public static readonly long ErrorApplicationIndex = -16; 30 | 31 | /// 32 | /// 获取文件类型的关联图标 33 | /// 34 | /// 文件类型的扩展名或文件的绝对路径 35 | /// 是否返回小图标 36 | /// 返回一个Icon类型的文件图标对象 37 | public static Icon GetFileIcon(string fileName, bool isSmallIcon) 38 | { 39 | long imageIndex; 40 | return GetFileIcon(fileName, isSmallIcon, out imageIndex); 41 | } 42 | 43 | /// 44 | /// 获取系统文件图标 45 | /// 46 | /// 文件类型的扩展名或文件的绝对路径,如果是一个exe可执行文件,请提供完整的文件名(包含路径信息) 47 | /// 是否返回小图标 48 | /// 输出与返回图标对应的系统图标索引号 49 | /// 返回一个Icon类型的文件图标对象 50 | public static Icon GetFileIcon(string fileName, bool isSmallIcon, out long imageIndex) 51 | { 52 | imageIndex = ErrorFileIndex; 53 | if (String.IsNullOrEmpty(fileName)) 54 | return null; 55 | 56 | SHFileInfo shfi = new SHFileInfo(); 57 | SHFileInfoFlags uFlags = SHFileInfoFlags.Icon | SHFileInfoFlags.ShellIconSize; 58 | if (isSmallIcon) 59 | uFlags |= SHFileInfoFlags.SmallIcon; 60 | else 61 | uFlags |= SHFileInfoFlags.LargeIcon; 62 | FileInfo fi = new FileInfo(fileName); 63 | if (fi.Name.ToUpper().EndsWith(".EXE")) 64 | uFlags |= SHFileInfoFlags.ExeType; 65 | else 66 | uFlags |= SHFileInfoFlags.UseFileAttributes; 67 | 68 | int iTotal = (int)SHGetFileInfo(fileName, FileAttribute.Normal, ref shfi, (uint)Marshal.SizeOf(shfi), uFlags); 69 | //或int iTotal = (int)SHGetFileInfo(fileName, 0, ref shfi, (uint)Marshal.SizeOf(shfi), uFlags); 70 | Icon icon = null; 71 | if (iTotal > 0) 72 | { 73 | icon = Icon.FromHandle(shfi.hIcon).Clone() as Icon; 74 | imageIndex = shfi.iIcon.ToInt64(); 75 | } 76 | User32Base.DestroyIcon(shfi.hIcon); //释放资源 77 | return icon; 78 | } 79 | 80 | /// 81 | /// 获取系统文件夹默认图标 82 | /// 83 | /// 是否返回小图标 84 | /// 返回一个Icon类型的文件夹图标对象 85 | public static Icon GetFolderIcon(bool isSmallIcon) 86 | { 87 | long imageIndex; 88 | return GetFolderIcon(isSmallIcon, out imageIndex); 89 | } 90 | 91 | /// 92 | /// 获取系统文件夹默认图标 93 | /// 94 | /// 是否返回小图标 95 | /// 输出与返回图标对应的系统图标索引号 96 | /// 返回一个Icon类型的文件夹图标对象 97 | public static Icon GetFolderIcon(bool isSmallIcon, out long imageIndex) 98 | { 99 | return GetFolderIcon(Environment.SystemDirectory, isSmallIcon, out imageIndex); 100 | } 101 | 102 | /// 103 | /// 获取系统文件夹默认图标 104 | /// 105 | /// 文件夹名称,如果想获取自定义文件夹图标,请指定完整的文件夹名称(如 F:\test) 106 | /// 是否返回小图标 107 | /// 输出与返回图标对应的系统图标索引号 108 | /// 返回一个Icon类型的文件夹图标对象 109 | public static Icon GetFolderIcon(string folderName, bool isSmallIcon, out long imageIndex) 110 | { 111 | imageIndex = ErrorFolderIndex; 112 | if (String.IsNullOrEmpty(folderName)) 113 | return null; 114 | 115 | SHFileInfo shfi = new SHFileInfo(); 116 | SHFileInfoFlags uFlags = SHFileInfoFlags.Icon | SHFileInfoFlags.ShellIconSize | SHFileInfoFlags.UseFileAttributes; 117 | if (isSmallIcon) 118 | uFlags |= SHFileInfoFlags.SmallIcon; 119 | else 120 | uFlags |= SHFileInfoFlags.LargeIcon; 121 | 122 | int iTotal = (int)SHGetFileInfo(folderName, FileAttribute.Directory, ref shfi, (uint)Marshal.SizeOf(shfi), uFlags); 123 | //或int iTotal = (int)SHGetFileInfo("", 0, ref shfi, (uint)Marshal.SizeOf(shfi), SHFileInfoFlags.Icon | SHFileInfoFlags.SmallIcon); 124 | Icon icon = null; 125 | if (iTotal > 0) 126 | { 127 | icon = Icon.FromHandle(shfi.hIcon).Clone() as Icon; 128 | imageIndex = shfi.iIcon.ToInt64(); 129 | } 130 | User32Base.DestroyIcon(shfi.hIcon); //释放资源 131 | return icon; 132 | } 133 | 134 | /// 135 | /// 获取磁盘驱动器图标 136 | /// 137 | /// 有效的磁盘标号,如C、D、I等等,不区分大小写 138 | /// 标识是获取小图标还是获取大图标 139 | /// 输出与返回图标对应的系统图标索引号 140 | /// 返回一个Icon类型的磁盘驱动器图标对象 141 | public static Icon GetDriverIcon(char driverMark, bool isSmallIcon) 142 | { 143 | long imageIndex; 144 | return GetDriverIcon(driverMark, isSmallIcon, out imageIndex); 145 | } 146 | 147 | /// 148 | /// 获取磁盘驱动器图标 149 | /// 150 | /// 有效的磁盘标号,如C、D、I等等,不区分大小写 151 | /// 标识是获取小图标还是获取大图标 152 | /// 输出与返回图标对应的系统图标索引号 153 | /// 返回一个Icon类型的磁盘驱动器图标对象 154 | public static Icon GetDriverIcon(char driverMark, bool isSmallIcon, out long imageIndex) 155 | { 156 | imageIndex = ErrorDriverIndex; 157 | //非有效盘符,返回封装的磁盘图标 158 | if (driverMark < 'a' && driverMark > 'z' && driverMark < 'A' && driverMark > 'Z') 159 | { 160 | return null; 161 | } 162 | string driverName = driverMark.ToString().ToUpper() + ":\\"; 163 | 164 | SHFileInfo shfi = new SHFileInfo(); 165 | SHFileInfoFlags uFlags = SHFileInfoFlags.Icon | SHFileInfoFlags.ShellIconSize | SHFileInfoFlags.UseFileAttributes; 166 | if (isSmallIcon) 167 | uFlags |= SHFileInfoFlags.SmallIcon; 168 | else 169 | uFlags |= SHFileInfoFlags.LargeIcon; 170 | int iTotal = (int)SHGetFileInfo(driverName, FileAttribute.Normal, ref shfi, (uint)Marshal.SizeOf(shfi), uFlags); 171 | //int iTotal = (int)SHGetFileInfo(driverName, 0, ref shfi, (uint)Marshal.SizeOf(shfi), uFlags); 172 | Icon icon = null; 173 | if (iTotal > 0) 174 | { 175 | icon = Icon.FromHandle(shfi.hIcon).Clone() as Icon; 176 | imageIndex = shfi.iIcon.ToInt64(); 177 | } 178 | User32Base.DestroyIcon(shfi.hIcon); //释放资源 179 | return icon; 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/User32/User32Base.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class User32Base 11 | { 12 | private const string User32 = "user32.dll"; 13 | 14 | #region Field 15 | public const int GWL_HWNDPARENT = -8; 16 | 17 | public const int SE_PRIVILEGE_ENABLED = 0x00000002; 18 | 19 | public const int TOKEN_QUERY = 0x00000008; 20 | 21 | public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; 22 | 23 | public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; 24 | 25 | /// 26 | /// 检索桌面壁纸的位图文件的完整路径 27 | /// 28 | public const uint SPI_GETDESKWALLPAPER = 0x0073; 29 | #endregion 30 | 31 | #region Structures 32 | 33 | [StructLayout(LayoutKind.Sequential)] 34 | internal struct LASTINPUTINFO 35 | { 36 | public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO)); 37 | 38 | [MarshalAs(UnmanagedType.U4)] 39 | public int cbSize; 40 | 41 | [MarshalAs(UnmanagedType.U4)] 42 | public UInt32 dwTime; 43 | } 44 | 45 | // 映射 DEVMODE 结构 46 | // 可以参照 DEVMODE结构的指针定义: 47 | // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx 48 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 49 | public struct DEVMODE 50 | { 51 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 52 | public string dmDeviceName; 53 | 54 | public short dmSpecVersion; 55 | public short dmDriverVersion; 56 | public short dmSize; 57 | public short dmDriverExtra; 58 | public int dmFields; 59 | public int dmPositionX; 60 | public int dmPositionY; 61 | public int dmDisplayOrientation; 62 | public int dmDisplayFixedOutput; 63 | public short dmColor; 64 | public short dmDuplex; 65 | public short dmYResolution; 66 | public short dmTTOption; 67 | public short dmCollate; 68 | 69 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 70 | public string dmFormName; 71 | 72 | public short dmLogPixels; 73 | public short dmBitsPerPel; 74 | public int dmPelsWidth; 75 | public int dmPelsHeight; 76 | public int dmDisplayFlags; 77 | public int dmDisplayFrequency; 78 | public int dmICMMethod; 79 | public int dmICMIntent; 80 | public int dmMediaType; 81 | public int dmDitherType; 82 | public int dmReserved1; 83 | public int dmReserved2; 84 | public int dmPanningWidth; 85 | public int dmPanningHeight; 86 | }; 87 | 88 | [StructLayout(LayoutKind.Sequential)] 89 | public struct DevBroadcastDeviceInterface 90 | { 91 | internal int Size; 92 | internal int DeviceType; 93 | internal int Reserved; 94 | internal Guid ClassGuid; 95 | internal short Name; 96 | } 97 | 98 | [StructLayout(LayoutKind.Sequential)] 99 | public struct DevBroadcastHdr 100 | { 101 | internal UInt32 Size; 102 | internal UInt32 DeviceType; 103 | internal UInt32 Reserved; 104 | } 105 | 106 | [Flags] 107 | public enum ExitWindows : uint 108 | { 109 | /// 110 | /// 注销 111 | /// 112 | LoginOff = 0x00, 113 | /// 114 | /// 关机 115 | /// 116 | ShutDown = 0x01, 117 | /// 118 | /// 重启 119 | /// 120 | Reboot = 0x02, 121 | Force = 0x04, 122 | PowerOff = 0x08, 123 | ForceIfHung = 0x10 124 | } 125 | 126 | [Flags] 127 | public enum ShutdownReason : uint 128 | { 129 | MajorApplication = 0x00040000, 130 | MajorHardware = 0x00010000, 131 | MajorLegacyApi = 0x00070000, 132 | MajorOperatingSystem = 0x00020000, 133 | MajorOther = 0x00000000, 134 | MajorPower = 0x00060000, 135 | MajorSoftware = 0x00030000, 136 | MajorSystem = 0x00050000, 137 | MinorBlueScreen = 0x0000000F, 138 | MinorCordUnplugged = 0x0000000b, 139 | MinorDisk = 0x00000007, 140 | MinorEnvironment = 0x0000000c, 141 | MinorHardwareDriver = 0x0000000d, 142 | MinorHotfix = 0x00000011, 143 | MinorHung = 0x00000005, 144 | MinorInstallation = 0x00000002, 145 | MinorMaintenance = 0x00000001, 146 | MinorMMC = 0x00000019, 147 | MinorNetworkConnectivity = 0x00000014, 148 | MinorNetworkCard = 0x00000009, 149 | MinorOther = 0x00000000, 150 | MinorOtherDriver = 0x0000000e, 151 | MinorPowerSupply = 0x0000000a, 152 | MinorProcessor = 0x00000008, 153 | MinorReconfig = 0x00000004, 154 | MinorSecurity = 0x00000013, 155 | MinorSecurityFix = 0x00000012, 156 | MinorSecurityFixUninstall = 0x00000018, 157 | MinorServicePack = 0x00000010, 158 | MinorServicePackUninstall = 0x00000016, 159 | MinorTermSrv = 0x00000020, 160 | MinorUnstable = 0x00000006, 161 | MinorUpgrade = 0x00000003, 162 | MinorWMI = 0x00000015, 163 | FlagUserDefined = 0x40000000, 164 | FlagPlanned = 0x80000000 165 | } 166 | 167 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 168 | public struct TokPriv1Luid 169 | { 170 | public int Count; 171 | public long Luid; 172 | public int Attr; 173 | } 174 | #endregion 175 | 176 | #region P/Invoke Functions 177 | 178 | [DllImport(User32)] 179 | internal static extern int Mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo); 180 | 181 | [DllImport(User32)] 182 | internal static extern int Keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); 183 | 184 | [DllImport(User32)] 185 | internal static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); 186 | 187 | [DllImport(User32)] 188 | internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); 189 | 190 | /// 191 | /// 设置窗体父窗体 192 | /// 193 | /// 子窗体句柄 194 | /// 父窗体句柄 195 | /// 196 | [DllImport(User32)] 197 | internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 198 | 199 | /// 200 | /// 得到对应名称Window的句柄 201 | /// 202 | /// Window所属类 203 | /// Window名称 204 | /// 205 | [DllImport(User32, SetLastError = true)] 206 | internal static extern IntPtr FindWindow(string lpWindowClass, string lpWindowName); 207 | 208 | /// 209 | /// 得到指定窗口的子窗口 210 | /// 211 | /// 212 | /// 213 | /// 214 | internal delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam); 215 | [DllImport(User32)] 216 | [return: MarshalAs(UnmanagedType.Bool)] 217 | internal static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); 218 | 219 | [DllImport(User32, SetLastError = true)] 220 | internal static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle); 221 | 222 | [DllImport(User32, SetLastError = true)] 223 | internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); 224 | 225 | [DllImport(User32, SetLastError = true)] 226 | internal static extern int ShowWindow(IntPtr hwnd, int nCmdShow); 227 | 228 | [DllImport(User32)] 229 | internal static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); 230 | 231 | /// 232 | /// 枚举显示器设置 233 | /// 234 | /// 显示器名称 235 | /// 参数类型 236 | /// 参数结构 237 | /// 238 | [DllImport(User32)] 239 | internal static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode); 240 | 241 | /// 242 | /// 改变显示设置 243 | /// 244 | /// 参数结构 245 | /// 246 | /// 247 | [DllImport(User32)] 248 | internal static extern int ChangeDisplaySettings(ref DEVMODE devMode, int flags); 249 | 250 | /// 251 | /// 注册设备通知 252 | /// 253 | /// 254 | /// 255 | /// 256 | /// 257 | [DllImport(User32, CharSet = CharSet.Auto, SetLastError = true)] 258 | internal static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags); 259 | 260 | /// 261 | /// 取消设备通知 262 | /// 263 | /// 264 | /// 265 | [DllImport(User32)] 266 | internal static extern bool UnregisterDeviceNotification(IntPtr handle); 267 | 268 | [DllImport(User32)] 269 | internal static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason); 270 | 271 | /// 272 | /// 检索或设置系统范围参数(sting类型) 273 | /// 274 | /// 275 | /// 276 | /// 277 | /// 278 | /// 279 | [DllImport(User32, CharSet = CharSet.Auto, SetLastError = true)] 280 | internal static extern bool SystemParametersInfo(uint uAction, uint uParam, StringBuilder lpvParam, uint init); 281 | 282 | [DllImport(User32, EntryPoint = "DestroyIcon")] 283 | public static extern int DestroyIcon(IntPtr hIcon); 284 | #endregion 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/User32/User32Extension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class User32Extension : User32Base 11 | { 12 | #region Field 13 | private const int WM_SYSCOMMAND = 0x112; //系统消息 14 | private const int SC_SCREENSAVE = 0xf140; // 启动屏幕保护消息 15 | private const int SC_MONITORPOWER = 0xF170; //关闭显示器的系统命令 16 | private const int POWER_OFF = 2; //2 为关闭, 1为省电状态,-1为开机 17 | private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); //广播消息,所有顶级窗体都会接收 18 | //移动鼠标 19 | public const int MOUSEEVENTF_MOVE = 0x0001; 20 | //模拟鼠标左键按下 21 | public const int MOUSEEVENTF_LEFTDOWN = 0x0002; 22 | //模拟鼠标左键抬起 23 | public const int MOUSEEVENTF_LEFTUP = 0x0004; 24 | //模拟鼠标右键按下 25 | public const int MOUSEEVENTF_RIGHTDOWN = 0x0008; 26 | //模拟鼠标右键抬起 27 | public const int MOUSEEVENTF_RIGHTUP = 0x0010; 28 | //模拟鼠标中键按下 29 | public const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; 30 | //模拟鼠标中键抬起 31 | public const int MOUSEEVENTF_MIDDLEUP = 0x0040; 32 | //标示是否采用绝对坐标 33 | public const int MOUSEEVENTF_ABSOLUTE = 0x8000; 34 | //模拟鼠标滚轮滚动操作,必须配合dwData参数 35 | public const int MOUSEEVENTF_WHEEL = 0x0800; 36 | 37 | // 控制改变屏幕分辨率的常量 38 | public const int ENUM_CURRENT_SETTINGS = -1; 39 | public const int CDS_UPDATEREGISTRY = 0x01; 40 | public const int CDS_TEST = 0x02; 41 | public const int DISP_CHANGE_SUCCESSFUL = 0; 42 | public const int DISP_CHANGE_RESTART = 1; 43 | public const int DISP_CHANGE_FAILED = -1; 44 | 45 | // 控制改变方向的常量定义 46 | public const int DMDO_DEFAULT = 0; 47 | public const int DMDO_90 = 1; 48 | public const int DMDO_180 = 2; 49 | public const int DMDO_270 = 3; 50 | 51 | //注册设备消息相关 52 | public const int DbtDeviceArrival = 0x8000; // System detected a new device 53 | public const int DbtDeviceRemoveComplete = 0x8004; // Device is gone 54 | public const int WmDeviceChange = 0x0219; // Device change event 55 | private const int DbtDeviceTypeDeviceInterface = 5; 56 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-usb-device 57 | private static readonly Guid GuidDeviceInterfaceUSBDevice = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"); // USB devices 58 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-monitor 59 | private static readonly Guid GuidDeviceInterfaceMonitorDevice = new Guid("E6F07B5F-EE97-4a90-B076-33F57BF4EAA7"); // Monitor devices 60 | private static IntPtr usbNotificationHandle; 61 | private static IntPtr monitorNotificationHandle; 62 | #endregion 63 | 64 | #region Function 65 | /// 66 | /// 虚拟鼠标操作 67 | /// 68 | /// 69 | /// 70 | /// 71 | /// 72 | /// 73 | public static void SimulateMouseOperation(int flags, int dx, int dy, int dData, int dwExtraInfo) 74 | { 75 | User32Base.Mouse_event(flags, dx, dy, dData, dwExtraInfo); 76 | } 77 | 78 | /// 79 | /// 进行一次简单的鼠标操作 80 | /// 81 | public static void ClearFreeTime() 82 | { 83 | User32Base.Keybd_event(39, 0, 0, 0); 84 | User32Base.Keybd_event(39, 0, 2, 0); 85 | } 86 | 87 | /// 88 | /// 获取电脑最后输入时间 89 | /// 90 | /// 91 | public static int GetLastInputTime() 92 | { 93 | int idleTime = 0; 94 | 95 | LASTINPUTINFO lastInputInfo = new LASTINPUTINFO(); 96 | 97 | lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo); 98 | 99 | lastInputInfo.dwTime = 0; 100 | 101 | int envTicks = Environment.TickCount; 102 | 103 | if (GetLastInputInfo(ref lastInputInfo)) 104 | { 105 | int lastInputTick = Convert.ToInt32(lastInputInfo.dwTime); 106 | 107 | idleTime = envTicks - lastInputTick; 108 | } 109 | 110 | int toret = ((idleTime > 0) ? (idleTime / 1000) : 0); 111 | 112 | return toret; 113 | } 114 | 115 | /// 116 | /// 关闭显示器 117 | /// 118 | public static void TurnOffScreen() 119 | { 120 | SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, POWER_OFF); // 关闭显示器 121 | } 122 | 123 | /// 124 | /// 返回窗口子窗口指针列表 125 | /// Returns a list of child windows 126 | /// 127 | /// Parent of the windows to return 128 | /// List of child windows 129 | public static List GetChildWindows(IntPtr parent) 130 | { 131 | List result = new List(); 132 | GCHandle listHandle = GCHandle.Alloc(result); 133 | try 134 | { 135 | EnumWindowsProc childProc = new EnumWindowsProc(EnumWindow); 136 | EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); 137 | } 138 | finally 139 | { 140 | if (listHandle.IsAllocated) 141 | listHandle.Free(); 142 | } 143 | return result; 144 | } 145 | 146 | /// 147 | /// 枚举子窗口的回调方法 148 | /// Callback method to be used when enumerating windows. 149 | /// 150 | /// Handle of the next window 151 | /// Pointer to a GCHandle that holds a reference to the list to fill 152 | /// True to continue the enumeration, false to bail 153 | private static bool EnumWindow(IntPtr handle, IntPtr pointer) 154 | { 155 | GCHandle gch = GCHandle.FromIntPtr(pointer); 156 | List list = gch.Target as List; 157 | if (list == null) 158 | { 159 | throw new InvalidCastException("GCHandle Target could not be cast as List"); 160 | } 161 | list.Add(handle); 162 | // You can modify this to check to see if you want to cancel the operation, then return a null here 163 | return true; 164 | } 165 | 166 | /// 167 | /// 改变分辨率 168 | /// 169 | /// 170 | /// 171 | public static ExecuteResult ChangeDisplayResolution(int width, int height) 172 | { 173 | // 初始化 DEVMODE结构 174 | DEVMODE devmode = new DEVMODE(); 175 | devmode.dmDeviceName = new String(new char[32]); 176 | devmode.dmFormName = new String(new char[32]); 177 | devmode.dmSize = (short)Marshal.SizeOf(devmode); 178 | 179 | if (0 != EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref devmode)) 180 | { 181 | devmode.dmPelsWidth = width; 182 | devmode.dmPelsHeight = height; 183 | 184 | // 改变屏幕分辨率 185 | int iRet = ChangeDisplaySettings(ref devmode, CDS_TEST); 186 | 187 | if (iRet == DISP_CHANGE_FAILED) 188 | { 189 | //MessageBox.Show("不能执行你的请求", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); 190 | return ExecuteResult.Failed; 191 | } 192 | else 193 | { 194 | iRet = ChangeDisplaySettings(ref devmode, CDS_UPDATEREGISTRY); 195 | 196 | switch (iRet) 197 | { 198 | // 成功改变 199 | case DISP_CHANGE_SUCCESSFUL: 200 | { 201 | return ExecuteResult.Success; 202 | //break; 203 | } 204 | case DISP_CHANGE_RESTART: 205 | { 206 | // MessageBox.Show("你需要重新启动电脑设置才能生效", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); 207 | return ExecuteResult.ReStart; 208 | //break; 209 | } 210 | default: 211 | { 212 | return ExecuteResult.Failed; 213 | // MessageBox.Show("改变屏幕分辨率失败", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); 214 | //break; 215 | } 216 | } 217 | } 218 | } 219 | else 220 | { 221 | return ExecuteResult.Failed; 222 | } 223 | } 224 | 225 | /// 226 | /// 获取显示设置 227 | /// 228 | /// 229 | public static DEVMODE GetDisplaySettings() 230 | { 231 | // 初始化 DEVMODE结构 232 | DEVMODE devmode = new DEVMODE(); 233 | devmode.dmDeviceName = new String(new char[32]); 234 | devmode.dmFormName = new String(new char[32]); 235 | devmode.dmSize = (short)Marshal.SizeOf(devmode); 236 | 237 | User32Base.EnumDisplaySettings(null, User32Extension.ENUM_CURRENT_SETTINGS, ref devmode); 238 | 239 | return devmode; 240 | } 241 | 242 | #region 注册设备消息相关 243 | public static bool IsMonitor(IntPtr lParam) 244 | { 245 | return IsDeviceOfClass(lParam, GuidDeviceInterfaceMonitorDevice); 246 | } 247 | 248 | public static bool IsUsbDevice(IntPtr lParam) 249 | { 250 | return IsDeviceOfClass(lParam, GuidDeviceInterfaceUSBDevice); 251 | } 252 | /// Registers a window to receive notifications when Monitor devices are plugged or unplugged. 253 | public static void RegisterMonitorDeviceNotification(IntPtr windowHandle) 254 | { 255 | var dbi = CreateBroadcastDeviceInterface(GuidDeviceInterfaceMonitorDevice); 256 | monitorNotificationHandle = RegisterDeviceNotification(dbi, windowHandle); 257 | } 258 | 259 | /// Registers a window to receive notifications when USB devices are plugged or unplugged. 260 | public static void RegisterUsbDeviceNotification(IntPtr windowHandle) 261 | { 262 | var dbi = CreateBroadcastDeviceInterface(GuidDeviceInterfaceUSBDevice); 263 | usbNotificationHandle = RegisterDeviceNotification(dbi, windowHandle); 264 | } 265 | 266 | /// UnRegisters the window for Monitor device notifications 267 | public static void UnRegisterMonitorDeviceNotification() 268 | { 269 | UnregisterDeviceNotification(monitorNotificationHandle); 270 | } 271 | 272 | /// UnRegisters the window for USB device notifications 273 | public static void UnRegisterUsbDeviceNotification() 274 | { 275 | UnregisterDeviceNotification(usbNotificationHandle); 276 | } 277 | 278 | private static bool IsDeviceOfClass(IntPtr lParam, Guid classGuid) 279 | { 280 | var hdr = Marshal.PtrToStructure(lParam); 281 | 282 | if (hdr.DeviceType != DbtDeviceTypeDeviceInterface) 283 | return false; 284 | 285 | var devIF = Marshal.PtrToStructure(lParam); 286 | 287 | return devIF.ClassGuid == classGuid; 288 | 289 | } 290 | 291 | private static IntPtr RegisterDeviceNotification(DevBroadcastDeviceInterface dbi, IntPtr windowHandle) 292 | { 293 | var buffer = Marshal.AllocHGlobal(dbi.Size); 294 | IntPtr handle; 295 | 296 | try 297 | { 298 | Marshal.StructureToPtr(dbi, buffer, true); 299 | 300 | handle = RegisterDeviceNotification(windowHandle, buffer, 0); 301 | } 302 | finally 303 | { 304 | // Free buffer 305 | Marshal.FreeHGlobal(buffer); 306 | } 307 | 308 | return handle; 309 | } 310 | 311 | private static DevBroadcastDeviceInterface CreateBroadcastDeviceInterface(Guid classGuid) 312 | { 313 | var dbi = new DevBroadcastDeviceInterface 314 | { 315 | DeviceType = DbtDeviceTypeDeviceInterface, 316 | Reserved = 0, 317 | ClassGuid = classGuid, 318 | Name = 0 319 | }; 320 | 321 | dbi.Size = Marshal.SizeOf(dbi); 322 | 323 | return dbi; 324 | } 325 | #endregion 326 | 327 | /// 328 | /// 重启 329 | /// 330 | public static void ReBoot() 331 | { 332 | DoExitWindows(ExitWindows.Force | ExitWindows.Reboot); 333 | } 334 | 335 | /// 336 | /// 关机 337 | /// 338 | public static void ShutDown() 339 | { 340 | DoExitWindows(ExitWindows.Force | ExitWindows.ShutDown); 341 | } 342 | 343 | /// 344 | /// 注销 345 | /// 346 | public static void LoginOff() 347 | { 348 | DoExitWindows(ExitWindows.Force | ExitWindows.LoginOff); 349 | } 350 | 351 | /// 352 | /// 获取当前使用的桌面壁纸的路径 353 | /// 354 | /// 355 | public static bool GetDesktopWallpaper(out string wallPaperPath) 356 | { 357 | StringBuilder path = new StringBuilder(200); 358 | var result = SystemParametersInfo(SPI_GETDESKWALLPAPER, 200, path, 0); 359 | wallPaperPath = path.ToString(); 360 | return result; 361 | } 362 | #endregion 363 | 364 | #region 私有方法 365 | /// 366 | /// 执行命令 367 | /// 368 | /// 369 | private static void DoExitWindows(ExitWindows flag) 370 | { 371 | TokPriv1Luid tp; 372 | IntPtr hproc = Kernel32Base.GetCurrentProcess(); 373 | Advapi32Base.OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out IntPtr htok); 374 | tp.Count = 1; 375 | tp.Luid = 0; 376 | tp.Attr = SE_PRIVILEGE_ENABLED; 377 | Advapi32Base.LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid); 378 | Advapi32Base.AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); 379 | ExitWindowsEx(flag, ShutdownReason.MajorOther); 380 | } 381 | #endregion 382 | } 383 | } 384 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Winmm/WinmmBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Utils.WindowsApi 9 | { 10 | public class WinmmBase 11 | { 12 | private const string Winmm = "winmm.dll"; 13 | 14 | [DllImport(Winmm, EntryPoint = "waveOutSetVolume")] 15 | internal static extern int WaveOutSetVolume(IntPtr deviceID, uint Volume); 16 | [DllImport(Winmm, EntryPoint = "waveOutGetVolume")] 17 | internal static extern int WaveOutGetVolume(IntPtr deviceID, out uint Volume); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Winmm/WinmmExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Utils.WindowsApi 8 | { 9 | public class WinmmExtension:WinmmBase 10 | { 11 | private const uint iMaxValue = 0xFFFF; 12 | private const uint iMinValue = 0x0000; 13 | private static int iCurrentValue = 0; 14 | 15 | public static void SetSystemVolume(double arg) 16 | { 17 | double newVolume = ushort.MaxValue * arg / 10.0; 18 | 19 | uint v = ((uint)newVolume) & 0xffff; 20 | uint vAll = v | (v << 16); 21 | 22 | int retVal = WaveOutSetVolume(IntPtr.Zero, vAll); 23 | } 24 | 25 | private static void GetVolume() 26 | { 27 | //uint d, v; 28 | //d = 0; 29 | //long i = WaveOutGetVolume(d, out v); 30 | //uint vleft = v & 0xFFFF; 31 | //uint vright = (v & 0xFFFF0000) >> 16; 32 | //uint all = vleft | vright; 33 | //uint value = (all * uint.Parse((MaxValue - MinValue).ToString()) / ((UInt32)iMaxValue)); 34 | //iCurrentValue = int.Parse(value.ToString()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Wlanapi/WlanapiBase.Struct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.NetworkInformation; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Utils.WindowsApi 10 | { 11 | [StructLayout(LayoutKind.Sequential)] 12 | public struct WlanNotificationData 13 | { 14 | /// 15 | /// Specifies where the notification comes from. 16 | /// 17 | /// 18 | /// On Windows XP SP2, this field must be set to , 19 | /// or . 20 | /// 21 | public WlanNotificationSource NotificationSource; 22 | /// 23 | /// Indicates the type of notification. The value of this field indicates what type of associated data will be present in . 24 | /// 25 | public int NotificationCode; 26 | /// 27 | /// Indicates which interface the notification is for. 28 | /// 29 | public Guid InterfaceGuid; 30 | /// 31 | /// Specifies the size of , in bytes. 32 | /// 33 | public int DataSize; 34 | /// 35 | /// Pointer to additional data needed for the notification, as indicated by . 36 | /// 37 | public IntPtr DataPtr; 38 | 39 | /// 40 | /// Gets the notification code (in the correct enumeration type) according to the notification source. 41 | /// 42 | public object WlanNotificationCode 43 | { 44 | get 45 | { 46 | if (NotificationSource == WlanNotificationSource.WLAN_NOTIFICATION_SOURCE_MSM) 47 | return (WlanNotificationCodeMsm)NotificationCode; 48 | else if (NotificationSource == WlanNotificationSource.WLAN_NOTIFICATION_SOURCE_ACM) 49 | return (WlanNotificationCodeAcm)NotificationCode; 50 | else 51 | return NotificationCode; 52 | } 53 | 54 | } 55 | } 56 | 57 | /// 58 | /// Contains information about a LAN interface. 59 | /// 60 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 61 | public struct WlanInterfaceInfo 62 | { 63 | /// 64 | /// The GUID of the interface. 65 | /// 66 | public Guid InterfaceGuid; 67 | /// 68 | /// The description of the interface. 69 | /// 70 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 71 | public string InterfaceDescription; 72 | /// 73 | /// The current state of the interface. 74 | /// 75 | public WlanInterfaceState State; 76 | } 77 | 78 | /// 79 | /// Contains information about connection related notifications. 80 | /// 81 | /// 82 | /// Corresponds to the native WLAN_CONNECTION_NOTIFICATION_DATA type. 83 | /// 84 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 85 | public struct WlanConnectionNotificationData 86 | { 87 | /// 88 | /// On Windows XP SP 2, only is supported. 89 | /// 90 | public WlanConnectionMode WlanConnectionMode; 91 | /// 92 | /// The name of the profile used for the connection. Profile names are case-sensitive. 93 | /// 94 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 95 | public string ProfileName; 96 | /// 97 | /// The SSID of the association. 98 | /// 99 | public Dot11Ssid Dot11Ssid; 100 | /// 101 | /// The BSS network type. 102 | /// 103 | public Dot11BssType Dot11BssType; 104 | /// 105 | /// Indicates whether security is enabled for this connection. 106 | /// 107 | public bool SecurityEnabled; 108 | /// 109 | /// Indicates the reason for an operation failure. 110 | /// This field has a value of for all connection-related notifications except . 111 | /// If the connection fails, this field indicates the reason for the failure. 112 | /// 113 | public WlanReasonCode WlanReasonCode; 114 | /// 115 | /// This field contains the XML presentation of the profile used for discovery, if the connection succeeds. 116 | /// 117 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)] 118 | public string ProfileXml; 119 | } 120 | 121 | /// 122 | /// Contains the SSID of an interface. 123 | /// 124 | public struct Dot11Ssid 125 | { 126 | /// 127 | /// The length, in bytes, of the array. 128 | /// 129 | public uint SSIDLength; 130 | /// 131 | /// The SSID. 132 | /// 133 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 134 | public byte[] SSID; 135 | } 136 | 137 | /// 138 | /// Defines the security attributes for a wireless connection. 139 | /// 140 | /// 141 | /// Corresponds to the native WLAN_SECURITY_ATTRIBUTES type. 142 | /// 143 | [StructLayout(LayoutKind.Sequential)] 144 | public struct WlanSecurityAttributes 145 | { 146 | /// 147 | /// Indicates whether security is enabled for this connection. 148 | /// 149 | [MarshalAs(UnmanagedType.Bool)] 150 | public bool SecurityEnabled; 151 | [MarshalAs(UnmanagedType.Bool)] 152 | public bool OneXEnabled; 153 | /// 154 | /// The authentication algorithm. 155 | /// 156 | public Dot11AuthAlgorithm Dot11AuthAlgorithm; 157 | /// 158 | /// The cipher algorithm. 159 | /// 160 | public Dot11CipherAlgorithm Dot11CipherAlgorithm; 161 | } 162 | 163 | /// 164 | /// Defines the attributes of a wireless connection. 165 | /// 166 | /// 167 | /// Corresponds to the native WLAN_CONNECTION_ATTRIBUTES type. 168 | /// 169 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 170 | public struct WlanConnectionAttributes 171 | { 172 | /// 173 | /// The state of the interface. 174 | /// 175 | public WlanInterfaceState IsState; 176 | /// 177 | /// The mode of the connection. 178 | /// 179 | public WlanConnectionMode WlanConnectionMode; 180 | /// 181 | /// The name of the profile used for the connection. Profile names are case-sensitive. 182 | /// 183 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 184 | public string ProfileName; 185 | /// 186 | /// The attributes of the association. 187 | /// 188 | public WlanAssociationAttributes WlanAssociationAttributes; 189 | /// 190 | /// The security attributes of the connection. 191 | /// 192 | public WlanSecurityAttributes WlanSecurityAttributes; 193 | } 194 | 195 | /// 196 | /// Contains association attributes for a connection 197 | /// 198 | /// 199 | /// Corresponds to the native WLAN_ASSOCIATION_ATTRIBUTES type. 200 | /// 201 | [StructLayout(LayoutKind.Sequential)] 202 | public struct WlanAssociationAttributes 203 | { 204 | /// 205 | /// The SSID of the association. 206 | /// 207 | public Dot11Ssid Dot11Ssid; 208 | /// 209 | /// Specifies whether the network is infrastructure or ad hoc. 210 | /// 211 | public Dot11BssType Dot11BssType; 212 | /// 213 | /// The BSSID of the association. 214 | /// 215 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 216 | public byte[] Dot11Bssid; 217 | /// 218 | /// The physical type of the association. 219 | /// 220 | public Dot11PhyType Dot11PhyType; 221 | /// 222 | /// The position of the value in the structure containing the list of PHY types. 223 | /// 224 | public uint Dot11PhyIndex; 225 | /// 226 | /// A percentage value that represents the signal quality of the network. 227 | /// This field contains a value between 0 and 100. 228 | /// A value of 0 implies an actual RSSI signal strength of -100 dbm. 229 | /// A value of 100 implies an actual RSSI signal strength of -50 dbm. 230 | /// You can calculate the RSSI signal strength value for values between 1 and 99 using linear interpolation. 231 | /// 232 | public uint WlanSignalQuality; 233 | /// 234 | /// The receiving rate of the association. 235 | /// 236 | public uint RxRate; 237 | /// 238 | /// The transmission rate of the association. 239 | /// 240 | public uint TxRate; 241 | 242 | /// 243 | /// Gets the BSSID of the associated access point. 244 | /// 245 | /// The BSSID. 246 | public PhysicalAddress WlanDot11Bssid 247 | { 248 | get { return new PhysicalAddress(Dot11Bssid); } 249 | } 250 | } 251 | 252 | /// 253 | /// Specifies the parameters used when using the function. 254 | /// 255 | /// 256 | /// Corresponds to the native WLAN_CONNECTION_PARAMETERS type. 257 | /// 258 | [StructLayout(LayoutKind.Sequential)] 259 | public struct WlanConnectionParameters 260 | { 261 | /// 262 | /// Specifies the mode of connection. 263 | /// 264 | public WlanConnectionMode WlanConnectionMode; 265 | /// 266 | /// Specifies the profile being used for the connection. 267 | /// The contents of the field depend on the : 268 | /// 269 | /// 270 | /// Value of 271 | /// Contents of the profile string 272 | /// 273 | /// 274 | /// 275 | /// The name of the profile used for the connection. 276 | /// 277 | /// 278 | /// 279 | /// The XML representation of the profile used for the connection. 280 | /// 281 | /// 282 | /// , or 283 | /// null 284 | /// 285 | /// 286 | /// 287 | [MarshalAs(UnmanagedType.LPWStr)] 288 | public string Profile; 289 | /// 290 | /// Pointer to a structure that specifies the SSID of the network to connect to. 291 | /// This field is optional. When set to null, all SSIDs in the profile will be tried. 292 | /// This field must not be null if is set to or . 293 | /// 294 | public IntPtr Dot11SsidPtr; 295 | /// 296 | /// Pointer to a structure that contains the list of basic service set (BSS) identifiers desired for the connection. 297 | /// 298 | /// 299 | /// On Windows XP SP2, must be set to null. 300 | /// 301 | public IntPtr DesiredBssidListPtr; 302 | /// 303 | /// A value that indicates the BSS type of the network. If a profile is provided, this BSS type must be the same as the one in the profile. 304 | /// 305 | public Dot11BssType Dot11BssType; 306 | /// 307 | /// Specifies ocnnection parameters. 308 | /// 309 | /// 310 | /// On Windows XP SP2, must be set to 0. 311 | /// 312 | public WlanConnectionFlags Flags; 313 | } 314 | 315 | /// 316 | /// Contains basic information about a profile. 317 | /// 318 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 319 | public struct WlanProfileInfo 320 | { 321 | /// 322 | /// The name of the profile. This value may be the name of a domain if the profile is for provisioning. Profile names are case-sensitive. 323 | /// 324 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 325 | public string ProfileName; 326 | /// 327 | /// Profile flags. 328 | /// 329 | public WlanProfileFlags ProfileFlags; 330 | } 331 | 332 | /// 333 | /// The header of the list returned by . 334 | /// 335 | [StructLayout(LayoutKind.Sequential)] 336 | internal struct WlanProfileInfoListHeader 337 | { 338 | public uint NumberOfItems; 339 | public uint Index; 340 | } 341 | 342 | /// 343 | /// Contains information about an available wireless network. 344 | /// 345 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 346 | public struct WlanAvailableNetwork 347 | { 348 | /// 349 | /// Contains the profile name associated with the network. 350 | /// If the network doesn't have a profile, this member will be empty. 351 | /// If multiple profiles are associated with the network, there will be multiple entries with the same SSID in the visible network list. Profile names are case-sensitive. 352 | /// 353 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 354 | public string ProfileName; 355 | /// 356 | /// Contains the SSID of the visible wireless network. 357 | /// 358 | public Dot11Ssid Dot11Ssid; 359 | /// 360 | /// Specifies whether the network is infrastructure or ad hoc. 361 | /// 362 | public Dot11BssType Dot11BssType; 363 | /// 364 | /// Indicates the number of BSSIDs in the network. 365 | /// 366 | public uint NumberOfBssids; 367 | /// 368 | /// Indicates whether the network is connectable or not. 369 | /// 370 | public bool NetworkConnectable; 371 | /// 372 | /// Indicates why a network cannot be connected to. This member is only valid when is false. 373 | /// 374 | public WlanReasonCode WlanNotConnectableReason; 375 | /// 376 | /// The number of PHY types supported on available networks. 377 | /// The maximum value of this field is 8. If more than 8 PHY types are supported, must be set to true. 378 | /// 379 | private uint NumberOfPhyTypes; 380 | /// 381 | /// Contains an array of values that represent the PHY types supported by the available networks. 382 | /// When is greater than 8, this array contains only the first 8 PHY types. 383 | /// 384 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 385 | private Dot11PhyType[] Dot11PhyTypes; 386 | /// 387 | /// Gets the values that represent the PHY types supported by the available networks. 388 | /// 389 | public Dot11PhyType[] WlanDot11PhyTypes 390 | { 391 | get 392 | { 393 | Dot11PhyType[] ret = new Dot11PhyType[NumberOfPhyTypes]; 394 | Array.Copy(Dot11PhyTypes, ret, NumberOfPhyTypes); 395 | return ret; 396 | } 397 | } 398 | /// 399 | /// Specifies if there are more than 8 PHY types supported. 400 | /// When this member is set to true, an application must call to get the complete list of PHY types. 401 | /// contains the PHY type for an entry. 402 | /// 403 | public bool MorePhyTypes; 404 | /// 405 | /// A percentage value that represents the signal quality of the network. 406 | /// This field contains a value between 0 and 100. 407 | /// A value of 0 implies an actual RSSI signal strength of -100 dbm. 408 | /// A value of 100 implies an actual RSSI signal strength of -50 dbm. 409 | /// You can calculate the RSSI signal strength value for values between 1 and 99 using linear interpolation. 410 | /// 411 | public uint WlanSignalQuality; 412 | /// 413 | /// Indicates whether security is enabled on the network. 414 | /// 415 | public bool SecurityEnabled; 416 | /// 417 | /// Indicates the default authentication algorithm used to join this network for the first time. 418 | /// 419 | public Dot11AuthAlgorithm Dot11DefaultAuthAlgorithm; 420 | /// 421 | /// Indicates the default cipher algorithm to be used when joining this network. 422 | /// 423 | public Dot11CipherAlgorithm Dot11DefaultCipherAlgorithm; 424 | /// 425 | /// Contains various flags for the network. 426 | /// 427 | public WlanAvailableNetworkFlags Flags; 428 | /// 429 | /// Reserved for future use. Must be set to NULL. 430 | /// 431 | uint Reserved; 432 | 433 | public bool Equals(WlanAvailableNetwork network) 434 | { 435 | // Compares the two SSID byte arrays 436 | return this.Dot11Ssid.SSIDLength == network.Dot11Ssid.SSIDLength 437 | && this.Dot11Ssid.SSID.SequenceEqual(network.Dot11Ssid.SSID); 438 | } 439 | } 440 | 441 | /// 442 | /// The header of an array of information about available networks. 443 | /// 444 | [StructLayout(LayoutKind.Sequential)] 445 | internal struct WlanAvailableNetworkListHeader 446 | { 447 | /// 448 | /// Contains the number of items following the header. 449 | /// 450 | public uint NumberOfItems; 451 | /// 452 | /// The index of the current item. The index of the first item is 0. 453 | /// 454 | public uint Index; 455 | } 456 | 457 | /// 458 | /// Contains information about a basic service set (BSS). 459 | /// 460 | [StructLayout(LayoutKind.Sequential)] 461 | public struct WlanBssEntry 462 | { 463 | /// 464 | /// Contains the SSID of the access point (AP) associated with the BSS. 465 | /// 466 | public Dot11Ssid Dot11Ssid; 467 | /// 468 | /// The identifier of the PHY on which the AP is operating. 469 | /// 470 | public uint PhyId; 471 | /// 472 | /// Contains the BSS identifier. 473 | /// 474 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 475 | public byte[] Dot11Bssid; 476 | /// 477 | /// Specifies whether the network is infrastructure or ad hoc. 478 | /// 479 | public Dot11BssType Dot11BssType; 480 | public Dot11PhyType Dot11BssPhyType; 481 | /// 482 | /// The received signal strength in dBm. 483 | /// 484 | public int Rssi; 485 | /// 486 | /// The link quality reported by the driver. Ranges from 0-100. 487 | /// 488 | public uint LinkQuality; 489 | /// 490 | /// If 802.11d is not implemented, the network interface card (NIC) must set this field to TRUE. If 802.11d is implemented (but not necessarily enabled), the NIC must set this field to TRUE if the BSS operation complies with the configured regulatory domain. 491 | /// 492 | public bool InRegDomain; 493 | /// 494 | /// Contains the beacon interval value from the beacon packet or probe response. 495 | /// 496 | public ushort BeaconPeriod; 497 | /// 498 | /// The timestamp from the beacon packet or probe response. 499 | /// 500 | public ulong Timestamp; 501 | /// 502 | /// The host timestamp value when the beacon or probe response is received. 503 | /// 504 | public ulong HostTimestamp; 505 | /// 506 | /// The capability value from the beacon packet or probe response. 507 | /// 508 | public ushort CapabilityInformation; 509 | /// 510 | /// The frequency of the center channel, in kHz. 511 | /// 512 | public uint ChCenterFrequency; 513 | /// 514 | /// Contains the set of data transfer rates supported by the BSS. 515 | /// 516 | public WlanRateSet WlanRateSet; 517 | /// 518 | /// Offset of the information element (IE) data blob. 519 | /// 520 | public uint IeOffset; 521 | /// 522 | /// Size of the IE data blob, in bytes. 523 | /// 524 | public uint IeSize; 525 | } 526 | 527 | /// 528 | /// Contains the set of supported data rates. 529 | /// 530 | [StructLayout(LayoutKind.Sequential)] 531 | public struct WlanRateSet 532 | { 533 | /// 534 | /// The length, in bytes, of . 535 | /// 536 | private uint RateSetLength; 537 | /// 538 | /// An array of supported data transfer rates. 539 | /// If the rate is a basic rate, the first bit of the rate value is set to 1. 540 | /// A basic rate is the data transfer rate that all stations in a basic service set (BSS) can use to receive frames from the wireless medium. 541 | /// 542 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 126)] 543 | private ushort[] RateSet; 544 | 545 | public ushort[] Rates 546 | { 547 | get 548 | { 549 | ushort[] rates = new ushort[RateSetLength / sizeof(ushort)]; 550 | Array.Copy(RateSet, rates, rates.Length); 551 | return rates; 552 | } 553 | } 554 | 555 | /// 556 | /// CalculateS the data transfer rate in Mbps for an arbitrary supported rate. 557 | /// 558 | /// 559 | /// 560 | public double GetRateInMbps(int rate) 561 | { 562 | return (RateSet[rate] & 0x7FFF) * 0.5; 563 | } 564 | } 565 | 566 | [StructLayout(LayoutKind.Sequential)] 567 | internal struct WlanBssListHeader 568 | { 569 | internal uint TotalSize; 570 | internal uint NumberOfItems; 571 | } 572 | 573 | /// 574 | /// The header of the list returned by . 575 | /// 576 | [StructLayout(LayoutKind.Sequential)] 577 | internal struct WlanInterfaceInfoListHeader 578 | { 579 | public uint NumberOfItems; 580 | public uint Index; 581 | } 582 | } 583 | -------------------------------------------------------------------------------- /Utils/WindowsApi/Win32/Wlanapi/WlanapiBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Utils.WindowsApi 11 | { 12 | public partial class WlanapiBase 13 | { 14 | private const string Wlanapi = "Wlanapi.dll"; 15 | 16 | public const uint WLAN_CLIENT_VERSION_XP_SP2 = 1; 17 | public const uint WLAN_CLIENT_VERSION_LONGHORN = 2; 18 | 19 | /// 20 | /// Defines the callback function which accepts WLAN notifications. 21 | /// 22 | public delegate void WlanNotificationCallbackDelegate(ref WlanNotificationData notificationData, IntPtr context); 23 | 24 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanopenhandle 25 | [DllImport(Wlanapi)] 26 | public static extern int WlanOpenHandle( 27 | uint dwClientVersion, 28 | IntPtr pReserved, 29 | [Out] out uint pdwNegotiatedVersion, 30 | [Out] out IntPtr ClientHandle); 31 | 32 | //https://learn.microsoft.com/zh-cn/previous-versions/windows/embedded/gg159537(v=winembedded.80) 33 | [DllImport(Wlanapi)] 34 | public static extern int WlanRegisterNotification( 35 | IntPtr hClientHandle, 36 | WlanNotificationSource dwNotifSource, 37 | bool bIgnoreDuplicate, 38 | WlanNotificationCallbackDelegate funcCallback, 39 | IntPtr pCallbackContext, 40 | IntPtr pReserved, 41 | [Out] out WlanNotificationSource pdwPrevNotifSource); 42 | 43 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanclosehandle 44 | [DllImport(Wlanapi)] 45 | public static extern int WlanCloseHandle( 46 | [In] IntPtr hClientHandle, 47 | IntPtr pReserved); 48 | 49 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanqueryinterface 50 | [DllImport(Wlanapi)] 51 | public static extern int WlanQueryInterface( 52 | [In] IntPtr clientHandle, 53 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 54 | [In] WlanIntfOpcode opCode, 55 | [In, Out] IntPtr pReserved, 56 | [Out] out int dataSize, 57 | [Out] out IntPtr ppData, 58 | [Out] out WlanOpcodeValueType wlanOpcodeValueType); 59 | 60 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlansetinterface 61 | [DllImport(Wlanapi)] 62 | public static extern int WlanSetInterface( 63 | [In] IntPtr clientHandle, 64 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 65 | [In] WlanIntfOpcode opCode, 66 | [In] uint dataSize, 67 | [In] IntPtr pData, 68 | [In, Out] IntPtr pReserved); 69 | 70 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanscan 71 | /// Not supported on Windows XP SP2: must be a null reference. 72 | /// Not supported on Windows XP SP2: must be a null reference. 73 | [DllImport(Wlanapi)] 74 | public static extern int WlanScan( 75 | [In] IntPtr clientHandle, 76 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 77 | [In] IntPtr pDot11Ssid, 78 | [In] IntPtr pIeData, 79 | [In, Out] IntPtr pReserved); 80 | 81 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanconnect 82 | [DllImport(Wlanapi)] 83 | public static extern int WlanConnect( 84 | [In] IntPtr clientHandle, 85 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 86 | [In] ref WlanConnectionParameters connectionParameters, 87 | IntPtr pReserved); 88 | 89 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlandisconnect 90 | [DllImport(Wlanapi)] 91 | public static extern int WlanDisconnect( 92 | [In] IntPtr clientHandle, 93 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 94 | IntPtr pReserved); 95 | 96 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlangetprofile 97 | /// Not supported on Windows XP SP2: must be a null reference. 98 | [DllImport(Wlanapi)] 99 | public static extern int WlanGetProfile( 100 | [In] IntPtr clientHandle, 101 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 102 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName, 103 | [In] IntPtr pReserved, 104 | [Out] out IntPtr profileXml, 105 | [Out, Optional] out WlanProfileFlags flags, 106 | [Out, Optional] out WlanAccess grantedAccess); 107 | 108 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlangetprofilelist 109 | [DllImport(Wlanapi)] 110 | public static extern int WlanGetProfileList( 111 | [In] IntPtr clientHandle, 112 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 113 | [In] IntPtr pReserved, 114 | [Out] out IntPtr profileList 115 | ); 116 | 117 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlangetavailablenetworklist 118 | [DllImport(Wlanapi)] 119 | public static extern int WlanGetAvailableNetworkList( 120 | [In] IntPtr clientHandle, 121 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 122 | [In] WlanGetAvailableNetworkFlags flags, 123 | [In, Out] IntPtr reservedPtr, 124 | [Out] out IntPtr availableNetworkListPtr); 125 | 126 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlangetnetworkbsslist 127 | [DllImport(Wlanapi)] 128 | public static extern int WlanGetNetworkBssList( 129 | [In] IntPtr clientHandle, 130 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 131 | [In] IntPtr dot11SsidInt, 132 | [In] Dot11BssType dot11BssType, 133 | [In] bool securityEnabled, 134 | IntPtr reservedPtr, 135 | [Out] out IntPtr wlanBssList 136 | ); 137 | 138 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlansetprofile 139 | [DllImport(Wlanapi)] 140 | public static extern int WlanSetProfile( 141 | [In] IntPtr clientHandle, 142 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 143 | [In] WlanProfileFlags flags, 144 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileXml, 145 | [In, Optional, MarshalAs(UnmanagedType.LPWStr)] string allUserProfileSecurity, 146 | [In] bool overwrite, 147 | [In] IntPtr pReserved, 148 | [Out] out WlanReasonCode reasonCode); 149 | 150 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlandeleteprofile 151 | [DllImport(Wlanapi)] 152 | public static extern int WlanDeleteProfile( 153 | [In] IntPtr clientHandle, 154 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 155 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName, 156 | IntPtr reservedPtr 157 | ); 158 | 159 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlansetprofileeapxmluserdata 160 | [DllImport(Wlanapi)] 161 | public static extern int WlanSetProfileEapXmlUserData( 162 | // The client's session handle, obtained by a previous call to the WlanOpenHandle function. 163 | // 客户端的会话句柄,通过先前对WlanOpenHandle函数的调用获得。 164 | [In] IntPtr clientHandle, 165 | // The GUID of the interface. 166 | // 接口的GUID。 167 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, 168 | // The name of the profile associated with the EAP user data. 169 | // 与EAP用户数据关联的配置文件的名称。 170 | // Profile names are case-sensitive. This string must be NULL-terminated. 171 | // 配置文件名称区分大小写。此字符串必须以NULL结尾。 172 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName, 173 | // A set of flags that modify the behavior of the function. 174 | [In] SetEapUserDataMode dwFlags, 175 | // A pointer to XML data used to set the user credentials, 176 | // 指向用于设置用户凭证的XML数据的指针, 177 | // The XML data must be based on the EAPHost User Credentials schema. To view sample user credential XML data, 178 | // XML数据必须基于EAPHost用户凭据架构。要查看示例用户凭证XML数据, 179 | // see EAPHost User Properties: http://msdn.microsoft.com/en-us/library/windows/desktop/bb204765(v=vs.85).aspx 180 | [In, MarshalAs(UnmanagedType.LPWStr)] string userDataXML, 181 | IntPtr reservedPtr 182 | ); 183 | 184 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanreasoncodetostring 185 | [DllImport(Wlanapi)] 186 | public static extern int WlanReasonCodeToString( 187 | [In] WlanReasonCode reasonCode, 188 | [In] int bufferSize, 189 | [In, Out] StringBuilder stringBuffer, 190 | IntPtr pReserved 191 | ); 192 | 193 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanenuminterfaces 194 | [DllImport(Wlanapi)] 195 | public static extern int WlanEnumInterfaces( 196 | [In] IntPtr clientHandle, 197 | [In, Out] IntPtr pReserved, 198 | [Out] out IntPtr ppInterfaceList); 199 | 200 | //https://learn.microsoft.com/zh-cn/windows/win32/api/wlanapi/nf-wlanapi-wlanfreememory 201 | [DllImport(Wlanapi)] 202 | public static extern void WlanFreeMemory(IntPtr pMemory); 203 | 204 | /// 205 | /// Helper method to wrap calls to Native WiFi API methods. 206 | /// If the method falls, throws an exception containing the error code. 207 | /// 208 | /// The error code. 209 | [DebuggerStepThrough] 210 | internal static void ThrowIfError(int win32ErrorCode) 211 | { 212 | if (win32ErrorCode != 0) 213 | throw new Win32Exception(win32ErrorCode); 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /UtilsDemo/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /UtilsDemo/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UtilsDemo 8 | { 9 | internal class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UtilsDemo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("UtilsDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UtilsDemo")] 13 | [assembly: AssemblyCopyright("Copyright © 2024")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("6a1b5e4b-0650-4e1f-ab48-2deafe40d6e8")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /UtilsDemo/UtilsDemo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6A1B5E4B-0650-4E1F-AB48-2DEAFE40D6E8} 8 | Exe 9 | UtilsDemo 10 | UtilsDemo 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {52b9c6b5-da34-4b13-a2ba-5a13f97d0386} 56 | Utils 57 | 58 | 59 | 60 | --------------------------------------------------------------------------------