├── .gitignore
├── AdvancedInstaller
├── .gitignore
├── wu10man.aip
├── wu10man.back (1).aip
└── wu10man.back.aip
├── CreatePortable.ps1
├── LICENSE
├── README.md
├── WereDev.Utils.Win32Wrappers
├── FileAccessBridge.cs
├── Models
│ └── ServiceConfigInfo.cs
├── Properties
│ └── AssemblyInfo.cs
├── WereDev.Utils.Win32Wrappers.csproj
├── WindowsApiBridge.cs
└── WindowsServiceBridge.cs
├── WereDev.Utils.Wu10Man.Core
├── DependencyManager.cs
├── Enums
│ ├── ServiceStartMode.cs
│ └── WindowsApiPrivelegeNames.cs
├── Exceptions
│ └── EntityNotFoundException.cs
├── Interfaces
│ ├── IFileManager.cs
│ ├── IHostsFileEditor.cs
│ ├── ILogWriter.cs
│ ├── IRegistryEditor.cs
│ ├── IWindowsPackageManager.cs
│ ├── IWindowsServiceManager.cs
│ ├── IWindowsTaskManager.cs
│ └── Providers
│ │ ├── ICredentialsProvider.cs
│ │ ├── IFileIoProvider.cs
│ │ ├── IRegistryProvider.cs
│ │ ├── IUserProvider.cs
│ │ ├── IWindowsApiProvider.cs
│ │ ├── IWindowsPackageProvider.cs
│ │ ├── IWindowsServiceProvider.cs
│ │ ├── IWindowsServiceProviderFactory.cs
│ │ └── IWindowsTaskProvider.cs
├── Models
│ ├── AppInfo.cs
│ ├── AppInfoExtended.cs
│ ├── DeclutterConfig.cs
│ ├── PackageInfo.cs
│ ├── SplitHostsFile.cs
│ ├── WindowsTask.cs
│ └── WindowsTaskConfig.cs
├── Properties
│ └── AssemblyInfo.cs
├── Services
│ ├── FileManager.cs
│ ├── HostsFileEditor.cs
│ ├── RegistryEditor.cs
│ ├── WindowsPackageManager.cs
│ ├── WindowsServiceManager.cs
│ └── WindowsTaskManager.cs
├── WereDev.Utils.Wu10Man.Core.csproj
├── app.config
└── packages.config
├── WereDev.Utils.Wu10Man.Providers
├── CredentialsProvider.cs
├── FileIoProvider.cs
├── PowerShellProvider.cs
├── Properties
│ └── AssemblyInfo.cs
├── RegistryProvider.cs
├── UserProvider.cs
├── WereDev.Utils.Wu10Man.Providers.csproj
├── WindowsApiProvider.cs
├── WindowsServiceProvider.cs
├── WindowsServiceProviderFactory.cs
├── WindowsTaskProvider.cs
├── app.config
└── packages.config
├── Wu10Man.sln
├── Wu10Man
├── App.xaml
├── App.xaml.cs
├── AppSettings.cs
├── Converters
│ └── MathConverter.cs
├── CustomDictionary.xml
├── Properties
│ └── AssemblyInfo.cs
├── Services
│ ├── EnvironmentVersionHelper.cs
│ └── Wu10Logger.cs
├── UserControls
│ ├── DeclutterControl.xaml
│ ├── DeclutterControl.xaml.cs
│ ├── GroupPolicyControl.xaml
│ ├── GroupPolicyControl.xaml.cs
│ ├── HostsFileControl.xaml
│ ├── HostsFileControl.xaml.cs
│ ├── Models
│ │ ├── DeclutterModel.cs
│ │ ├── HostStatus.cs
│ │ ├── HostsFileModel.cs
│ │ ├── ModelBase.cs
│ │ ├── PackageInfo.cs
│ │ ├── PauseUpdatesModel.cs
│ │ ├── ProgressBarModel.cs
│ │ ├── WindowsServiceStatusModel.cs
│ │ ├── WindowsServicesModel.cs
│ │ ├── WindowsTasksModel.cs
│ │ └── WindowsTasksStatusModel.cs
│ ├── PauseUpdatesControl.xaml
│ ├── PauseUpdatesControl.xaml.cs
│ ├── ProgressBarControl.xaml
│ ├── ProgressBarControl.xaml.cs
│ ├── UserControlBase.cs
│ ├── UserControlBaseWithWorker.cs
│ ├── WindowsServicesControl.xaml
│ ├── WindowsServicesControl.xaml.cs
│ ├── WindowsTasksControl.xaml
│ └── WindowsTasksControl.xaml.cs
├── UserWindows
│ ├── About.xaml
│ ├── About.xaml.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ └── Models
│ │ ├── ITabItemModel.cs
│ │ ├── MainWindowModel.cs
│ │ └── TabItemModel.cs
├── Wu10Man.csproj
├── app.manifest
├── app.settings.json
├── nlog.config
├── packages.config
├── question.png
├── warning.png
└── wu10man.ico
├── stylecop.json
└── stylecop.ruleset
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 | [Pp]ublish/
27 |
28 | # Visual Studio 2015/2017 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # Visual Studio 2017 auto generated files
34 | Generated\ Files/
35 |
36 | # MSTest test Results
37 | [Tt]est[Rr]esult*/
38 | [Bb]uild[Ll]og.*
39 |
40 | # NUNIT
41 | *.VisualState.xml
42 | TestResult.xml
43 |
44 | # Build Results of an ATL Project
45 | [Dd]ebugPS/
46 | [Rr]eleasePS/
47 | dlldata.c
48 |
49 | # Benchmark Results
50 | BenchmarkDotNet.Artifacts/
51 |
52 | # .NET Core
53 | project.lock.json
54 | project.fragment.lock.json
55 | artifacts/
56 | **/Properties/launchSettings.json
57 |
58 | # StyleCop
59 | StyleCopReport.xml
60 |
61 | # Files built by Visual Studio
62 | *_i.c
63 | *_p.c
64 | *_i.h
65 | *.ilk
66 | *.meta
67 | *.obj
68 | *.iobj
69 | *.pch
70 | *.pdb
71 | *.ipdb
72 | *.pgc
73 | *.pgd
74 | *.rsp
75 | *.sbr
76 | *.tlb
77 | *.tli
78 | *.tlh
79 | *.tmp
80 | *.tmp_proj
81 | *.log
82 | *.vspscc
83 | *.vssscc
84 | .builds
85 | *.pidb
86 | *.svclog
87 | *.scc
88 |
89 | # Chutzpah Test files
90 | _Chutzpah*
91 |
92 | # Visual C++ cache files
93 | ipch/
94 | *.aps
95 | *.ncb
96 | *.opendb
97 | *.opensdf
98 | *.sdf
99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 |
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 |
109 | # Visual Studio Trace Files
110 | *.e2e
111 |
112 | # TFS 2012 Local Workspace
113 | $tf/
114 |
115 | # Guidance Automation Toolkit
116 | *.gpState
117 |
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 |
123 | # JustCode is a .NET coding add-in
124 | .JustCode
125 |
126 | # TeamCity is a build add-in
127 | _TeamCity*
128 |
129 | # DotCover is a Code Coverage Tool
130 | *.dotCover
131 |
132 | # AxoCover is a Code Coverage Tool
133 | .axoCover/*
134 | !.axoCover/settings.json
135 |
136 | # Visual Studio code coverage results
137 | *.coverage
138 | *.coveragexml
139 |
140 | # NCrunch
141 | _NCrunch_*
142 | .*crunch*.local.xml
143 | nCrunchTemp_*
144 |
145 | # MightyMoose
146 | *.mm.*
147 | AutoTest.Net/
148 |
149 | # Web workbench (sass)
150 | .sass-cache/
151 |
152 | # Installshield output folder
153 | [Ee]xpress/
154 |
155 | # DocProject is a documentation generator add-in
156 | DocProject/buildhelp/
157 | DocProject/Help/*.HxT
158 | DocProject/Help/*.HxC
159 | DocProject/Help/*.hhc
160 | DocProject/Help/*.hhk
161 | DocProject/Help/*.hhp
162 | DocProject/Help/Html2
163 | DocProject/Help/html
164 |
165 | # Click-Once directory
166 | publish/
167 |
168 | # Publish Web Output
169 | *.[Pp]ublish.xml
170 | *.azurePubxml
171 | # Note: Comment the next line if you want to checkin your web deploy settings,
172 | # but database connection strings (with potential passwords) will be unencrypted
173 | *.pubxml
174 | *.publishproj
175 |
176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
177 | # checkin your Azure Web App publish settings, but sensitive information contained
178 | # in these scripts will be unencrypted
179 | PublishScripts/
180 |
181 | # NuGet Packages
182 | *.nupkg
183 | # The packages folder can be ignored because of Package Restore
184 | **/[Pp]ackages/*
185 | # except build/, which is used as an MSBuild target.
186 | !**/[Pp]ackages/build/
187 | # Uncomment if necessary however generally it will be regenerated when needed
188 | #!**/[Pp]ackages/repositories.config
189 | # NuGet v3's project.json files produces more ignorable files
190 | *.nuget.props
191 | *.nuget.targets
192 |
193 | # Microsoft Azure Build Output
194 | csx/
195 | *.build.csdef
196 |
197 | # Microsoft Azure Emulator
198 | ecf/
199 | rcf/
200 |
201 | # Windows Store app package directories and files
202 | AppPackages/
203 | BundleArtifacts/
204 | Package.StoreAssociation.xml
205 | _pkginfo.txt
206 | *.appx
207 |
208 | # Visual Studio cache files
209 | # files ending in .cache can be ignored
210 | *.[Cc]ache
211 | # but keep track of directories ending in .cache
212 | !*.[Cc]ache/
213 |
214 | # Others
215 | ClientBin/
216 | ~$*
217 | *~
218 | *.dbmdl
219 | *.dbproj.schemaview
220 | *.jfm
221 | *.pfx
222 | *.publishsettings
223 | orleans.codegen.cs
224 |
225 | # Including strong name files can present a security risk
226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
227 | #*.snk
228 |
229 | # Since there are multiple workflows, uncomment next line to ignore bower_components
230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
231 | #bower_components/
232 |
233 | # RIA/Silverlight projects
234 | Generated_Code/
235 |
236 | # Backup & report files from converting an old project file
237 | # to a newer Visual Studio version. Backup files are not needed,
238 | # because we have git ;-)
239 | _UpgradeReport_Files/
240 | Backup*/
241 | UpgradeLog*.XML
242 | UpgradeLog*.htm
243 | ServiceFabricBackup/
244 | *.rptproj.bak
245 |
246 | # SQL Server files
247 | *.mdf
248 | *.ldf
249 | *.ndf
250 |
251 | # Business Intelligence projects
252 | *.rdl.data
253 | *.bim.layout
254 | *.bim_*.settings
255 | *.rptproj.rsuser
256 |
257 | # Microsoft Fakes
258 | FakesAssemblies/
259 |
260 | # GhostDoc plugin setting file
261 | *.GhostDoc.xml
262 |
263 | # Node.js Tools for Visual Studio
264 | .ntvs_analysis.dat
265 | node_modules/
266 |
267 | # Visual Studio 6 build log
268 | *.plg
269 |
270 | # Visual Studio 6 workspace options file
271 | *.opt
272 |
273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
274 | *.vbw
275 |
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 |
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 |
288 | # FAKE - F# Make
289 | .fake/
290 |
291 | # JetBrains Rider
292 | .idea/
293 | *.sln.iml
294 |
295 | # CodeRush
296 | .cr/
297 |
298 | # Python Tools for Visual Studio (PTVS)
299 | __pycache__/
300 | *.pyc
301 |
302 | # Cake - Uncomment if you are using it
303 | # tools/**
304 | # !tools/packages.config
305 |
306 | # Tabs Studio
307 | *.tss
308 |
309 | # Telerik's JustMock configuration file
310 | *.jmconfig
311 |
312 | # BizTalk build output
313 | *.btp.cs
314 | *.btm.cs
315 | *.odx.cs
316 | *.xsd.cs
317 |
318 | # OpenCover UI analysis results
319 | OpenCover/
320 |
321 | # Azure Stream Analytics local run output
322 | ASALocalRun/
323 |
324 | # MSBuild Binary and Structured Log
325 | *.binlog
326 |
327 | # NVidia Nsight GPU debugger configuration file
328 | *.nvuser
329 |
330 | # MFractors (Xamarin productivity tool) working folder
331 | .mfractor/
332 | /packages/
333 |
--------------------------------------------------------------------------------
/AdvancedInstaller/.gitignore:
--------------------------------------------------------------------------------
1 | /wu10man-cache/
2 |
--------------------------------------------------------------------------------
/CreatePortable.ps1:
--------------------------------------------------------------------------------
1 | $compress = @{
2 | Path = "Wu10Man\bin\Release\Wu10Man.exe",
3 | "Wu10Man\bin\Release\app.settings.json",
4 | "Wu10Man\bin\Release\nlog.config",
5 | "Wu10Man\bin\Release\*.dll"
6 | CompressionLevel = "Optimal"
7 | DestinationPath = "Publish\Wu10Man_Portable.zip"
8 | }
9 | Compress-Archive @compress -Force
--------------------------------------------------------------------------------
/WereDev.Utils.Win32Wrappers/FileAccessBridge.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Runtime.InteropServices;
5 |
6 | // https://stackoverflow.com/questions/1304/how-to-check-for-file-lock#3202085
7 | namespace WereDev.Utils.Win32Wrappers
8 | {
9 | public static class FileAccessBridge
10 | {
11 | [StructLayout(LayoutKind.Sequential)]
12 | struct RM_UNIQUE_PROCESS
13 | {
14 | public int dwProcessId;
15 | public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
16 | }
17 |
18 | const int RmRebootReasonNone = 0;
19 | const int CCH_RM_MAX_APP_NAME = 255;
20 | const int CCH_RM_MAX_SVC_NAME = 63;
21 |
22 | enum RM_APP_TYPE
23 | {
24 | RmUnknownApp = 0,
25 | RmMainWindow = 1,
26 | RmOtherWindow = 2,
27 | RmService = 3,
28 | RmExplorer = 4,
29 | RmConsole = 5,
30 | RmCritical = 1000
31 | }
32 |
33 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
34 | struct RM_PROCESS_INFO
35 | {
36 | public RM_UNIQUE_PROCESS Process;
37 |
38 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
39 | public string strAppName;
40 |
41 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
42 | public string strServiceShortName;
43 |
44 | public RM_APP_TYPE ApplicationType;
45 | public uint AppStatus;
46 | public uint TSSessionId;
47 | [MarshalAs(UnmanagedType.Bool)]
48 | public bool bRestartable;
49 | }
50 |
51 | [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
52 | static extern int RmRegisterResources(uint pSessionHandle,
53 | UInt32 nFiles,
54 | string[] rgsFilenames,
55 | UInt32 nApplications,
56 | [In] RM_UNIQUE_PROCESS[] rgApplications,
57 | UInt32 nServices,
58 | string[] rgsServiceNames);
59 |
60 | [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
61 | static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
62 |
63 | [DllImport("rstrtmgr.dll")]
64 | static extern int RmEndSession(uint pSessionHandle);
65 |
66 | [DllImport("rstrtmgr.dll")]
67 | static extern int RmGetList(uint dwSessionHandle,
68 | out uint pnProcInfoNeeded,
69 | ref uint pnProcInfo,
70 | [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
71 | ref uint lpdwRebootReasons);
72 |
73 | ///
74 | /// Find out what process(es) have a lock on the specified file.
75 | ///
76 | /// Path of the file.
77 | /// Processes locking the file
78 | /// See also:
79 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx
80 | /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
81 | ///
82 | ///
83 | public static List WhoIsLocking(string path)
84 | {
85 | string key = Guid.NewGuid().ToString();
86 | List processes = new List();
87 |
88 | int res = RmStartSession(out uint handle, 0, key);
89 |
90 | if (res != 0)
91 | throw new Exception("Could not begin restart session. Unable to determine file locker.");
92 |
93 | try
94 | {
95 | const int ERROR_MORE_DATA = 234;
96 | uint pnProcInfo = 0,
97 | lpdwRebootReasons = RmRebootReasonNone;
98 |
99 | string[] resources = new string[] { path }; // Just checking on one resource.
100 |
101 | res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
102 |
103 | if (res != 0)
104 | throw new Exception("Could not register resource.");
105 |
106 | //Note: there's a race condition here -- the first call to RmGetList() returns
107 | // the total number of process. However, when we call RmGetList() again to get
108 | // the actual processes this number may have increased.
109 | res = RmGetList(handle, out uint pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
110 |
111 | if (res == ERROR_MORE_DATA)
112 | {
113 | // Create an array to store the process results
114 | RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
115 | pnProcInfo = pnProcInfoNeeded;
116 |
117 | // Get the list
118 | res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
119 |
120 | if (res == 0)
121 | {
122 | processes = new List((int)pnProcInfo);
123 |
124 | // Enumerate all of the results and add them to the
125 | // list to be returned
126 | for (int i = 0; i < pnProcInfo; i++)
127 | {
128 | try
129 | {
130 | processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
131 | }
132 | // catch the error -- in case the process is no longer running
133 | catch (ArgumentException) { }
134 | }
135 | }
136 | else
137 | throw new Exception("Could not list processes locking resource.");
138 | }
139 | else if (res != 0)
140 | throw new Exception("Could not list processes locking resource. Failed to get size of result.");
141 | }
142 | finally
143 | {
144 | RmEndSession(handle);
145 | }
146 |
147 | return processes;
148 | }
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/WereDev.Utils.Win32Wrappers/Models/ServiceConfigInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | namespace WereDev.Utils.Win32Wrappers.Models
4 | {
5 | [StructLayout(LayoutKind.Sequential)]
6 | public class ServiceConfigInfo
7 | {
8 | [MarshalAs(UnmanagedType.U4)]
9 | public uint ServiceType;
10 | [MarshalAs(UnmanagedType.U4)]
11 | public uint StartType;
12 | [MarshalAs(UnmanagedType.U4)]
13 | public uint ErrorControl;
14 | [MarshalAs(UnmanagedType.LPWStr)]
15 | public string BinaryPathName;
16 | [MarshalAs(UnmanagedType.LPWStr)]
17 | public string LoadOrderGroup;
18 | [MarshalAs(UnmanagedType.U4)]
19 | public uint TagID;
20 | [MarshalAs(UnmanagedType.LPWStr)]
21 | public string Dependencies;
22 | [MarshalAs(UnmanagedType.LPWStr)]
23 | public string ServiceStartName;
24 | [MarshalAs(UnmanagedType.LPWStr)]
25 | public string DisplayName;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/WereDev.Utils.Win32Wrappers/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("WereDev.Utils.Win32Wrappers")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("WereDev")]
11 | [assembly: AssemblyProduct("WereDev.Utils.Win32Wrappers")]
12 | [assembly: AssemblyCopyright("Copyright © 2018-2022")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("11e7c6da-6d2c-4ffd-9b2b-80646fdf9500")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/WereDev.Utils.Win32Wrappers/WereDev.Utils.Win32Wrappers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {11E7C6DA-6D2C-4FFD-9B2B-80646FDF9500}
8 | Library
9 | Properties
10 | WereDev.Utils.Win32Wrappers
11 | WereDev.Utils.Win32Wrappers
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 | SecurityRules.ruleset
27 |
28 |
29 | none
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | false
36 |
37 |
38 |
39 |
40 | true
41 |
42 |
43 | wu10man-snk.pfx
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/WereDev.Utils.Win32Wrappers/WindowsApiBridge.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Principal;
5 |
6 | // https://stackoverflow.com/questions/17031552/how-do-you-take-file-ownership-with-powershell/17047190#17047190
7 | namespace WereDev.Utils.Win32Wrappers
8 | {
9 | public static class WindowsApiBridge
10 | {
11 | private const uint SE_PRIVILEGE_ENABLED = 2;
12 |
13 | ///
14 | /// Enables or disables the specified privilege on the primary access token of the current process.
15 | ///
16 | /// Privilege to enable or disable.
17 | ///
18 | /// True to enable the privilege, false to disable it.
19 | ///
20 | /// True if the privilege was enabled prior to the change, false if it was disabled.
21 | public static bool ModifyPrivilege(PrivilegeName privilege, bool enable)
22 | {
23 | if (!LookupPrivilegeValue(null, privilege.ToString(), out Luid luid))
24 | throw new Win32Exception();
25 |
26 | using (var identity = WindowsIdentity.GetCurrent(TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query))
27 | {
28 | var newPriv = new TokenPrivileges
29 | {
30 | Privileges = new LuidAndAttributes[]
31 | {
32 | new LuidAndAttributes {
33 | Luid = luid,
34 | Attributes = enable ? SE_PRIVILEGE_ENABLED : 0
35 | }
36 | },
37 | PrivilegeCount = 1
38 | };
39 |
40 | var prevPriv = new TokenPrivileges
41 | {
42 | Privileges = new LuidAndAttributes[1],
43 | PrivilegeCount = 1
44 | };
45 |
46 | if (!AdjustTokenPrivileges(identity.Token, false, ref newPriv, (uint)Marshal.SizeOf(prevPriv), ref prevPriv, out uint returnedBytes))
47 | throw new Win32Exception();
48 |
49 | return prevPriv.PrivilegeCount == 0 ? enable /* didn't make a change */ : ((prevPriv.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) != 0);
50 | }
51 | }
52 |
53 | [DllImport("advapi32.dll", SetLastError = true)]
54 | [return: MarshalAs(UnmanagedType.Bool)]
55 | private extern static bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, ref TokenPrivileges NewState,
56 | UInt32 BufferLengthInBytes, ref TokenPrivileges PreviousState, out UInt32 ReturnLengthInBytes);
57 |
58 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
59 | [return: MarshalAs(UnmanagedType.Bool)]
60 | private extern static bool LookupPrivilegeValue(string lpSystemName, string lpName, out Luid lpLuid);
61 |
62 | private struct TokenPrivileges
63 | {
64 | public UInt32 PrivilegeCount;
65 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1 /*ANYSIZE_ARRAY*/)]
66 | public LuidAndAttributes[] Privileges;
67 | }
68 |
69 | [StructLayout(LayoutKind.Sequential)]
70 | private struct LuidAndAttributes
71 | {
72 | public Luid Luid;
73 | public UInt32 Attributes;
74 | }
75 |
76 | [StructLayout(LayoutKind.Sequential)]
77 | private struct Luid
78 | {
79 | public uint LowPart;
80 | public int HighPart;
81 | }
82 | }
83 |
84 | public enum PrivilegeName
85 | {
86 | SeAssignPrimaryTokenPrivilege,
87 | SeAuditPrivilege,
88 | SeBackupPrivilege,
89 | SeChangeNotifyPrivilege,
90 | SeCreateGlobalPrivilege,
91 | SeCreatePagefilePrivilege,
92 | SeCreatePermanentPrivilege,
93 | SeCreateSymbolicLinkPrivilege,
94 | SeCreateTokenPrivilege,
95 | SeDebugPrivilege,
96 | SeEnableDelegationPrivilege,
97 | SeImpersonatePrivilege,
98 | SeIncreaseBasePriorityPrivilege,
99 | SeIncreaseQuotaPrivilege,
100 | SeIncreaseWorkingSetPrivilege,
101 | SeLoadDriverPrivilege,
102 | SeLockMemoryPrivilege,
103 | SeMachineAccountPrivilege,
104 | SeManageVolumePrivilege,
105 | SeProfileSingleProcessPrivilege,
106 | SeRelabelPrivilege,
107 | SeRemoteShutdownPrivilege,
108 | SeRestorePrivilege,
109 | SeSecurityPrivilege,
110 | SeShutdownPrivilege,
111 | SeSyncAgentPrivilege,
112 | SeSystemEnvironmentPrivilege,
113 | SeSystemProfilePrivilege,
114 | SeSystemtimePrivilege,
115 | SeTakeOwnershipPrivilege,
116 | SeTcbPrivilege,
117 | SeTimeZonePrivilege,
118 | SeTrustedCredManAccessPrivilege,
119 | SeUndockPrivilege,
120 | SeUnsolicitedInputPrivilege,
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/WereDev.Utils.Win32Wrappers/WindowsServiceBridge.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WereDev.Utils.Win32Wrappers
5 | {
6 | public static class WindowsServiceBridge
7 | {
8 | public const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;
9 | public const uint SC_MANAGER_QUERY_ACESS = 0x10000000;
10 | public const uint SERVICE_NO_CHANGE = 0xffffffff; //this value is found in winsvc.h
11 | public const uint SERVICE_QUERY_CONFIG = 0x00000001;
12 | public const uint SERVICE_CHANGE_CONFIG = 0x00000002;
13 | public const uint SERVICE_QUERY_STATUS = 0x00000004;
14 | public const uint SERVICE_ENUMERATE_DEPENDENTS = 0x00000008;
15 | public const uint SERVICE_START = 0x00000010;
16 | public const uint SERVICE_STOP = 0x00000020;
17 | public const uint SERVICE_PAUSE_CONTINUE = 0x00000040;
18 | public const uint SERVICE_INTERROGATE = 0x00000080;
19 | public const uint SERVICE_USER_DEFINED_CONTROL = 0x00000100;
20 | public const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
21 | public const uint SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
22 | SERVICE_CHANGE_CONFIG |
23 | SERVICE_QUERY_STATUS |
24 | SERVICE_ENUMERATE_DEPENDENTS |
25 | SERVICE_START |
26 | SERVICE_STOP |
27 | SERVICE_PAUSE_CONTINUE |
28 | SERVICE_INTERROGATE |
29 | SERVICE_USER_DEFINED_CONTROL);
30 |
31 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
32 | [return: MarshalAs(UnmanagedType.Bool)]
33 | public static extern bool ChangeServiceConfig(IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, String lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName);
34 |
35 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
36 | public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
37 |
38 | [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
39 | public static extern IntPtr OpenSCManager(
40 | string machineName,
41 | string databaseName,
42 | uint dwAccess);
43 |
44 | [DllImport("advapi32.dll", SetLastError = true)]
45 | [return: MarshalAs(UnmanagedType.Bool)]
46 | public static extern bool CloseServiceHandle(IntPtr hSCObject);
47 |
48 | [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
49 | public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/DependencyManager.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Interfaces;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core
4 | {
5 | public static class DependencyManager
6 | {
7 | public static ILogWriter LogWriter { get; set; }
8 |
9 | public static IFileManager FileManager { get; set; }
10 |
11 | public static IRegistryEditor RegistryEditor { get; set; }
12 |
13 | public static IWindowsPackageManager WindowsPackageManager { get; set; }
14 |
15 | public static IHostsFileEditor HostsFileEditor { get; set; }
16 |
17 | public static IWindowsServiceManager WindowsServiceManager { get; set; }
18 |
19 | public static IWindowsTaskManager WindowsTaskManager { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Enums/ServiceStartMode.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Enums
2 | {
3 | public enum ServiceStartMode
4 | {
5 | // Summary:
6 | // Indicates that the service is a device driver started by the system loader. This
7 | // value is valid only for device drivers.
8 | Boot = 0,
9 |
10 | // Summary:
11 | // Indicates that the service is a device driver started by the IOInitSystem function.
12 | // This value is valid only for device drivers.
13 | System = 1,
14 |
15 | // Summary:
16 | // Indicates that the service is to be started (or was started) by the operating
17 | // system, at system start-up. If an automatically started service depends on a
18 | // manually started service, the manually started service is also started automatically
19 | // at system startup.
20 | Automatic = 2,
21 |
22 | // Summary:
23 | // Indicates that the service is started only manually, by a user (using the Service
24 | // Control Manager) or by an application.
25 | Manual = 3,
26 |
27 | // Summary:
28 | // Indicates that the service is disabled, so that it cannot be started by a user
29 | // or application.
30 | Disabled = 4,
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Enums/WindowsApiPrivelegeNames.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Enums
2 | {
3 | public enum WindowsApiPrivelegeNames
4 | {
5 | SeAssignPrimaryTokenPrivilege,
6 | SeAuditPrivilege,
7 | SeBackupPrivilege,
8 | SeChangeNotifyPrivilege,
9 | SeCreateGlobalPrivilege,
10 | SeCreatePagefilePrivilege,
11 | SeCreatePermanentPrivilege,
12 | SeCreateSymbolicLinkPrivilege,
13 | SeCreateTokenPrivilege,
14 | SeDebugPrivilege,
15 | SeEnableDelegationPrivilege,
16 | SeImpersonatePrivilege,
17 | SeIncreaseBasePriorityPrivilege,
18 | SeIncreaseQuotaPrivilege,
19 | SeIncreaseWorkingSetPrivilege,
20 | SeLoadDriverPrivilege,
21 | SeLockMemoryPrivilege,
22 | SeMachineAccountPrivilege,
23 | SeManageVolumePrivilege,
24 | SeProfileSingleProcessPrivilege,
25 | SeRelabelPrivilege,
26 | SeRemoteShutdownPrivilege,
27 | SeRestorePrivilege,
28 | SeSecurityPrivilege,
29 | SeShutdownPrivilege,
30 | SeSyncAgentPrivilege,
31 | SeSystemEnvironmentPrivilege,
32 | SeSystemProfilePrivilege,
33 | SeSystemtimePrivilege,
34 | SeTakeOwnershipPrivilege,
35 | SeTcbPrivilege,
36 | SeTimeZonePrivilege,
37 | SeTrustedCredManAccessPrivilege,
38 | SeUndockPrivilege,
39 | SeUnsolicitedInputPrivilege,
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Exceptions/EntityNotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Exceptions
4 | {
5 | public class EntityNotFoundException : Exception
6 | {
7 | public EntityNotFoundException(string message, string entityname)
8 | : base(message)
9 | {
10 | EntityName = entityname;
11 | }
12 |
13 | public string EntityName { get; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/IFileManager.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
4 | {
5 | public interface IFileManager
6 | {
7 | void RenameFile(string origPath, string newPath);
8 |
9 | void TakeOwnership(string fileName, string userName);
10 |
11 | void GiveOwnershipToAdministrators(string fileName);
12 |
13 | void GiveOwnershipToTrustedInstaller(string fileName);
14 |
15 | void SetOwnership(string fileName, string userName);
16 |
17 | void GrantFullAccessToFile(string fileName, string userName);
18 |
19 | string GetDirectoryName(string path);
20 |
21 | string GetFileName(string path);
22 |
23 | string Combine(string path1, string path2);
24 |
25 | bool Exists(string path);
26 |
27 | void Delete(string path);
28 |
29 | string[] FindLockingProcesses(string path);
30 |
31 | string[] ReadAllLines(string path);
32 |
33 | void WriteAllLines(string path, IEnumerable lines);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/IHostsFileEditor.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
4 | {
5 | public interface IHostsFileEditor
6 | {
7 | void SetHostsEntries(IEnumerable hostUrls);
8 |
9 | void ClearHostsEntries();
10 |
11 | string[] GetHostsInFile();
12 |
13 | string[] GetLockingProcessNames();
14 |
15 | void BlockHostUrl(string hostUrl);
16 |
17 | void UnblockHostUrl(string hostUrl);
18 |
19 | string[] GetManagedHosts();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/ILogWriter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
4 | {
5 | public interface ILogWriter
6 | {
7 | void LogError(Exception ex);
8 |
9 | void LogError(string message);
10 |
11 | void LogInfo(string message);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/IRegistryEditor.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
2 | {
3 | public interface IRegistryEditor
4 | {
5 | string ReadLocalMachineRegistryValue(string registryKey, string registryName);
6 |
7 | void WriteLocalMachineRegistryDword(string registryKey, string registryName, string registryValue);
8 |
9 | void WriteLocalMachineRegistryString(string registryKey, string registryName, string registryValue);
10 |
11 | void DeleteLocalMachineRegistryValue(string registryKey, string registryName);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/IWindowsPackageManager.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using WereDev.Utils.Wu10Man.Core.Models;
3 |
4 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
5 | {
6 | public interface IWindowsPackageManager
7 | {
8 | DeclutterConfig GetDeclutterConfig();
9 |
10 | PackageInfo[] ListInstalledPackages();
11 |
12 | AppInfoExtended[] MergePackageInfo(IEnumerable apps, IEnumerable packages);
13 |
14 | void RemovePackage(string packageName);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/IWindowsServiceManager.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
2 | {
3 | public interface IWindowsServiceManager
4 | {
5 | string[] ListAllServices();
6 |
7 | bool ServiceExists(string serviceName);
8 |
9 | string GetServiceDisplayName(string serviceName);
10 |
11 | string GetServiceDllPath(string serviceName);
12 |
13 | bool AreAllServicesEnabled();
14 |
15 | bool AreAllServicesDisabled();
16 |
17 | bool IsServiceEnabled(string serviceName);
18 |
19 | bool EnableService(string serviceName);
20 |
21 | void DisableService(string serviceName);
22 |
23 | void AddWu10ToFileName(string serviceName);
24 |
25 | void RemoveWu10FromFileName(string serviceName);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/IWindowsTaskManager.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Models;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces
4 | {
5 | public interface IWindowsTaskManager
6 | {
7 | WindowsTask[] GetTasks();
8 |
9 | WindowsTask GetTask(string path);
10 |
11 | WindowsTask[] DisableTasks();
12 |
13 | WindowsTask DisableTask(string path);
14 |
15 | WindowsTask[] EnableTasks();
16 |
17 | WindowsTask EnableTask(string path);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/ICredentialsProvider.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
2 | {
3 | public interface ICredentialsProvider
4 | {
5 | string GetAccountAdministratorUserName();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IFileIoProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 | using System.Security.AccessControl;
4 |
5 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
6 | {
7 | public interface IFileIoProvider
8 | {
9 | Process[] FindLockingProcesses(string path);
10 |
11 | bool Exists(string path);
12 |
13 | void Delete(string path);
14 |
15 | void Move(string sourceFile, string destFile);
16 |
17 | FileSecurity GetAccessControl(string path);
18 |
19 | void SetAccessControl(string path, FileSecurity fileSecurity);
20 |
21 | string GetFileName(string path);
22 |
23 | string GetDirectoryName(string path);
24 |
25 | string Combine(string path1, string path2);
26 |
27 | string[] ReadAllLines(string path);
28 |
29 | void WriteAllLines(string path, IEnumerable lines);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IRegistryProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Principal;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
4 | {
5 | public interface IRegistryProvider
6 | {
7 | string ReadLocalMachineRegistryValue(string registryKey, string registryName);
8 |
9 | void WriteLocalMachineRegistryDword(string registryKey, string registryName, string registryValue);
10 |
11 | void WriteLocalMachineRegistryString(string registryKey, string registryName, string registryValue);
12 |
13 | void DeleteLocalMachineRegistryValue(string registryKey, string registryName);
14 |
15 | void TakeLocalMachineOwnership(string registryKey, SecurityIdentifier user);
16 |
17 | void SetLocalMachineWritePermission(string registryKey, SecurityIdentifier user);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IUserProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Principal;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
4 | {
5 | public interface IUserProvider
6 | {
7 | SecurityIdentifier GetCurrentUser();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IWindowsApiProvider.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Enums;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
4 | {
5 | public interface IWindowsApiProvider
6 | {
7 | void ModifyPrivilege(WindowsApiPrivelegeNames privilege, bool enable);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IWindowsPackageProvider.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Models;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
4 | {
5 | public interface IWindowsPackageProvider
6 | {
7 | PackageInfo[] ListInstalledPackages();
8 |
9 | void RemovePackage(string packageName);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IWindowsServiceProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ServiceProcess;
3 |
4 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
5 | {
6 | public interface IWindowsServiceProvider : IDisposable
7 | {
8 | string DisplayName { get; }
9 |
10 | bool SetStartupType(ServiceStartMode startMode);
11 |
12 | bool ServiceExists();
13 |
14 | bool TryDisableService();
15 |
16 | bool TryEnableService();
17 |
18 | bool IsServiceEnabled();
19 |
20 | void StopService();
21 |
22 | void SetAccountAsLocalService();
23 |
24 | void SetAccountAsLocalSystem();
25 |
26 | bool IsServiceRunAsLocalSystem();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IWindowsServiceProviderFactory.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
2 | {
3 | public interface IWindowsServiceProviderFactory
4 | {
5 | IWindowsServiceProvider GetWindowsServiceProvider(string service);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Interfaces/Providers/IWindowsTaskProvider.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Models;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Interfaces.Providers
4 | {
5 | public interface IWindowsTaskProvider
6 | {
7 | WindowsTask GetTask(string fullPath);
8 |
9 | void EnableTask(string fullPath);
10 |
11 | void DisableTask(string fullPath);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/AppInfo.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Models
2 | {
3 | public class AppInfo
4 | {
5 | public string AppName { get; set; }
6 |
7 | public string PackageName { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/AppInfoExtended.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Models
2 | {
3 | public class AppInfoExtended : AppInfo
4 | {
5 | public AppInfoExtended(AppInfo appInfo)
6 | {
7 | AppName = appInfo?.AppName;
8 | PackageName = appInfo?.PackageName;
9 | }
10 |
11 | public bool IsInstalled { get; set; }
12 |
13 | public string IconPath { get; set; }
14 |
15 | public override string ToString()
16 | {
17 | return AppName;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/DeclutterConfig.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Models
2 | {
3 | public class DeclutterConfig
4 | {
5 | public AppInfo[] Microsoft { get; set; }
6 |
7 | public AppInfo[] ThirdParty { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/PackageInfo.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Models
2 | {
3 | public class PackageInfo
4 | {
5 | public string PackageName { get; set; }
6 |
7 | public string InstallLocation { get; set; }
8 |
9 | public override string ToString()
10 | {
11 | return PackageName;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/SplitHostsFile.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace WereDev.Utils.Wu10Man.Core.Models
4 | {
5 | internal class SplitHostsFile
6 | {
7 | public SplitHostsFile()
8 | {
9 | Wu10ManLines = new List();
10 | OtherLines = new List();
11 | }
12 |
13 | public List Wu10ManLines { get; }
14 |
15 | public List OtherLines { get; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/WindowsTask.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Models
2 | {
3 | public class WindowsTask
4 | {
5 | public string Name { get; set; }
6 |
7 | public string FullPath { get; set; }
8 |
9 | public bool Enabled { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Models/WindowsTaskConfig.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.Core.Models
2 | {
3 | public class WindowsTaskConfig
4 | {
5 | public string TaskName { get; set; }
6 |
7 | public string TaskPath { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("WereDev.Utils.Wu10Man.Core")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("WereDev")]
12 | [assembly: AssemblyProduct("WereDev.Utils.Wu10Man.Core")]
13 | [assembly: AssemblyCopyright("Copyright © 2018-2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("e10091e5-2789-4515-a7b2-79f316ecd30b")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Services/FileManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.AccessControl;
5 | using System.Security.Principal;
6 | using WereDev.Utils.Wu10Man.Core.Exceptions;
7 | using WereDev.Utils.Wu10Man.Core.Interfaces;
8 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
9 |
10 | namespace WereDev.Utils.Wu10Man.Core.Services
11 | {
12 | public class FileManager : IFileManager
13 | {
14 | private readonly string _trustedInstallerUser = @"NT SERVICE\TrustedInstaller";
15 | private readonly IWindowsApiProvider _windowsApiProvider;
16 | private readonly IFileIoProvider _fileIoProvider;
17 | private readonly ICredentialsProvider _credentialsProvider;
18 |
19 | public FileManager(IFileIoProvider fileIoProvider, IWindowsApiProvider windowsApiProvider, ICredentialsProvider credentialsProvider)
20 | {
21 | _fileIoProvider = fileIoProvider ?? throw new ArgumentNullException(nameof(fileIoProvider));
22 | _windowsApiProvider = windowsApiProvider ?? throw new ArgumentNullException(nameof(windowsApiProvider));
23 | _credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
24 | }
25 |
26 | public void RenameFile(string origPath, string newPath)
27 | {
28 | if (_fileIoProvider.Exists(origPath))
29 | {
30 | _fileIoProvider.Move(origPath, newPath);
31 | }
32 | }
33 |
34 | public void TakeOwnership(string fileName, string userName)
35 | {
36 | SetOwnership(fileName, userName);
37 | }
38 |
39 | public void GiveOwnershipToAdministrators(string fileName)
40 | {
41 | var username = _credentialsProvider.GetAccountAdministratorUserName();
42 | SetOwnership(fileName, username);
43 | GrantFullAccessToFile(fileName, username);
44 | }
45 |
46 | public void GiveOwnershipToTrustedInstaller(string fileName)
47 | {
48 | SetOwnership(fileName, _trustedInstallerUser);
49 | }
50 |
51 | public void SetOwnership(string fileName, string userName)
52 | {
53 | if (string.IsNullOrWhiteSpace(userName))
54 | throw new ArgumentNullException(nameof(userName));
55 |
56 | var fileSecurity = GetFileSecurity(fileName);
57 | var account = new NTAccount(userName);
58 | fileSecurity.SetOwner(account);
59 | _fileIoProvider.SetAccessControl(fileName, fileSecurity);
60 | }
61 |
62 | public void GrantFullAccessToFile(string fileName, string userName)
63 | {
64 | if (string.IsNullOrWhiteSpace(userName))
65 | throw new ArgumentNullException(nameof(userName));
66 |
67 | var fileSecurity = GetFileSecurity(fileName);
68 | var account = new NTAccount(userName);
69 | fileSecurity.SetAccessRule(new FileSystemAccessRule(account, FileSystemRights.FullControl, AccessControlType.Allow));
70 | _fileIoProvider.SetAccessControl(fileName, fileSecurity);
71 | }
72 |
73 | public string[] ReadAllLines(string path)
74 | {
75 | return _fileIoProvider.ReadAllLines(path);
76 | }
77 |
78 | public void WriteAllLines(string path, IEnumerable lines)
79 | {
80 | _fileIoProvider.WriteAllLines(path, lines);
81 | }
82 |
83 | public string[] FindLockingProcesses(string path)
84 | {
85 | var processes = _fileIoProvider.FindLockingProcesses(path);
86 | return processes.Select(x => x.MainModule?.FileVersionInfo?.ProductName ?? x.ProcessName).ToArray();
87 | }
88 |
89 | public string GetFileName(string path)
90 | {
91 | return _fileIoProvider.GetFileName(path);
92 | }
93 |
94 | public string Combine(string path1, string path2)
95 | {
96 | return _fileIoProvider.Combine(path1, path2);
97 | }
98 |
99 | public bool Exists(string path)
100 | {
101 | return _fileIoProvider.Exists(path);
102 | }
103 |
104 | public void Delete(string path)
105 | {
106 | _fileIoProvider.Delete(path);
107 | }
108 |
109 | public string GetDirectoryName(string path)
110 | {
111 | return _fileIoProvider.GetDirectoryName(path);
112 | }
113 |
114 | private FileSecurity GetFileSecurity(string fileName)
115 | {
116 | if (string.IsNullOrWhiteSpace(fileName))
117 | throw new ArgumentNullException(nameof(fileName));
118 | if (!_fileIoProvider.Exists(fileName))
119 | throw new EntityNotFoundException("Could not find file to set ownership.", fileName);
120 |
121 | // Allow this process to circumvent ACL restrictions
122 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeRestorePrivilege, true);
123 |
124 | // Sometimes this is required and other times it works without it. Not sure when.
125 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeTakeOwnershipPrivilege, true);
126 |
127 | var accessControl = _fileIoProvider.GetAccessControl(fileName);
128 |
129 | return accessControl;
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Services/HostsFileEditor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
6 | using WereDev.Utils.Wu10Man.Core.Models;
7 |
8 | namespace WereDev.Utils.Wu10Man.Core.Services
9 | {
10 | public class HostsFileEditor : IHostsFileEditor
11 | {
12 | private const string HostsFilePath = @"drivers\etc\hosts";
13 | private const string Wu10ManStart = "# Start of entries added by Wu10Man";
14 | private const string OldWu10ManStart = "# Start of entried added by Wu10Man"; // was misspelled but left here for backwards compatibility
15 | private const string Wu10ManEnd = "# End of entries added by Wu10Man";
16 | private const string OldWu10ManEnd = "# End of entried added by Wu10Man"; // was misspelled but left here for backwards compatibility
17 | private const string NullEndpoint = "0.0.0.0\t";
18 |
19 | private readonly IFileIoProvider _fileIoProvider;
20 | private readonly string[] _windowsUpdateUrls;
21 |
22 | public HostsFileEditor(IFileIoProvider fileIoProvider, string[] windowsUpateUrls)
23 | {
24 | _fileIoProvider = fileIoProvider ?? throw new ArgumentNullException(nameof(fileIoProvider));
25 | _windowsUpdateUrls = windowsUpateUrls ?? new string[0];
26 | }
27 |
28 | private string HostsFile => _fileIoProvider.Combine(Environment.SystemDirectory, HostsFilePath);
29 |
30 | public void SetHostsEntries(IEnumerable hostUrls)
31 | {
32 | var lines = ReadHostsFile();
33 | var split = SplitLines(lines);
34 | split.Wu10ManLines.Clear();
35 | var hosts = CreateLinesFromHosts(hostUrls);
36 | split.Wu10ManLines.AddRange(hosts);
37 | WriteHostsFile(split);
38 | }
39 |
40 | public void ClearHostsEntries()
41 | {
42 | var lines = ReadHostsFile();
43 | var split = SplitLines(lines);
44 | split.Wu10ManLines.Clear();
45 | WriteHostsFile(split);
46 | }
47 |
48 | public string[] GetHostsInFile()
49 | {
50 | var lines = ReadHostsFile();
51 | var split = SplitLines(lines);
52 | var hosts = GetHostsFromLines(split.Wu10ManLines);
53 | if (hosts == null)
54 | return Array.Empty();
55 | else
56 | return hosts.Select(x => StandardizeHostUrl(x)).Distinct().ToArray();
57 | }
58 |
59 | public string[] GetManagedHosts()
60 | {
61 | var uniques = _windowsUpdateUrls.Select(x => StandardizeHostUrl(x)).Distinct();
62 | return uniques.ToArray();
63 | }
64 |
65 | public string[] GetLockingProcessNames()
66 | {
67 | var processes = _fileIoProvider.FindLockingProcesses(HostsFile);
68 | return processes.Select(x => x.MainModule?.FileVersionInfo?.ProductName ?? x.ProcessName).ToArray();
69 | }
70 |
71 | public void BlockHostUrl(string hostUrl)
72 | {
73 | if (string.IsNullOrWhiteSpace(hostUrl))
74 | throw new ArgumentNullException(nameof(hostUrl));
75 | hostUrl = StandardizeHostUrl(hostUrl);
76 | if (!GetManagedHosts().Contains(hostUrl))
77 | throw new InvalidOperationException("Host URL not monitored by Wu10Man: " + hostUrl);
78 | var currentHosts = GetHostsInFile();
79 | if (!currentHosts.Contains(hostUrl))
80 | {
81 | var hostsList = currentHosts.ToList();
82 | hostsList.Add(hostUrl);
83 | SetHostsEntries(hostsList);
84 | }
85 | }
86 |
87 | public void UnblockHostUrl(string hostUrl)
88 | {
89 | if (string.IsNullOrWhiteSpace(hostUrl))
90 | throw new ArgumentNullException(nameof(hostUrl));
91 | hostUrl = StandardizeHostUrl(hostUrl);
92 | if (!GetManagedHosts().Contains(hostUrl))
93 | throw new InvalidOperationException("Host URL not monitored by Wu10Man: " + hostUrl);
94 | var currentHosts = GetHostsInFile();
95 | if (currentHosts.Contains(hostUrl))
96 | {
97 | var hostsList = currentHosts.ToList();
98 | hostsList.Remove(hostUrl);
99 | SetHostsEntries(hostsList);
100 | }
101 | }
102 |
103 | private string StandardizeHostUrl(string hostUrl)
104 | {
105 | if (string.IsNullOrWhiteSpace(hostUrl))
106 | hostUrl = string.Empty;
107 |
108 | return hostUrl.Trim().ToLower();
109 | }
110 |
111 | private string[] GetHostsFromLines(IEnumerable lines)
112 | {
113 | var hosts = lines.Select(x => GetHostFromLine(x))
114 | .Where(x => !string.IsNullOrEmpty(x))
115 | .ToArray();
116 | return hosts;
117 | }
118 |
119 | private string GetHostFromLine(string line)
120 | {
121 | line = line.Trim();
122 | if (string.IsNullOrEmpty(line))
123 | return line;
124 | var split = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
125 | return split[1];
126 | }
127 |
128 | private string[] CreateLinesFromHosts(IEnumerable hosts)
129 | {
130 | if (hosts?.Any() == true)
131 | {
132 | var lines = hosts.Select(x => NullEndpoint + x);
133 | return lines.ToArray();
134 | }
135 |
136 | return new string[0];
137 | }
138 |
139 | private string[] ReadHostsFile()
140 | {
141 | var lines = _fileIoProvider.ReadAllLines(HostsFile);
142 | return lines;
143 | }
144 |
145 | private SplitHostsFile SplitLines(IEnumerable lines)
146 | {
147 | var splitLines = new SplitHostsFile();
148 | bool wu10Line = false;
149 |
150 | foreach (var line in lines)
151 | {
152 | switch (line)
153 | {
154 | case Wu10ManStart:
155 | case OldWu10ManStart:
156 | wu10Line = true;
157 | break;
158 | case Wu10ManEnd:
159 | case OldWu10ManEnd:
160 | wu10Line = false;
161 | break;
162 | default:
163 | if (wu10Line)
164 | splitLines.Wu10ManLines.Add(line);
165 | else
166 | splitLines.OtherLines.Add(line);
167 | break;
168 | }
169 | }
170 |
171 | return splitLines;
172 | }
173 |
174 | private void WriteHostsFile(SplitHostsFile splitHostsFile)
175 | {
176 | List lines = new List(splitHostsFile.OtherLines);
177 |
178 | if (splitHostsFile.Wu10ManLines.Any())
179 | {
180 | lines.Add(Wu10ManStart);
181 | lines.AddRange(splitHostsFile.Wu10ManLines);
182 | lines.Add(Wu10ManEnd);
183 | }
184 |
185 | _fileIoProvider.WriteAllLines(HostsFile, lines);
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Services/RegistryEditor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security;
3 | using WereDev.Utils.Wu10Man.Core.Interfaces;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
5 |
6 | namespace WereDev.Utils.Wu10Man.Core.Services
7 | {
8 | public class RegistryEditor : IRegistryEditor
9 | {
10 | private readonly IWindowsApiProvider _windowsApiProvider;
11 | private readonly IRegistryProvider _registryProvider;
12 | private readonly IUserProvider _userProvider;
13 |
14 | public RegistryEditor(IWindowsApiProvider windowsApiProvider, IRegistryProvider registryProvider, IUserProvider userProvider)
15 | {
16 | _windowsApiProvider = windowsApiProvider ?? throw new ArgumentNullException(nameof(windowsApiProvider));
17 | _registryProvider = registryProvider ?? throw new ArgumentNullException(nameof(registryProvider));
18 | _userProvider = userProvider ?? throw new ArgumentNullException(nameof(userProvider));
19 | }
20 |
21 | public string ReadLocalMachineRegistryValue(string registryKey, string registryName)
22 | {
23 | if (string.IsNullOrWhiteSpace(registryKey))
24 | throw new ArgumentNullException(nameof(registryKey));
25 | if (string.IsNullOrWhiteSpace(registryName))
26 | throw new ArgumentNullException(nameof(registryName));
27 |
28 | return _registryProvider.ReadLocalMachineRegistryValue(registryKey, registryName);
29 | }
30 |
31 | public void WriteLocalMachineRegistryString(string registryKey, string registryName, string registryValue)
32 | {
33 | try
34 | {
35 | _registryProvider.WriteLocalMachineRegistryString(registryKey, registryName, registryValue);
36 | }
37 | catch (Exception ex)
38 | {
39 | if (ex is UnauthorizedAccessException || ex is SecurityException)
40 | {
41 | TakeOwnership(registryKey);
42 | SetWritePermission(registryKey);
43 | _registryProvider.WriteLocalMachineRegistryString(registryKey, registryName, registryValue);
44 | }
45 | }
46 | }
47 |
48 | public void WriteLocalMachineRegistryDword(string registryKey, string registryName, string registryValue)
49 | {
50 | try
51 | {
52 | _registryProvider.WriteLocalMachineRegistryDword(registryKey, registryName, registryValue);
53 | }
54 | catch (Exception ex)
55 | {
56 | if (ex is UnauthorizedAccessException || ex is SecurityException)
57 | {
58 | TakeOwnership(registryKey);
59 | SetWritePermission(registryKey);
60 | _registryProvider.WriteLocalMachineRegistryDword(registryKey, registryName, registryValue);
61 | }
62 | }
63 | }
64 |
65 | public void DeleteLocalMachineRegistryValue(string registryKey, string registryName)
66 | {
67 | try
68 | {
69 | _registryProvider.DeleteLocalMachineRegistryValue(registryKey, registryName);
70 | }
71 | catch (Exception ex)
72 | {
73 | if (ex is UnauthorizedAccessException || ex is SecurityException)
74 | {
75 | TakeOwnership(registryKey);
76 | SetWritePermission(registryKey);
77 | _registryProvider.DeleteLocalMachineRegistryValue(registryKey, registryName);
78 | }
79 | }
80 | }
81 |
82 | private void TakeOwnership(string registryKey)
83 | {
84 | try
85 | {
86 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeRestorePrivilege, true);
87 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeBackupPrivilege, true);
88 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeTakeOwnershipPrivilege, true);
89 | _registryProvider.TakeLocalMachineOwnership(registryKey, _userProvider.GetCurrentUser());
90 | }
91 | finally
92 | {
93 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeRestorePrivilege, false);
94 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeBackupPrivilege, false);
95 | _windowsApiProvider.ModifyPrivilege(Enums.WindowsApiPrivelegeNames.SeTakeOwnershipPrivilege, false);
96 | }
97 | }
98 |
99 | private void SetWritePermission(string registryKey)
100 | {
101 | _registryProvider.SetLocalMachineWritePermission(registryKey, _userProvider.GetCurrentUser());
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Services/WindowsPackageManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
6 | using WereDev.Utils.Wu10Man.Core.Models;
7 |
8 | namespace WereDev.Utils.Wu10Man.Core.Services
9 | {
10 | public class WindowsPackageManager : IWindowsPackageManager
11 | {
12 | private readonly IWindowsPackageProvider _packageProvider;
13 | private readonly DeclutterConfig _declutterConfig;
14 |
15 | public WindowsPackageManager(IWindowsPackageProvider packageProvider, DeclutterConfig declutterConfig)
16 | {
17 | _packageProvider = packageProvider ?? throw new ArgumentNullException(nameof(packageProvider));
18 | _declutterConfig = declutterConfig ?? new DeclutterConfig();
19 | }
20 |
21 | public DeclutterConfig GetDeclutterConfig()
22 | {
23 | return _declutterConfig;
24 | }
25 |
26 | public PackageInfo[] ListInstalledPackages()
27 | {
28 | return _packageProvider.ListInstalledPackages();
29 | }
30 |
31 | public AppInfoExtended[] MergePackageInfo(IEnumerable apps, IEnumerable packages)
32 | {
33 | List appInfos = new List();
34 | foreach (var app in apps)
35 | {
36 | var appInfo = new AppInfoExtended(app);
37 | var package = packages.FirstOrDefault(x => x.PackageName == app.PackageName);
38 | if (package != null)
39 | {
40 | appInfo.IsInstalled = true;
41 | }
42 |
43 | appInfos.Add(appInfo);
44 | }
45 |
46 | return appInfos.ToArray();
47 | }
48 |
49 | public void RemovePackage(string packageName)
50 | {
51 | _packageProvider.RemovePackage(packageName);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Services/WindowsServiceManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using WereDev.Utils.Wu10Man.Core.Enums;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
6 |
7 | namespace WereDev.Utils.Wu10Man.Core.Services
8 | {
9 | public class WindowsServiceManager : IWindowsServiceManager
10 | {
11 | private readonly string _wu10FilePrefix = "Wu10Man_";
12 | private readonly string _serviceRegistryPath = @"SYSTEM\CurrentControlSet\Services\";
13 | private readonly IWindowsServiceProviderFactory _providerFactory;
14 | private readonly IRegistryEditor _registryEditor; // TODO: Not a fan of this because of possible circular reference
15 | private readonly IFileManager _fileManager;
16 | private readonly string[] _windowsServices;
17 |
18 | public WindowsServiceManager(IWindowsServiceProviderFactory providerFactory, IRegistryEditor registryEditor, IFileManager fileManager, string[] windowsServices)
19 | {
20 | _providerFactory = providerFactory ?? throw new ArgumentNullException(nameof(providerFactory));
21 | _registryEditor = registryEditor ?? throw new ArgumentNullException(nameof(registryEditor));
22 | _fileManager = fileManager ?? throw new ArgumentNullException(nameof(fileManager));
23 | _windowsServices = windowsServices ?? new string[0];
24 | }
25 |
26 | public string[] ListAllServices()
27 | {
28 | return _windowsServices;
29 | }
30 |
31 | public bool ServiceExists(string serviceName)
32 | {
33 | if (string.IsNullOrWhiteSpace(serviceName))
34 | throw new ArgumentNullException(nameof(serviceName));
35 | using (var service = _providerFactory.GetWindowsServiceProvider(serviceName))
36 | {
37 | return service.ServiceExists();
38 | }
39 | }
40 |
41 | public string GetServiceDisplayName(string serviceName)
42 | {
43 | if (string.IsNullOrWhiteSpace(serviceName))
44 | throw new ArgumentNullException(nameof(serviceName));
45 | using (var service = _providerFactory.GetWindowsServiceProvider(serviceName))
46 | {
47 | return service.DisplayName;
48 | }
49 | }
50 |
51 | public string GetServiceDllPath(string serviceName)
52 | {
53 | if (string.IsNullOrWhiteSpace(serviceName))
54 | throw new ArgumentNullException(nameof(serviceName));
55 |
56 | return _registryEditor.ReadLocalMachineRegistryValue(_serviceRegistryPath + serviceName + @"\Parameters", "ServiceDll");
57 | }
58 |
59 | public bool AreAllServicesEnabled()
60 | {
61 | return ListAllServices().All(x => IsServiceEnabled(x));
62 | }
63 |
64 | public bool AreAllServicesDisabled()
65 | {
66 | return ListAllServices().All(x => !IsServiceEnabled(x));
67 | }
68 |
69 | public bool IsServiceEnabled(string serviceName)
70 | {
71 | if (string.IsNullOrWhiteSpace(serviceName))
72 | throw new ArgumentNullException(nameof(serviceName));
73 | var serviceDllPath = GetServiceDllPath(serviceName);
74 |
75 | using (var service = _providerFactory.GetWindowsServiceProvider(serviceName))
76 | {
77 | return service.IsServiceEnabled()
78 | && (string.IsNullOrEmpty(serviceDllPath) || _fileManager.Exists(serviceDllPath));
79 | }
80 | }
81 |
82 | public bool EnableService(string serviceName)
83 | {
84 | if (string.IsNullOrWhiteSpace(serviceName))
85 | throw new ArgumentNullException(nameof(serviceName));
86 | RemoveWu10FromFileName(serviceName);
87 | var enabledRealtime = false;
88 | using (var service = _providerFactory.GetWindowsServiceProvider(serviceName))
89 | {
90 | if (!service.IsServiceRunAsLocalSystem())
91 | service.SetAccountAsLocalSystem();
92 | enabledRealtime = service.TryEnableService();
93 | if (!enabledRealtime)
94 | {
95 | SetStartModeViaRegistry(serviceName, ServiceStartMode.Manual);
96 | }
97 | }
98 |
99 | return enabledRealtime;
100 | }
101 |
102 | public void DisableService(string serviceName)
103 | {
104 | if (string.IsNullOrWhiteSpace(serviceName))
105 | throw new ArgumentNullException(nameof(serviceName));
106 | using (var service = _providerFactory.GetWindowsServiceProvider(serviceName))
107 | {
108 | if (!service.TryDisableService())
109 | {
110 | SetStartModeViaRegistry(serviceName, ServiceStartMode.Disabled);
111 | }
112 | }
113 |
114 | AddWu10ToFileName(serviceName);
115 | }
116 |
117 | public void AddWu10ToFileName(string serviceName)
118 | {
119 | var dllPath = GetServiceDllPath(serviceName);
120 | if (string.IsNullOrEmpty(dllPath))
121 | return;
122 |
123 | _fileManager.GiveOwnershipToAdministrators(dllPath);
124 | var wu10Path = GetPathWithWu10Prefix(dllPath);
125 | _fileManager.RenameFile(dllPath, wu10Path);
126 | }
127 |
128 | public void RemoveWu10FromFileName(string serviceName)
129 | {
130 | var dllPath = GetServiceDllPath(serviceName);
131 | if (string.IsNullOrEmpty(dllPath))
132 | return;
133 |
134 | var wu10Path = GetPathWithWu10Prefix(dllPath);
135 |
136 | // If the file has returned, then we need to assume that some other process has recreated
137 | // it. It's safer to assume the new file is correct and delete the "old" file.
138 | if (_fileManager.Exists(dllPath))
139 | {
140 | _fileManager.Delete(wu10Path);
141 | }
142 | else
143 | {
144 | _fileManager.GiveOwnershipToAdministrators(wu10Path);
145 | _fileManager.RenameFile(wu10Path, dllPath);
146 | _fileManager.GiveOwnershipToTrustedInstaller(dllPath);
147 | }
148 | }
149 |
150 | private string GetPathWithWu10Prefix(string path)
151 | {
152 | var folder = _fileManager.GetDirectoryName(path);
153 | var fileName = _fileManager.GetFileName(path);
154 | if (fileName.StartsWith(_wu10FilePrefix, StringComparison.CurrentCultureIgnoreCase))
155 | return path;
156 |
157 | fileName = _wu10FilePrefix + fileName;
158 | var newPath = _fileManager.Combine(folder, fileName);
159 | return newPath;
160 | }
161 |
162 | private void SetStartModeViaRegistry(string serviceName, ServiceStartMode startMode)
163 | {
164 | _registryEditor.WriteLocalMachineRegistryDword(
165 | _serviceRegistryPath + serviceName,
166 | "Start",
167 | ((int)startMode).ToString());
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/Services/WindowsTaskManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
6 | using WereDev.Utils.Wu10Man.Core.Models;
7 |
8 | namespace WereDev.Utils.Wu10Man.Core.Services
9 | {
10 | public class WindowsTaskManager : IWindowsTaskManager
11 | {
12 | private readonly IWindowsTaskProvider _taskProvider;
13 | private readonly WindowsTaskConfig[] _windowsTaskConfigs;
14 |
15 | public WindowsTaskManager(IWindowsTaskProvider taskProvider, WindowsTaskConfig[] windowsTaskConfigs)
16 | {
17 | _taskProvider = taskProvider ?? throw new ArgumentNullException(nameof(taskProvider));
18 | _windowsTaskConfigs = windowsTaskConfigs ?? new WindowsTaskConfig[0];
19 | var distinct = _windowsTaskConfigs.GroupBy(x => x.TaskPath)
20 | .Select(x => x.First())
21 | .ToArray();
22 | _windowsTaskConfigs = distinct;
23 | }
24 |
25 | public WindowsTask[] DisableTasks()
26 | {
27 | foreach (var config in _windowsTaskConfigs)
28 | {
29 | _taskProvider.DisableTask(config.TaskPath);
30 | }
31 |
32 | return GetTasks();
33 | }
34 |
35 | public WindowsTask DisableTask(string path)
36 | {
37 | _taskProvider.DisableTask(path);
38 | return _taskProvider.GetTask(path);
39 | }
40 |
41 | public WindowsTask[] EnableTasks()
42 | {
43 | foreach (var config in _windowsTaskConfigs)
44 | {
45 | _taskProvider.EnableTask(config.TaskPath);
46 | }
47 |
48 | return GetTasks();
49 | }
50 |
51 | public WindowsTask EnableTask(string path)
52 | {
53 | _taskProvider.EnableTask(path);
54 | return _taskProvider.GetTask(path);
55 | }
56 |
57 | public WindowsTask[] GetTasks()
58 | {
59 | var tasks = new List();
60 | foreach (var config in _windowsTaskConfigs)
61 | {
62 | var task = _taskProvider.GetTask(config.TaskPath);
63 | if (task == null)
64 | continue;
65 | var pathSplit = task.FullPath.Split('\\');
66 | task.Name = pathSplit[pathSplit.Length - 2] + " - " + task.Name;
67 | tasks.Add(task);
68 | }
69 |
70 | return tasks.ToArray();
71 | }
72 |
73 | public WindowsTask GetTask(string path)
74 | {
75 | var task = _taskProvider.GetTask(path);
76 | var taskFromCollection = _windowsTaskConfigs.FirstOrDefault(x => x.TaskPath.Equals(path, StringComparison.OrdinalIgnoreCase));
77 | task.Name = taskFromCollection?.TaskName ?? task.Name;
78 | return task;
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/WereDev.Utils.Wu10Man.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Debug
8 | AnyCPU
9 | {E10091E5-2789-4515-A7B2-79F316ECD30B}
10 | Library
11 | Properties
12 | WereDev.Utils.Wu10Man.Core
13 | WereDev.Utils.Wu10Man.Core
14 | v4.7.2
15 | 512
16 | true
17 |
18 |
19 |
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 | ..\stylecop.ruleset
28 |
29 |
30 | none
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 | ..\stylecop.ruleset
37 |
38 |
39 | true
40 |
41 |
42 | wu10man-snk.pfx
43 |
44 |
45 |
46 |
47 |
48 | ..\packages\System.Diagnostics.EventLog.5.0.1\lib\net461\System.Diagnostics.EventLog.dll
49 |
50 |
51 | ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll
52 |
53 |
54 | ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll
55 |
56 |
57 |
58 | ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
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 | stylecop.json
100 |
101 |
102 | stylecop.ruleset
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Core/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/CredentialsProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Principal;
2 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
3 |
4 | namespace WereDev.Utils.Wu10Man.Providers
5 | {
6 | public class CredentialsProvider : ICredentialsProvider
7 | {
8 | public string GetAccountAdministratorUserName()
9 | {
10 | return GetUserName(WellKnownSidType.AccountAdministratorSid);
11 | }
12 |
13 | public string GetUserName(WellKnownSidType sidType)
14 | {
15 | var sid = new SecurityIdentifier(sidType, WindowsIdentity.GetCurrent().User.AccountDomainSid);
16 | var account = sid.Translate(typeof(NTAccount));
17 | return account.Value;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/FileIoProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Security.AccessControl;
6 | using WereDev.Utils.Win32Wrappers;
7 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
8 |
9 | namespace WereDev.Utils.Wu10Man.Providers
10 | {
11 | public class FileIoProvider : IFileIoProvider
12 | {
13 | public bool Exists(string path)
14 | {
15 | return File.Exists(path);
16 | }
17 |
18 | public void Move(string sourceFile, string destFile)
19 | {
20 | File.Move(sourceFile, destFile);
21 | }
22 |
23 | public void SetAccessControl(string path, FileSecurity fileSecurity)
24 | {
25 | File.SetAccessControl(path, fileSecurity);
26 | }
27 |
28 | public Process[] FindLockingProcesses(string path)
29 | {
30 | if (string.IsNullOrWhiteSpace(path))
31 | throw new ArgumentNullException(nameof(path));
32 |
33 | return FileAccessBridge.WhoIsLocking(path)?.ToArray();
34 | }
35 |
36 | public void Delete(string path)
37 | {
38 | File.Delete(path);
39 | }
40 |
41 | public FileSecurity GetAccessControl(string path)
42 | {
43 | return File.GetAccessControl(path);
44 | }
45 |
46 | public string GetFileName(string path)
47 | {
48 | return Path.GetFileName(path);
49 | }
50 |
51 | public string GetDirectoryName(string path)
52 | {
53 | return Path.GetDirectoryName(path);
54 | }
55 |
56 | public string Combine(string path1, string path2)
57 | {
58 | return Path.Combine(path1, path2);
59 | }
60 |
61 | public string[] ReadAllLines(string path)
62 | {
63 | return File.ReadAllLines(path);
64 | }
65 |
66 | public void WriteAllLines(string path, IEnumerable lines)
67 | {
68 | File.WriteAllLines(path, lines);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/PowerShellProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Management.Automation;
3 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
4 | using WereDev.Utils.Wu10Man.Core.Models;
5 |
6 | namespace WereDev.Utils.Wu10Man.Providers
7 | {
8 | public class PowerShellProvider : IWindowsPackageProvider
9 | {
10 | private const string CommandGetPackages = "Get-AppxPackage";
11 | private const string CommandRemovePackage = "Get-AppxPackage *{0}* | Remove-AppxPackage";
12 | private const string CommandRemoveProvisionedPackage = "Get-AppxProvisionedPackage -Online | where Displayname -EQ *{0}*| Remove-AppxProvisionedPackage -Online";
13 |
14 | public PackageInfo[] ListInstalledPackages()
15 | {
16 | var packages = new List();
17 | using (var ps = PowerShell.Create())
18 | {
19 | ps.AddCommand(CommandGetPackages);
20 | var results = ps.Invoke();
21 |
22 | foreach (var result in results)
23 | {
24 | dynamic appx = result.BaseObject;
25 | var package = new PackageInfo()
26 | {
27 | PackageName = appx.Name,
28 | };
29 | packages.Add(package);
30 | }
31 | }
32 |
33 | return packages.ToArray();
34 | }
35 |
36 | public void RemovePackage(string packageName)
37 | {
38 | using (var ps = PowerShell.Create())
39 | {
40 | ps.AddScript(string.Format(CommandRemovePackage, packageName));
41 | ps.AddScript(string.Format(CommandRemoveProvisionedPackage, packageName));
42 | var results = ps.Invoke();
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("WereDev.Utils.Wu10Man.Providers")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("WereDev")]
12 | [assembly: AssemblyProduct("WereDev.Utils.Wu10Man.Providers")]
13 | [assembly: AssemblyCopyright("Copyright © 2018-2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("2c880065-bd13-4abb-b3fc-11ecd25625de")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/RegistryProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Security.AccessControl;
4 | using System.Security.Principal;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
6 |
7 | namespace WereDev.Utils.Wu10Man.Providers
8 | {
9 | public class RegistryProvider : IRegistryProvider
10 | {
11 | public string ReadLocalMachineRegistryValue(string registryKey, string registryName)
12 | {
13 | if (string.IsNullOrWhiteSpace(registryKey))
14 | throw new ArgumentNullException(nameof(registryKey));
15 | if (string.IsNullOrWhiteSpace(registryName))
16 | throw new ArgumentNullException(nameof(registryName));
17 | using (var regKey = Registry.LocalMachine.OpenSubKey(registryKey))
18 | {
19 | var regValue = regKey?.GetValue(registryName);
20 | return regValue?.ToString();
21 | }
22 | }
23 |
24 | public void WriteLocalMachineRegistryString(string registryKey, string registryName, string registryValue)
25 | {
26 | WriteRegistryValue(Registry.LocalMachine, registryKey, registryName, registryValue, RegistryValueKind.String);
27 | }
28 |
29 | public void WriteLocalMachineRegistryDword(string registryKey, string registryName, string registryValue)
30 | {
31 | WriteRegistryValue(Registry.LocalMachine, registryKey, registryName, registryValue, RegistryValueKind.DWord);
32 | }
33 |
34 | public void DeleteLocalMachineRegistryValue(string registryKey, string registryName)
35 | {
36 | DeleteRegistryValue(Registry.LocalMachine, registryKey, registryName);
37 | }
38 |
39 | public void TakeLocalMachineOwnership(string registryKey, SecurityIdentifier user)
40 | {
41 | TakeOwnership(Registry.LocalMachine, registryKey, user);
42 | }
43 |
44 | public void SetLocalMachineWritePermission(string registryKey, SecurityIdentifier user)
45 | {
46 | SetWritePermission(Registry.LocalMachine, registryKey, user);
47 | }
48 |
49 | private void WriteRegistryValue(RegistryKey registryRoot, string registryKey, string registryName, string registryValue, RegistryValueKind registryValueKind)
50 | {
51 | if (registryRoot == null)
52 | throw new ArgumentNullException(nameof(registryRoot));
53 | if (string.IsNullOrWhiteSpace(registryKey))
54 | throw new ArgumentNullException(nameof(registryKey));
55 | if (string.IsNullOrWhiteSpace(registryName))
56 | throw new ArgumentNullException(nameof(registryName));
57 |
58 | using (var regKey = OpenOrCreateRegistryKey(registryRoot, registryKey, true))
59 | {
60 | regKey.SetValue(registryName, registryValue, registryValueKind);
61 | regKey.Flush();
62 | }
63 | }
64 |
65 | private RegistryKey OpenOrCreateRegistryKey(RegistryKey registryRoot, string registryKey, bool writable)
66 | {
67 | var regKey = registryRoot.OpenSubKey(registryKey, writable);
68 | if (regKey == null)
69 | regKey = registryRoot.CreateSubKey(registryKey, writable);
70 | regKey.Flush();
71 | return regKey;
72 | }
73 |
74 | private void DeleteRegistryValue(RegistryKey registryRoot, string registryKey, string registryName)
75 | {
76 | if (registryRoot == null)
77 | throw new ArgumentNullException(nameof(registryRoot));
78 | if (string.IsNullOrWhiteSpace(registryKey))
79 | throw new ArgumentNullException(nameof(registryKey));
80 | if (string.IsNullOrWhiteSpace(registryName))
81 | throw new ArgumentNullException(nameof(registryName));
82 |
83 | using (var regKey = registryRoot.OpenSubKey(registryKey, false))
84 | {
85 | var value = regKey.GetValue(registryName);
86 | if (value == null)
87 | return;
88 | }
89 |
90 | using (var regKey = registryRoot.OpenSubKey(registryKey, true))
91 | {
92 | regKey.DeleteValue(registryName);
93 | }
94 | }
95 |
96 | private void TakeOwnership(RegistryKey registryRoot, string registryKey, SecurityIdentifier user)
97 | {
98 | using (var regKey = registryRoot.OpenSubKey(registryKey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership))
99 | {
100 | var regSec = regKey.GetAccessControl();
101 | regSec.SetOwner(user);
102 | regKey.SetAccessControl(regSec);
103 | }
104 | }
105 |
106 | private void SetWritePermission(RegistryKey registryRoot, string registryKey, SecurityIdentifier user)
107 | {
108 | using (var regKey = registryRoot.OpenSubKey(registryKey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions))
109 | {
110 | var regSec = regKey.GetAccessControl();
111 |
112 | RegistryAccessRule regRule = new RegistryAccessRule(
113 | user,
114 | RegistryRights.FullControl,
115 | InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
116 | PropagationFlags.None,
117 | AccessControlType.Allow);
118 |
119 | regSec.AddAccessRule(regRule);
120 | regKey.SetAccessControl(regSec);
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/UserProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Principal;
2 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
3 |
4 | namespace WereDev.Utils.Wu10Man.Providers
5 | {
6 | public class UserProvider : IUserProvider
7 | {
8 | public SecurityIdentifier GetCurrentUser()
9 | {
10 | return WindowsIdentity.GetCurrent().User;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/WindowsApiProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using WereDev.Utils.Win32Wrappers;
3 | using WereDev.Utils.Wu10Man.Core.Enums;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
5 |
6 | namespace WereDev.Utils.Wu10Man.Providers
7 | {
8 | public class WindowsApiProvider : IWindowsApiProvider
9 | {
10 | public void ModifyPrivilege(WindowsApiPrivelegeNames privilege, bool enable)
11 | {
12 | var privlegeName = (PrivilegeName)Enum.Parse(typeof(PrivilegeName), privilege.ToString());
13 | WindowsApiBridge.ModifyPrivilege(privlegeName, enable);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/WindowsServiceProviderFactory.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
2 |
3 | namespace WereDev.Utils.Wu10Man.Providers
4 | {
5 | public class WindowsServiceProviderFactory : IWindowsServiceProviderFactory
6 | {
7 | public IWindowsServiceProvider GetWindowsServiceProvider(string service)
8 | {
9 | return new WindowsServiceProvider(service);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/WindowsTaskProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.TaskScheduler;
2 | using System;
3 | using System.Security.Principal;
4 | using System.Threading;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces.Providers;
6 | using WereDev.Utils.Wu10Man.Core.Models;
7 |
8 | namespace WereDev.Utils.Wu10Man.Providers
9 | {
10 | public class WindowsTaskProvider : IWindowsTaskProvider
11 | {
12 | private readonly string _wu10TaskPath = "Wu10Man Admin Task";
13 |
14 | public WindowsTaskProvider()
15 | {
16 | }
17 |
18 | public void DisableTask(string fullPath)
19 | {
20 | RunAdminTask("Disable-ScheduledTask", fullPath);
21 | }
22 |
23 | public void EnableTask(string fullPath)
24 | {
25 | RunAdminTask("Enable-ScheduledTask", fullPath);
26 | }
27 |
28 | public WindowsTask GetTask(string fullPath)
29 | {
30 | using (var task = TaskService.Instance.GetTask(fullPath))
31 | {
32 | if (task == null)
33 | return null;
34 |
35 | return new WindowsTask
36 | {
37 | Enabled = task.Enabled,
38 | FullPath = fullPath,
39 | Name = task.Name,
40 | };
41 | }
42 | }
43 |
44 | private void RunAdminTask(string toExecute, string fullPath)
45 | {
46 | CleanupAdminTask();
47 |
48 | using (var task = CreateHelperTask(toExecute, fullPath))
49 | {
50 | task.Run();
51 | }
52 |
53 | WaitForAdminTaskCompletion();
54 |
55 | CleanupAdminTask();
56 | }
57 |
58 | private Task CreateHelperTask(string toExecute, string fullPath)
59 | {
60 | var sid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, WindowsIdentity.GetCurrent().User.AccountDomainSid);
61 | var account = sid.Translate(typeof(NTAccount));
62 | var username = account.Value;
63 |
64 | return TaskService.Instance.AddTask(
65 | _wu10TaskPath,
66 | new TimeTrigger() { StartBoundary = DateTime.Now, Enabled = false },
67 | new ExecAction(
68 | @"powershell",
69 | $" -command \"& {{ {toExecute} -TaskName '{fullPath}' }}\"",
70 | Environment.CurrentDirectory),
71 | userId: username,
72 | logonType: TaskLogonType.ServiceAccount,
73 | description: "Task used by Wu10Man to enable other tasks");
74 | }
75 |
76 | private void CleanupAdminTask()
77 | {
78 | using (var oldTask = TaskService.Instance.GetTask(_wu10TaskPath))
79 | {
80 | if (oldTask != null)
81 | {
82 | oldTask.Stop();
83 | TaskService.Instance.RootFolder.DeleteTask(_wu10TaskPath);
84 | }
85 | }
86 | }
87 |
88 | private void WaitForAdminTaskCompletion()
89 | {
90 | while (true)
91 | {
92 | using (var task = TaskService.Instance.GetTask(_wu10TaskPath))
93 | {
94 | if (task.State != TaskState.Running)
95 | break;
96 | else
97 | Thread.Sleep(100);
98 | }
99 | }
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/WereDev.Utils.Wu10Man.Providers/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Wu10Man.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29025.244
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wu10Man", "Wu10Man\Wu10Man.csproj", "{5162DE0E-A9CE-480D-A550-E4F8833E5D26}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WereDev.Utils.Win32Wrappers", "WereDev.Utils.Win32Wrappers\WereDev.Utils.Win32Wrappers.csproj", "{11E7C6DA-6D2C-4FFD-9B2B-80646FDF9500}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WereDev.Utils.Wu10Man.Core", "WereDev.Utils.Wu10Man.Core\WereDev.Utils.Wu10Man.Core.csproj", "{E10091E5-2789-4515-A7B2-79F316ECD30B}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WereDev.Utils.Wu10Man.Providers", "WereDev.Utils.Wu10Man.Providers\WereDev.Utils.Wu10Man.Providers.csproj", "{2C880065-BD13-4ABB-B3FC-11ECD25625DE}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {5162DE0E-A9CE-480D-A550-E4F8833E5D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {5162DE0E-A9CE-480D-A550-E4F8833E5D26}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {5162DE0E-A9CE-480D-A550-E4F8833E5D26}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {5162DE0E-A9CE-480D-A550-E4F8833E5D26}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {11E7C6DA-6D2C-4FFD-9B2B-80646FDF9500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {11E7C6DA-6D2C-4FFD-9B2B-80646FDF9500}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {11E7C6DA-6D2C-4FFD-9B2B-80646FDF9500}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {11E7C6DA-6D2C-4FFD-9B2B-80646FDF9500}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {E10091E5-2789-4515-A7B2-79F316ECD30B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {E10091E5-2789-4515-A7B2-79F316ECD30B}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {E10091E5-2789-4515-A7B2-79F316ECD30B}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {E10091E5-2789-4515-A7B2-79F316ECD30B}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {2C880065-BD13-4ABB-B3FC-11ECD25625DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {2C880065-BD13-4ABB-B3FC-11ECD25625DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {2C880065-BD13-4ABB-B3FC-11ECD25625DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {2C880065-BD13-4ABB-B3FC-11ECD25625DE}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {5FF65910-90B3-413F-B7D3-A1F3D40FC5C1}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/Wu10Man/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
--------------------------------------------------------------------------------
/Wu10Man/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.IO;
4 | using System.Windows;
5 | using WereDev.Utils.Wu10Man.Core;
6 | using WereDev.Utils.Wu10Man.Core.Interfaces;
7 | using WereDev.Utils.Wu10Man.Core.Services;
8 | using WereDev.Utils.Wu10Man.Providers;
9 | using WereDev.Utils.Wu10Man.Services;
10 | using WereDev.Utils.Wu10Man.UserWindows;
11 |
12 | namespace WereDev.Utils.Wu10Man
13 | {
14 | ///
15 | /// Interaction logic for App.xaml.
16 | ///
17 | public partial class App : Application
18 | {
19 | private readonly ILogWriter _logWriter = new Wu10Logger();
20 |
21 | public App()
22 | : base()
23 | {
24 | _logWriter.LogInfo("Application starting");
25 | try
26 | {
27 | RegisterDependencies();
28 | WriteStartupLogs();
29 | Dispatcher.UnhandledException += OnDispatcherUnhandledException;
30 | MainWindow = new MainWindow();
31 | MainWindow.Show();
32 |
33 | _logWriter.LogInfo("Application started");
34 | }
35 | catch (Exception ex)
36 | {
37 | _logWriter.LogError(ex);
38 | MessageBox.Show("An error occured attempting to initialize the application. Check the log file for more details.", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
39 | Shutdown();
40 | }
41 | }
42 |
43 | protected override void OnExit(ExitEventArgs e)
44 | {
45 | _logWriter.LogInfo("Application ended");
46 | base.OnExit(e);
47 | }
48 |
49 | private void RegisterDependencies()
50 | {
51 | DependencyManager.LogWriter = _logWriter;
52 | var appSettings = GetAppSettings();
53 |
54 | // Providers
55 | var credentialsProvider = new CredentialsProvider();
56 | var fileIoProvider = new FileIoProvider();
57 | var registryProvider = new RegistryProvider();
58 | var userProvider = new UserProvider();
59 | var windowsApiProvider = new WindowsApiProvider();
60 | var windowsServiceProviderFactory = new WindowsServiceProviderFactory();
61 | var powerShellProvider = new PowerShellProvider();
62 | var windowsTaskProvider = new WindowsTaskProvider();
63 |
64 | // Services
65 | var fileManager = new FileManager(fileIoProvider, windowsApiProvider, credentialsProvider);
66 | DependencyManager.FileManager = fileManager;
67 | DependencyManager.HostsFileEditor = new HostsFileEditor(fileIoProvider, appSettings.WindowsUpdateUrls);
68 | var registryEditor = new RegistryEditor(windowsApiProvider, registryProvider, userProvider);
69 | DependencyManager.RegistryEditor = registryEditor;
70 | DependencyManager.WindowsServiceManager = new WindowsServiceManager(windowsServiceProviderFactory, registryEditor, fileManager, appSettings.WindowsServices);
71 | DependencyManager.WindowsPackageManager = new WindowsPackageManager(powerShellProvider, appSettings.Declutter);
72 | DependencyManager.WindowsTaskManager = new WindowsTaskManager(windowsTaskProvider, appSettings.WindowsTasks);
73 | }
74 |
75 | private AppSettings GetAppSettings()
76 | {
77 | var appSettingsFile = File.ReadAllText("./app.settings.json");
78 | var appSettings = JsonConvert.DeserializeObject(appSettingsFile);
79 | return appSettings;
80 | }
81 |
82 | private void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
83 | {
84 | _logWriter.LogError(e.Exception);
85 | string errorMessage = string.Format("{0}\r\n\r\nCheck the logs for more details.", e.Exception.Message);
86 | MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
87 | e.Handled = true;
88 | }
89 |
90 | private void WriteStartupLogs()
91 | {
92 | var appVersion = GetType().Assembly.GetName().Version;
93 | _logWriter.LogInfo($"Application version: v{appVersion}");
94 |
95 | var registryEditor = DependencyManager.RegistryEditor;
96 | _logWriter.LogInfo(EnvironmentVersionHelper.GetWindowsVersion(registryEditor));
97 | _logWriter.LogInfo($".Net Framework: {EnvironmentVersionHelper.GetDotNetFrameworkBuild(registryEditor)}");
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Wu10Man/AppSettings.cs:
--------------------------------------------------------------------------------
1 | using WereDev.Utils.Wu10Man.Core.Models;
2 |
3 | namespace WereDev.Utils.Wu10Man
4 | {
5 | internal class AppSettings
6 | {
7 | public string[] WindowsUpdateUrls { get; set; }
8 |
9 | public string[] WindowsServices { get; set; }
10 |
11 | public DeclutterConfig Declutter { get; set; }
12 |
13 | public WindowsTaskConfig[] WindowsTasks { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Wu10Man/Converters/MathConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Windows.Data;
6 |
7 | namespace WereDev.Utils.Wu10Man.Converters
8 | {
9 | // Does a math equation on the bound value.
10 | // Use @VALUE in your mathEquation as a substitute for bound value
11 | // Operator order is parenthesis first, then Left-To-Right (no operator precedence)
12 | // https://rachel53461.wordpress.com/2011/08/20/the-math-converter/
13 | public class MathConverter : IValueConverter
14 | {
15 | private static readonly char[] _allOperators = new[] { '+', '-', '*', '/', '%', '(', ')' };
16 |
17 | private static readonly List _grouping = new List { "(", ")" };
18 | private static readonly List _operators = new List { "+", "-", "*", "/", "%" };
19 |
20 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
21 | {
22 | // Parse value into equation and remove spaces
23 | var mathEquation = parameter as string;
24 | mathEquation = mathEquation.Replace(" ", string.Empty);
25 | mathEquation = mathEquation.Replace("@VALUE", value?.ToString() ?? string.Empty);
26 |
27 | // Validate values and get list of numbers in equation
28 | var numbers = new List();
29 | foreach (string s in mathEquation.Split(_allOperators))
30 | {
31 | if (!string.IsNullOrEmpty(s))
32 | {
33 | if (double.TryParse(s, out var tmp))
34 | {
35 | numbers.Add(tmp);
36 | }
37 | else
38 | {
39 | // Handle Error - Some non-numeric, operator, or grouping character found in string
40 | throw new InvalidCastException();
41 | }
42 | }
43 | }
44 |
45 | // Begin parsing method
46 | EvaluateMathString(ref mathEquation, ref numbers, 0);
47 |
48 | // After parsing the numbers list should only have one value - the total
49 | return numbers[0];
50 | }
51 |
52 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
53 | {
54 | throw new NotImplementedException();
55 | }
56 |
57 | // Evaluates a mathematical string and keeps track of the results in a List of numbers
58 | private void EvaluateMathString(ref string mathEquation, ref List numbers, int index)
59 | {
60 | // Loop through each mathemtaical token in the equation
61 | string token = GetNextToken(mathEquation);
62 |
63 | while (!string.IsNullOrEmpty(token))
64 | {
65 | // Remove token from mathEquation
66 | mathEquation = mathEquation.Remove(0, token.Length);
67 |
68 | // If token is a grouping character, it affects program flow
69 | if (_grouping.Contains(token))
70 | {
71 | switch (token)
72 | {
73 | case "(":
74 | EvaluateMathString(ref mathEquation, ref numbers, index);
75 | break;
76 |
77 | case ")":
78 | return;
79 | }
80 | }
81 |
82 | // If token is an operator, do requested operation
83 | if (_operators.Contains(token))
84 | {
85 | // If next token after operator is a parenthesis, call method recursively
86 | string nextToken = GetNextToken(mathEquation);
87 | if (nextToken == "(")
88 | {
89 | EvaluateMathString(ref mathEquation, ref numbers, index + 1);
90 | }
91 |
92 | // Verify that enough numbers exist in the List to complete the operation
93 | // and that the next token is either the number expected, or it was a ( meaning
94 | // that this was called recursively and that the number changed
95 | if (numbers.Count > (index + 1) &&
96 | (double.Parse(nextToken) == numbers[index + 1] || nextToken == "("))
97 | {
98 | switch (token)
99 | {
100 | case "+":
101 | numbers[index] = numbers[index] + numbers[index + 1];
102 | break;
103 | case "-":
104 | numbers[index] = numbers[index] - numbers[index + 1];
105 | break;
106 | case "*":
107 | numbers[index] = numbers[index] * numbers[index + 1];
108 | break;
109 | case "/":
110 | numbers[index] = numbers[index] / numbers[index + 1];
111 | break;
112 | case "%":
113 | numbers[index] = numbers[index] % numbers[index + 1];
114 | break;
115 | }
116 |
117 | numbers.RemoveAt(index + 1);
118 | }
119 | else
120 | {
121 | // Handle Error - Next token is not the expected number
122 | throw new FormatException("Next token is not the expected number");
123 | }
124 | }
125 |
126 | token = GetNextToken(mathEquation);
127 | }
128 | }
129 |
130 | // Gets the next mathematical token in the equation
131 | private string GetNextToken(string mathEquation)
132 | {
133 | // If we're at the end of the equation, return string.empty
134 | if (string.IsNullOrEmpty(mathEquation))
135 | {
136 | return string.Empty;
137 | }
138 |
139 | // Get next operator or numeric value in equation and return it
140 | string tmp = string.Empty;
141 | foreach (char c in mathEquation)
142 | {
143 | if (_allOperators.Contains(c))
144 | {
145 | return string.IsNullOrEmpty(tmp) ? c.ToString() : tmp;
146 | }
147 | else
148 | {
149 | tmp += c;
150 | }
151 | }
152 |
153 | return tmp;
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/Wu10Man/CustomDictionary.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | declutter
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Wu10Man/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.InteropServices;
4 | using System.Windows;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Wu10Man")]
10 | [assembly: AssemblyDescription("Windows 10 Update Manager")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("WereDev")]
13 | [assembly: AssemblyProduct("Wu10Man")]
14 | [assembly: AssemblyCopyright("Copyright WereDev © 2018-2022")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | // In order to begin building localizable applications, set
24 | // CultureYouAreCodingWith in your .csproj file
25 | // inside a . For example, if you are using US english
26 | // in your source files, set the to en-US. Then uncomment
27 | // the NeutralResourceLanguage attribute below. Update the "en-US" in
28 | // the line below to match the UICulture setting in the project file.
29 |
30 | // [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
31 |
32 | [assembly: ThemeInfo(
33 | ResourceDictionaryLocation.None, // where theme specific resource dictionaries are located
34 | // (used if a resource is not found in the page,
35 | // or application resource dictionaries)
36 | ResourceDictionaryLocation.SourceAssembly) // where the generic resource dictionary is located
37 | // (used if a resource is not found in the page,
38 | // app, or any theme specific resource dictionaries)
39 | ]
40 |
41 | // Version information for an assembly consists of the following four values:
42 | //
43 | // Major Version
44 | // Minor Version
45 | // Build Number
46 | // Revision
47 | //
48 | // You can specify all the values or you can default the Build and Revision Numbers
49 | // by using the '*' as shown below:
50 | // [assembly: AssemblyVersion("1.0.*")]
51 | [assembly: AssemblyVersion("4.4.0.0")]
52 | [assembly: AssemblyFileVersion("4.4.0.0")]
53 | [assembly: NeutralResourcesLanguage("en-US")]
54 |
--------------------------------------------------------------------------------
/Wu10Man/Services/EnvironmentVersionHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using WereDev.Utils.Wu10Man.Core.Interfaces;
3 |
4 | namespace WereDev.Utils.Wu10Man.Services
5 | {
6 | public static class EnvironmentVersionHelper
7 | {
8 | private const string WindowsVersionRegistryKey = @"SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion";
9 | private const string DotNetVersionRegistryKey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full";
10 |
11 | public static string GetDotNetFrameworkBuild(IRegistryEditor registryEditor)
12 | {
13 | if (registryEditor == null)
14 | throw new ArgumentNullException(nameof(registryEditor));
15 |
16 | var release = registryEditor.ReadLocalMachineRegistryValue(DotNetVersionRegistryKey, "Release");
17 | int.TryParse(release, out var releaseInt);
18 |
19 | if (releaseInt >= 528040)
20 | return $"{release} / 4.8 or later";
21 | else if (releaseInt >= 461808)
22 | return $"{release} / 4.7.2";
23 | else if (releaseInt >= 461308)
24 | return $"{release} / 4.7.1";
25 | else if (releaseInt >= 460798)
26 | return $"{release} / 4.7";
27 | else if (releaseInt >= 394802)
28 | return $"{release} / 4.6.2";
29 | else if (releaseInt >= 394254)
30 | return $"{release} / 4.6.1";
31 | else if (releaseInt >= 393295)
32 | return $"{release} / 4.6";
33 | else if (releaseInt >= 393273)
34 | return $"{release} / 4.6 RC";
35 | else if (releaseInt >= 379893)
36 | return $"{release} / 4.5.2";
37 | else if (releaseInt >= 378675)
38 | return $"{release} / 4.5.1";
39 | else if (releaseInt >= 378389)
40 | return $"{release} / 4.5";
41 | else
42 | return $"{release} / No 4.5 or later version detected";
43 | }
44 |
45 | public static string GetWindowsVersion(IRegistryEditor registryEditor)
46 | {
47 | if (registryEditor == null)
48 | throw new ArgumentNullException(nameof(registryEditor));
49 |
50 | var windowsProduct = registryEditor.ReadLocalMachineRegistryValue(WindowsVersionRegistryKey, "ProductName");
51 | var windowsRelease = registryEditor.ReadLocalMachineRegistryValue(WindowsVersionRegistryKey, "ReleaseId");
52 | var windowsBuild = registryEditor.ReadLocalMachineRegistryValue(WindowsVersionRegistryKey, "CurrentBuild");
53 | var windowsBuildRevision = registryEditor.ReadLocalMachineRegistryValue(WindowsVersionRegistryKey, "BaseBuildRevisionNumber");
54 | return $"{windowsProduct} Version {windowsRelease} Build {windowsBuild}.{windowsBuildRevision}";
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Wu10Man/Services/Wu10Logger.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using NLog.Targets;
3 | using System;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.IO;
6 | using WereDev.Utils.Wu10Man.Core.Interfaces;
7 |
8 | namespace WereDev.Utils.Wu10Man.Services
9 | {
10 | internal class Wu10Logger : ILogWriter
11 | {
12 | private readonly Logger _logger = LogManager.GetCurrentClassLogger();
13 |
14 | [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "nlog", Justification="nlog.config is the expected file name.")]
15 | public string LogFolder
16 | {
17 | get
18 | {
19 | var targets = LogManager.Configuration.AllTargets;
20 | foreach (var target in targets)
21 | {
22 | if (target is FileTarget fileTarget)
23 | {
24 | var logEventInfo = new LogEventInfo { TimeStamp = DateTime.Now };
25 | var fileName = fileTarget.FileName.Render(logEventInfo);
26 | var folder = Path.GetDirectoryName(fileName);
27 | return folder;
28 | }
29 | }
30 |
31 | throw new InvalidOperationException("No file logging has been configured in nlog.config");
32 | }
33 | }
34 |
35 | public void LogError(Exception ex)
36 | {
37 | var exception = ex;
38 | while (exception != null)
39 | {
40 | LogError($"{exception.GetType()}: {exception.Message}\r\n{exception.StackTrace}");
41 | exception = exception.InnerException;
42 | }
43 | }
44 |
45 | public void LogError(string message)
46 | {
47 | _logger.Error(message);
48 | }
49 |
50 | public void LogInfo(string message)
51 | {
52 | _logger.Info(message ?? string.Empty);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/DeclutterControl.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
32 |
33 |
34 |
36 |
37 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/DeclutterControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading;
4 | using System.Windows;
5 | using WereDev.Utils.Wu10Man.Core;
6 | using WereDev.Utils.Wu10Man.Core.Interfaces;
7 | using WereDev.Utils.Wu10Man.UserControls.Models;
8 |
9 | namespace WereDev.Utils.Wu10Man.UserControls
10 | {
11 | ///
12 | /// Interaction logic for DeclutterControl.xaml.
13 | ///
14 | public partial class DeclutterControl : UserControlBaseWithWorker
15 | {
16 | private readonly IWindowsPackageManager _packageManager;
17 |
18 | public DeclutterControl()
19 | : base()
20 | {
21 | _packageManager = DependencyManager.WindowsPackageManager;
22 | TabTitle = "Declutter";
23 |
24 | InitializeComponent();
25 | }
26 |
27 | protected override bool SetRuntimeOptions()
28 | {
29 | var declutter = _packageManager.GetDeclutterConfig();
30 | var installedApps = _packageManager.ListInstalledPackages();
31 | var microsoftApps = _packageManager.MergePackageInfo(declutter.Microsoft, installedApps);
32 | Model.SetPackages(DeclutterModel.PackageSource.Microsoft, microsoftApps.Select(x => new PackageInfo(x)));
33 | var thirdPartyApps = _packageManager.MergePackageInfo(declutter.ThirdParty, installedApps);
34 | Model.SetPackages(DeclutterModel.PackageSource.ThirdParty, thirdPartyApps.Select(x => new PackageInfo(x)));
35 | return true;
36 | }
37 |
38 | private void ShowMicrosoftApps(object sender, RoutedEventArgs e)
39 | {
40 | Model.ActiveSource = DeclutterModel.PackageSource.Microsoft;
41 | }
42 |
43 | private void ShowThirdPartyApps(object sender, RoutedEventArgs e)
44 | {
45 | Model.ActiveSource = DeclutterModel.PackageSource.ThirdParty;
46 | }
47 |
48 | private void ToggleAppsSelection(object sender, RoutedEventArgs e)
49 | {
50 | var setChecked = !Model.AllPackagesSelected;
51 |
52 | foreach (var package in Model.Packages)
53 | {
54 | if (package.CheckedForRemoval != setChecked)
55 | {
56 | package.CheckedForRemoval = setChecked;
57 | }
58 | }
59 | }
60 |
61 | private void RemoveCheckedApps(object sender, RoutedEventArgs e)
62 | {
63 | var packages = (PackageInfo[])ListViewWindowsApps.ItemsSource;
64 | var packagesToRemove = packages.Count(x => x.CheckedForRemoval);
65 |
66 | RunBackgroundProcess(packagesToRemove, RemoveCheckedAppWorker);
67 | }
68 |
69 | private void RemoveCheckedAppWorker(object sender, EventArgs e)
70 | {
71 | try
72 | {
73 | var packages = (PackageInfo[])ListViewWindowsApps.ItemsSource;
74 | var packagesToRemove = packages.Where(x => x.CheckedForRemoval);
75 |
76 | foreach (var ptr in packagesToRemove)
77 | {
78 | _packageManager.RemovePackage(ptr.PackageName);
79 | ptr.IsInstalled = false;
80 | ptr.CheckedForRemoval = false;
81 | LogWriter.LogInfo($"Removing Windows App: ${ptr.PackageName}");
82 | AdvanceProgressBar();
83 | }
84 |
85 | ShowInfoMessage("Selected Windows Apps have been removed.");
86 | }
87 | catch (Exception ex)
88 | {
89 | LogWriter.LogError(ex);
90 | ShowErrorMessage(ex.Message);
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/GroupPolicyControl.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
31 |
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/HostsFileControl.xaml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
45 |
46 |
47 |
48 |
49 |
60 |
61 |
62 |
63 |
64 |
65 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/HostsFileControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Windows;
3 | using WereDev.Utils.Wu10Man.Core;
4 | using WereDev.Utils.Wu10Man.Core.Interfaces;
5 | using WereDev.Utils.Wu10Man.UserControls.Models;
6 | using WPFSpark;
7 |
8 | namespace WereDev.Utils.Wu10Man.UserControls
9 | {
10 | ///
11 | /// Interaction logic for HostsFileControl.xaml.
12 | ///
13 | public partial class HostsFileControl : UserControlBase
14 | {
15 | private readonly IHostsFileEditor _hostsFileEditor;
16 |
17 | public HostsFileControl()
18 | : base()
19 | {
20 | _hostsFileEditor = DependencyManager.HostsFileEditor;
21 | TabTitle = "Hosts File";
22 | InitializeComponent();
23 | }
24 |
25 | protected override bool SetRuntimeOptions()
26 | {
27 | GetHostSettings();
28 | return true;
29 | }
30 |
31 | private void GetHostSettings()
32 | {
33 | var hostUrls = _hostsFileEditor.GetManagedHosts();
34 | if (hostUrls == null)
35 | return;
36 |
37 | var currentHosts = _hostsFileEditor.GetHostsInFile();
38 | var hostSettings = hostUrls.ToDictionary(x => x, x => !currentHosts.Contains(x));
39 | Model.HostStatus = hostSettings.Select(x => new HostStatus(x.Key, x.Value))
40 | .OrderBy(x => x.Host)
41 | .ToArray();
42 | }
43 |
44 | private void ToggleHostItem(object sender, RoutedEventArgs e)
45 | {
46 | if (!IsHostsFileLocked())
47 | {
48 | var toggle = (ToggleSwitch)sender;
49 | var kvp = (HostStatus)toggle.DataContext;
50 | if (toggle.IsChecked.Value)
51 | {
52 | _hostsFileEditor.UnblockHostUrl(kvp.Host);
53 | LogWriter.LogInfo($"Host UNBLOCKED: {kvp.Host}");
54 | }
55 | else
56 | {
57 | _hostsFileEditor.BlockHostUrl(kvp.Host);
58 | LogWriter.LogInfo($"Host BLOCKED: {kvp.Host}");
59 | }
60 |
61 | ShowUpdateNotice();
62 | }
63 | }
64 |
65 | private void UnblockAllHosts_Click(object sender, RoutedEventArgs e)
66 | {
67 | if (!IsHostsFileLocked())
68 | {
69 | _hostsFileEditor.SetHostsEntries(new string[0]);
70 | LogWriter.LogInfo($"All hosts UNBLOCKED");
71 | GetHostSettings();
72 | ShowUpdateNotice();
73 | }
74 | }
75 |
76 | private void BlockAllHosts_Click(object sender, RoutedEventArgs e)
77 | {
78 | if (!IsHostsFileLocked())
79 | {
80 | _hostsFileEditor.SetHostsEntries(_hostsFileEditor.GetManagedHosts());
81 | LogWriter.LogInfo($"All hosts BLOCKED");
82 | GetHostSettings();
83 | ShowUpdateNotice();
84 | }
85 | }
86 |
87 | private void ShowUpdateNotice()
88 | {
89 | MessageBox.Show("Hosts file updated.", TabTitle, MessageBoxButton.OK, MessageBoxImage.Information);
90 | }
91 |
92 | private bool IsHostsFileLocked()
93 | {
94 | var lockingProcesses = _hostsFileEditor.GetLockingProcessNames();
95 | if (lockingProcesses?.Any() == true)
96 | {
97 | var processNames = string.Join("\r\n", lockingProcesses);
98 | var message = "The Hosts file is being locked by the following processes and cannot be updated:\r\n" + processNames;
99 | LogWriter.LogInfo(message);
100 | ShowWarningMessage(message);
101 | return true;
102 | }
103 |
104 | return false;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/DeclutterModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace WereDev.Utils.Wu10Man.UserControls.Models
5 | {
6 | public class DeclutterModel : ModelBase
7 | {
8 | private PackageInfo[] _microsoftPackages = new PackageInfo[0];
9 | private PackageInfo[] _thirdPartyPackages = new PackageInfo[0];
10 | private PackageSource _activeSource = PackageSource.Microsoft;
11 |
12 | public enum PackageSource
13 | {
14 | Microsoft,
15 | ThirdParty,
16 | }
17 |
18 | public PackageInfo[] Packages { get; private set; }
19 |
20 | public bool AllPackagesSelected => !(Packages?.Any(x => !x.CheckedForRemoval) ?? false);
21 |
22 | public string SelectButtonText => AllPackagesSelected ? "Deselect All Apps" : "Select All Apps";
23 |
24 | public PackageSource ActiveSource
25 | {
26 | get
27 | {
28 | return _activeSource;
29 | }
30 |
31 | set
32 | {
33 | _activeSource = value;
34 | SetActivePackages();
35 | TriggerPropertyChanged(nameof(Packages), nameof(SelectButtonText));
36 | }
37 | }
38 |
39 | public void SetPackages(PackageSource packageSource, IEnumerable packages)
40 | {
41 | packages = packages ?? System.Array.Empty();
42 |
43 | switch (packageSource)
44 | {
45 | case PackageSource.Microsoft:
46 | _microsoftPackages = packages.ToArray();
47 | break;
48 | case PackageSource.ThirdParty:
49 | _thirdPartyPackages = packages.ToArray();
50 | break;
51 | }
52 |
53 | foreach (var package in packages)
54 | {
55 | package.PropertyChanged += (sender, e) =>
56 | {
57 | TriggerPropertyChanged(nameof(Packages), nameof(SelectButtonText));
58 | };
59 | }
60 |
61 | SetActivePackages();
62 | TriggerPropertyChanged(nameof(Packages), nameof(SelectButtonText));
63 | }
64 |
65 | private void SetActivePackages()
66 | {
67 | Packages = _activeSource == PackageSource.Microsoft
68 | ? _microsoftPackages
69 | : _thirdPartyPackages;
70 |
71 | Packages = Packages.Where(x => x.IsInstalled).OrderBy(x => x.AppName).ToArray();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/HostStatus.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserControls.Models
4 | {
5 | public class HostStatus : ModelBase
6 | {
7 | private bool _isActive;
8 |
9 | public HostStatus(string host, bool isActive)
10 | {
11 | if (string.IsNullOrWhiteSpace(host))
12 | throw new ArgumentNullException(nameof(host));
13 |
14 | Host = host;
15 | _isActive = isActive;
16 | }
17 |
18 | public string Host { get; }
19 |
20 | public bool IsActive
21 | {
22 | get
23 | {
24 | return _isActive;
25 | }
26 |
27 | set
28 | {
29 | _isActive = value;
30 | TriggerPropertyChanged(nameof(IsActive));
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/HostsFileModel.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.UserControls.Models
2 | {
3 | public class HostsFileModel : ModelBase
4 | {
5 | private HostStatus[] _hostStatus = new HostStatus[0];
6 |
7 | public HostStatus[] HostStatus
8 | {
9 | get
10 | {
11 | return _hostStatus;
12 | }
13 |
14 | set
15 | {
16 | _hostStatus = value ?? new HostStatus[0];
17 | TriggerPropertyChanged(nameof(HostStatus));
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/ModelBase.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserControls.Models
4 | {
5 | public abstract class ModelBase : INotifyPropertyChanged
6 | {
7 | public event PropertyChangedEventHandler PropertyChanged;
8 |
9 | protected void TriggerPropertyChanged(params string[] properties)
10 | {
11 | properties = properties ?? new string[0];
12 | foreach (var property in properties)
13 | {
14 | TriggerPropertyChanged(property);
15 | }
16 | }
17 |
18 | private void TriggerPropertyChanged(string propName)
19 | {
20 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/PackageInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using WereDev.Utils.Wu10Man.Core.Models;
4 |
5 | namespace WereDev.Utils.Wu10Man.UserControls.Models
6 | {
7 | public class PackageInfo : ModelBase
8 | {
9 | private string _appName = string.Empty;
10 | private string _packageName = string.Empty;
11 | private bool _isInstalled = false;
12 | private string _iconPath = string.Empty;
13 | private bool _checkedForRemoval = false;
14 |
15 | public PackageInfo(AppInfoExtended appInfo)
16 | {
17 | if (appInfo == null)
18 | throw new ArgumentNullException(nameof(appInfo));
19 |
20 | _appName = appInfo.AppName;
21 | _iconPath = appInfo.IconPath;
22 | _isInstalled = appInfo.IsInstalled;
23 | _packageName = appInfo.PackageName;
24 | }
25 |
26 | public string AppName
27 | {
28 | get
29 | {
30 | return _appName;
31 | }
32 |
33 | set
34 | {
35 | _appName = value;
36 | TriggerPropertyChanged(nameof(AppName));
37 | }
38 | }
39 |
40 | public string PackageName
41 | {
42 | get
43 | {
44 | return _packageName;
45 | }
46 |
47 | set
48 | {
49 | _packageName = value;
50 | TriggerPropertyChanged(nameof(PackageName));
51 | }
52 | }
53 |
54 | public bool IsInstalled
55 | {
56 | get
57 | {
58 | return _isInstalled;
59 | }
60 |
61 | set
62 | {
63 | _isInstalled = value;
64 | TriggerPropertyChanged(nameof(IsInstalled), nameof(GetVisibility));
65 | }
66 | }
67 |
68 | public string IconPath
69 | {
70 | get
71 | {
72 | return _iconPath;
73 | }
74 |
75 | set
76 | {
77 | _iconPath = value;
78 | TriggerPropertyChanged(nameof(IconPath));
79 | }
80 | }
81 |
82 | public bool CheckedForRemoval
83 | {
84 | get
85 | {
86 | return _checkedForRemoval;
87 | }
88 |
89 | set
90 | {
91 | _checkedForRemoval = value;
92 | TriggerPropertyChanged(nameof(CheckedForRemoval));
93 | }
94 | }
95 |
96 | public Visibility GetVisibility => IsInstalled ? Visibility.Visible : Visibility.Collapsed;
97 |
98 | public override string ToString()
99 | {
100 | return _appName;
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/PauseUpdatesModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserControls.Models
4 | {
5 | public class PauseUpdatesModel : ModelBase
6 | {
7 | private DateTime? _featureUpdatePauseDate = null;
8 | private int _featureUpdateDelayDays = 0;
9 | private DateTime? _qualityUpdatePauseDate = null;
10 | private int _qualityUpdateDelayDays = 0;
11 |
12 | public DateTime? FeatureUpdatePauseDate
13 | {
14 | get
15 | {
16 | return _featureUpdatePauseDate;
17 | }
18 |
19 | set
20 | {
21 | _featureUpdatePauseDate = value;
22 | TriggerPropertyChanged(nameof(FeatureUpdatePauseDate));
23 | }
24 | }
25 |
26 | public int FeatureUpdateDelayDays
27 | {
28 | get
29 | {
30 | return _featureUpdateDelayDays;
31 | }
32 |
33 | set
34 | {
35 | _featureUpdateDelayDays = value;
36 | TriggerPropertyChanged(nameof(FeatureUpdateDelayDays));
37 | }
38 | }
39 |
40 | public DateTime? QualityUpdatePauseDate
41 | {
42 | get
43 | {
44 | return _qualityUpdatePauseDate;
45 | }
46 |
47 | set
48 | {
49 | _qualityUpdatePauseDate = value;
50 | TriggerPropertyChanged(nameof(QualityUpdatePauseDate));
51 | }
52 | }
53 |
54 | public int QualityUpdateDelayDays
55 | {
56 | get
57 | {
58 | return _qualityUpdateDelayDays;
59 | }
60 |
61 | set
62 | {
63 | _qualityUpdateDelayDays = value;
64 | TriggerPropertyChanged(nameof(QualityUpdateDelayDays));
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/ProgressBarModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserControls.Models
4 | {
5 | public class ProgressBarModel : ModelBase
6 | {
7 | private int _minValue = 0;
8 | private int _maxValue = 100;
9 | private int _currentValue = 25;
10 |
11 | public int MinValue
12 | {
13 | get
14 | {
15 | return _minValue;
16 | }
17 |
18 | set
19 | {
20 | _minValue = Math.Max(value, 0);
21 | TriggerPropertyChanged(nameof(MinValue), nameof(CurrentValue));
22 | }
23 | }
24 |
25 | public int MaxValue
26 | {
27 | get
28 | {
29 | return _maxValue;
30 | }
31 |
32 | set
33 | {
34 | _maxValue = Math.Max(value, _minValue);
35 | TriggerPropertyChanged(nameof(MaxValue), nameof(CurrentValue));
36 | }
37 | }
38 |
39 | public int CurrentValue
40 | {
41 | get
42 | {
43 | return _currentValue;
44 | }
45 |
46 | set
47 | {
48 | _currentValue = Math.Min(Math.Max(value, _minValue), _maxValue);
49 | TriggerPropertyChanged(nameof(CurrentValue));
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/WindowsServiceStatusModel.cs:
--------------------------------------------------------------------------------
1 | namespace WereDev.Utils.Wu10Man.UserControls.Models
2 | {
3 | public class WindowsServiceStatusModel : ModelBase
4 | {
5 | private string _serviceName = null;
6 | private string _displayName = null;
7 | private bool _isServiceEnabled = false;
8 | private bool _serviceExists = false;
9 |
10 | public WindowsServiceStatusModel(string serviceName)
11 | {
12 | _serviceName = serviceName;
13 | }
14 |
15 | public string ServiceName
16 | {
17 | get
18 | {
19 | return _serviceName;
20 | }
21 |
22 | set
23 | {
24 | if (_serviceName != value)
25 | {
26 | _serviceName = value;
27 | TriggerPropertyChanged(nameof(ServiceName));
28 | }
29 | }
30 | }
31 |
32 | public string DisplayName
33 | {
34 | get
35 | {
36 | return _displayName;
37 | }
38 |
39 | set
40 | {
41 | if (_displayName != value)
42 | {
43 | _displayName = value;
44 | TriggerPropertyChanged(nameof(DisplayName));
45 | }
46 | }
47 | }
48 |
49 | public bool IsServiceEnabled
50 | {
51 | get
52 | {
53 | return _isServiceEnabled;
54 | }
55 |
56 | set
57 | {
58 | _isServiceEnabled = value;
59 | TriggerPropertyChanged(nameof(IsServiceEnabled));
60 | }
61 | }
62 |
63 | public bool ServiceExists
64 | {
65 | get
66 | {
67 | return _serviceExists;
68 | }
69 |
70 | set
71 | {
72 | if (_serviceExists != value)
73 | {
74 | _serviceExists = value;
75 | TriggerPropertyChanged(nameof(ServiceExists));
76 | }
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/WindowsServicesModel.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserControls.Models
4 | {
5 | public class WindowsServicesModel : ModelBase
6 | {
7 | private WindowsServiceStatusModel[] _services = new WindowsServiceStatusModel[0];
8 |
9 | public bool AllServicesDisabled => !_services.Any(x => x.ServiceExists && x.IsServiceEnabled);
10 |
11 | public string AllServicesButtonLabel => AllServicesDisabled ? "Enable All Services" : "Disable All Services";
12 |
13 | public WindowsServiceStatusModel[] Services
14 | {
15 | get
16 | {
17 | return _services;
18 | }
19 |
20 | set
21 | {
22 | _services = value ?? new WindowsServiceStatusModel[0];
23 | foreach (var service in _services)
24 | {
25 | service.PropertyChanged += (sender, e) =>
26 | {
27 | TriggerPropertyChanged(nameof(AllServicesButtonLabel), nameof(AllServicesDisabled), nameof(Services));
28 | };
29 | }
30 |
31 | TriggerPropertyChanged(nameof(AllServicesButtonLabel), nameof(AllServicesDisabled), nameof(Services));
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/WindowsTasksModel.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserControls.Models
4 | {
5 | public class WindowsTasksModel : ModelBase
6 | {
7 | private WindowsTasksStatusModel[] _tasks = new WindowsTasksStatusModel[0];
8 |
9 | public bool AllTasksDisabled => !_tasks.Any(x => x.TaskExists && x.IsTaskEnabled);
10 |
11 | public string AllTasksButtonLabel => AllTasksDisabled ? "Enable All Tasks" : "Disable All Tasks";
12 |
13 | public WindowsTasksStatusModel[] Tasks
14 | {
15 | get
16 | {
17 | return _tasks;
18 | }
19 |
20 | set
21 | {
22 | _tasks = value ?? new WindowsTasksStatusModel[0];
23 | foreach (var service in _tasks)
24 | {
25 | service.PropertyChanged += (sender, e) =>
26 | {
27 | TriggerPropertyChanged(nameof(AllTasksButtonLabel), nameof(AllTasksDisabled), nameof(Tasks));
28 | };
29 | }
30 |
31 | TriggerPropertyChanged(nameof(AllTasksButtonLabel), nameof(AllTasksDisabled), nameof(Tasks));
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/Models/WindowsTasksStatusModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using WereDev.Utils.Wu10Man.Core.Models;
3 |
4 | namespace WereDev.Utils.Wu10Man.UserControls.Models
5 | {
6 | public class WindowsTasksStatusModel : ModelBase
7 | {
8 | private string _taskPath = null;
9 | private string _displayName = null;
10 | private bool _isTaskEnabled = false;
11 | private bool _taskExists = false;
12 |
13 | public WindowsTasksStatusModel(WindowsTask task)
14 | {
15 | if (task == null)
16 | throw new ArgumentNullException(nameof(task));
17 |
18 | _taskExists = true;
19 | _taskPath = task.FullPath;
20 | _displayName = task.Name;
21 | _isTaskEnabled = task.Enabled;
22 | }
23 |
24 | public string TaskPath
25 | {
26 | get
27 | {
28 | return _taskPath;
29 | }
30 |
31 | set
32 | {
33 | if (_taskPath != value)
34 | {
35 | _taskPath = value;
36 | TriggerPropertyChanged(nameof(TaskPath));
37 | }
38 | }
39 | }
40 |
41 | public string DisplayName
42 | {
43 | get
44 | {
45 | return _displayName;
46 | }
47 |
48 | set
49 | {
50 | if (_displayName != value)
51 | {
52 | _displayName = value;
53 | TriggerPropertyChanged(nameof(DisplayName));
54 | }
55 | }
56 | }
57 |
58 | public bool IsTaskEnabled
59 | {
60 | get
61 | {
62 | return _isTaskEnabled;
63 | }
64 |
65 | set
66 | {
67 | _isTaskEnabled = value;
68 | TriggerPropertyChanged(nameof(IsTaskEnabled));
69 | }
70 | }
71 |
72 | public bool TaskExists
73 | {
74 | get
75 | {
76 | return _taskExists;
77 | }
78 |
79 | set
80 | {
81 | if (_taskExists != value)
82 | {
83 | _taskExists = value;
84 | TriggerPropertyChanged(nameof(TaskExists));
85 | }
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/PauseUpdatesControl.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/ProgressBarControl.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/ProgressBarControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 | using WereDev.Utils.Wu10Man.UserControls.Models;
3 |
4 | namespace WereDev.Utils.Wu10Man.UserControls
5 | {
6 | ///
7 | /// Interaction logic for ProgressBarControl.xaml.
8 | ///
9 | public partial class ProgressBarControl : UserControl
10 | {
11 | private readonly ProgressBarModel _model;
12 |
13 | public ProgressBarControl()
14 | {
15 | _model = new ProgressBarModel();
16 | DataContext = _model;
17 | InitializeComponent();
18 | }
19 |
20 | public void Initialize(int minValue, int maxValue)
21 | {
22 | _model.MinValue = minValue;
23 | _model.MaxValue = maxValue;
24 | _model.CurrentValue = minValue;
25 | }
26 |
27 | public void Advance()
28 | {
29 | _model.CurrentValue++;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/UserControlBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 | using System.Windows.Input;
6 | using WereDev.Utils.Wu10Man.Core;
7 | using WereDev.Utils.Wu10Man.Core.Interfaces;
8 |
9 | namespace WereDev.Utils.Wu10Man.UserControls
10 | {
11 | public class UserControlBase : UserControl
12 | where T : class, new()
13 | {
14 | public UserControlBase()
15 | : base()
16 | {
17 | if (!DesignerProperties.GetIsInDesignMode(this))
18 | {
19 | Model = new T();
20 | LogWriter = DependencyManager.LogWriter;
21 | LogWriter.LogInfo($"{TabTitle} initializing.");
22 | Mouse.OverrideCursor = Cursors.Wait;
23 | }
24 | }
25 |
26 | protected ILogWriter LogWriter { get; private set; }
27 |
28 | protected T Model { get; set; }
29 |
30 | protected string TabTitle { get; set; } = "Wu10Man";
31 |
32 | protected override void OnInitialized(EventArgs e)
33 | {
34 | if (!DesignerProperties.GetIsInDesignMode(this))
35 | {
36 | SetRuntimeOptionsWrapper();
37 | LogWriter.LogInfo($"{TabTitle} rendered.");
38 | Mouse.OverrideCursor = Cursors.Arrow;
39 | }
40 |
41 | DataContext = Model;
42 | base.OnInitialized(e);
43 | }
44 |
45 | protected virtual bool SetRuntimeOptions()
46 | {
47 | return true;
48 | }
49 |
50 | protected void ShowErrorMessage(string message)
51 | {
52 | MessageBox.Show($"{message}\r\n\r\nCheck the logs for more details.", TabTitle, MessageBoxButton.OK, MessageBoxImage.Error);
53 | }
54 |
55 | protected void ShowWarningMessage(string message)
56 | {
57 | MessageBox.Show(message, TabTitle, MessageBoxButton.OK, MessageBoxImage.Warning);
58 | }
59 |
60 | protected void ShowInfoMessage(string message)
61 | {
62 | MessageBox.Show(message, TabTitle, MessageBoxButton.OK, MessageBoxImage.Information);
63 | }
64 |
65 | private bool SetRuntimeOptionsWrapper()
66 | {
67 | try
68 | {
69 | return SetRuntimeOptions();
70 | }
71 | catch (Exception ex)
72 | {
73 | LogWriter.LogError(ex);
74 | ShowErrorMessage(ex.Message);
75 | return false;
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/UserControlBaseWithWorker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 |
6 | namespace WereDev.Utils.Wu10Man.UserControls
7 | {
8 | public class UserControlBaseWithWorker : UserControlBase, IDisposable
9 | where T : class, new()
10 | {
11 | private readonly ProgressBarControl _progressBar = new ProgressBarControl();
12 | private bool _isDisposed = false;
13 | private BackgroundWorker _worker;
14 |
15 | public UserControlBaseWithWorker()
16 | : base()
17 | {
18 | }
19 |
20 | public void Dispose()
21 | {
22 | Dispose(true);
23 | GC.SuppressFinalize(this);
24 | }
25 |
26 | protected virtual void Dispose(bool disposing)
27 | {
28 | if (_isDisposed)
29 | return;
30 |
31 | if (disposing)
32 | {
33 | _worker.Dispose();
34 | }
35 |
36 | _isDisposed = true;
37 | }
38 |
39 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "_worker part of larger scope.")]
40 | protected virtual void RunBackgroundProcess(int progressBarMax, DoWorkEventHandler backgroundMethod)
41 | {
42 | InitializeProgressBar(0, progressBarMax);
43 |
44 | _worker = new BackgroundWorker
45 | {
46 | WorkerReportsProgress = true,
47 | };
48 | _worker.DoWork += backgroundMethod;
49 | _worker.RunWorkerCompleted += RunWorkerCompleted;
50 | _worker.RunWorkerAsync();
51 | }
52 |
53 | protected virtual void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
54 | {
55 | _progressBar.Visibility = Visibility.Hidden;
56 | ((Grid)Application.Current.MainWindow.Content).Children.Remove(_progressBar);
57 | }
58 |
59 | protected void InitializeProgressBar(int minValue, int maxValue)
60 | {
61 | ((Grid)Application.Current.MainWindow.Content).Children.Add(_progressBar);
62 | _progressBar.HorizontalAlignment = HorizontalAlignment.Stretch;
63 | _progressBar.VerticalAlignment = VerticalAlignment.Stretch;
64 | _progressBar.Visibility = Visibility.Visible;
65 | _progressBar.Initialize(minValue, maxValue);
66 | }
67 |
68 | protected void AdvanceProgressBar()
69 | {
70 | _progressBar.Advance();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/WindowsServicesControl.xaml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
69 |
70 |
71 |
72 |
73 |
89 |
90 |
91 |
92 |
93 |
94 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/WindowsServicesControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Windows;
4 | using WereDev.Utils.Wu10Man.Core;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces;
6 | using WereDev.Utils.Wu10Man.UserControls.Models;
7 | using WPFSpark;
8 |
9 | namespace WereDev.Utils.Wu10Man.UserControls
10 | {
11 | ///
12 | /// Interaction logic for WindowsServicesControl.xaml.
13 | ///
14 | public partial class WindowsServicesControl : UserControlBaseWithWorker
15 | {
16 | private readonly IWindowsServiceManager _windowsServiceManager;
17 |
18 | public WindowsServicesControl()
19 | : base()
20 | {
21 | _windowsServiceManager = DependencyManager.WindowsServiceManager;
22 | TabTitle = "Windows Services";
23 | InitializeComponent();
24 | }
25 |
26 | protected override bool SetRuntimeOptions()
27 | {
28 | BuildServiceStatus();
29 | return true;
30 | }
31 |
32 | private void BuildServiceStatus()
33 | {
34 | Model.Services = _windowsServiceManager.ListAllServices()
35 | .Select(x => new WindowsServiceStatusModel(x))
36 | .ToArray();
37 | foreach (var service in Model.Services)
38 | SetServiceStatus(service.ServiceName);
39 | }
40 |
41 | private void SetServiceStatus(string serviceName)
42 | {
43 | var serviceModel = Model.Services.Single(x => x.ServiceName == serviceName);
44 | serviceModel.ServiceExists = _windowsServiceManager.ServiceExists(serviceName);
45 | if (serviceModel.ServiceExists)
46 | {
47 | serviceModel.DisplayName = _windowsServiceManager.GetServiceDisplayName(serviceName);
48 | serviceModel.IsServiceEnabled = _windowsServiceManager.IsServiceEnabled(serviceName);
49 | }
50 | }
51 |
52 | private void ToggleService(object sender, RoutedEventArgs e)
53 | {
54 | var toggle = (ToggleSwitch)sender;
55 | var data = (WindowsServiceStatusModel)toggle.DataContext;
56 | if (toggle.IsChecked.Value)
57 | {
58 | var enabledRealtime = EnableService(data.ServiceName, data.DisplayName);
59 | var message = $"{data.DisplayName} has been ENABLED";
60 | if (!enabledRealtime)
61 | message += "\r\rYou will need to reboot for the setting to take effect.";
62 | ShowInfoMessage(message);
63 | }
64 | else
65 | {
66 | DisableService(data.ServiceName, data.DisplayName);
67 | ShowInfoMessage($"{data.DisplayName} has been DISABLED");
68 | }
69 | }
70 |
71 | private void UpdateServices(object sender, RoutedEventArgs e)
72 | {
73 | var count = Model.Services.Where(x => x.ServiceExists).Count();
74 | RunBackgroundProcess(count, ToggleServices);
75 | }
76 |
77 | private bool EnableService(string serviceName, string displayName)
78 | {
79 | var enabledRealtime = _windowsServiceManager.EnableService(serviceName);
80 | SetServiceStatus(serviceName);
81 | LogWriter.LogInfo($"Service ENABLED: {serviceName} - {displayName}");
82 | return enabledRealtime;
83 | }
84 |
85 | private void DisableService(string serviceName, string displayName)
86 | {
87 | _windowsServiceManager.DisableService(serviceName);
88 | SetServiceStatus(serviceName);
89 | LogWriter.LogInfo($"Service DISABLED: {serviceName} - {displayName}");
90 | }
91 |
92 | private void ToggleServices(object sender, EventArgs e)
93 | {
94 | var allServicesDisabled = Model.AllServicesDisabled;
95 | var services = Model.Services.Where(x => x.ServiceExists).ToArray();
96 | foreach (var service in services)
97 | {
98 | if (allServicesDisabled)
99 | {
100 | EnableService(service.ServiceName, service.DisplayName);
101 | }
102 | else if (service.IsServiceEnabled)
103 | {
104 | DisableService(service.ServiceName, service.DisplayName);
105 | }
106 |
107 | AdvanceProgressBar();
108 | }
109 |
110 | BuildServiceStatus();
111 | ShowInfoMessage("Windows Services updated.");
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/WindowsTasksControl.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
43 |
44 |
45 |
47 |
48 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/Wu10Man/UserControls/WindowsTasksControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Windows;
4 | using WereDev.Utils.Wu10Man.Core;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces;
6 | using WereDev.Utils.Wu10Man.UserControls.Models;
7 | using WPFSpark;
8 |
9 | namespace WereDev.Utils.Wu10Man.UserControls
10 | {
11 | ///
12 | /// Interaction logic for WindowsTasksControl.xaml.
13 | ///
14 | public partial class WindowsTasksControl : UserControlBaseWithWorker
15 | {
16 | private readonly IWindowsTaskManager _windowsTaskManager;
17 |
18 | public WindowsTasksControl()
19 | : base()
20 | {
21 | _windowsTaskManager = DependencyManager.WindowsTaskManager;
22 | TabTitle = "Windows Scheduled Tasks";
23 | InitializeComponent();
24 | }
25 |
26 | protected override bool SetRuntimeOptions()
27 | {
28 | BuildTaskStatus();
29 | return true;
30 | }
31 |
32 | private void BuildTaskStatus()
33 | {
34 | Model.Tasks = _windowsTaskManager.GetTasks()
35 | .Select(x => new WindowsTasksStatusModel(x))
36 | .ToArray();
37 | }
38 |
39 | private void ToggleTask(object sender, RoutedEventArgs e)
40 | {
41 | var toggle = (ToggleSwitch)sender;
42 | var data = (WindowsTasksStatusModel)toggle.DataContext;
43 | if (toggle.IsChecked.Value)
44 | {
45 | EnableTask(data.TaskPath, data.DisplayName);
46 | var message = $"{data.DisplayName} has been ENABLED";
47 | ShowInfoMessage(message);
48 | }
49 | else
50 | {
51 | DisableTask(data.TaskPath, data.DisplayName);
52 | ShowInfoMessage($"{data.DisplayName} has been DISABLED");
53 | }
54 | }
55 |
56 | private void UpdateTasks(object sender, RoutedEventArgs e)
57 | {
58 | var count = Model.Tasks.Where(x => x.TaskExists).Count();
59 | RunBackgroundProcess(count, TaggleTasks);
60 | }
61 |
62 | private void EnableTask(string taskPath, string displayName)
63 | {
64 | _windowsTaskManager.EnableTask(taskPath);
65 | SetTaskStatus(taskPath);
66 | LogWriter.LogInfo($"Scheduled Task ENABLED: {taskPath} - {displayName}");
67 | }
68 |
69 | private void DisableTask(string taskpath, string displayName)
70 | {
71 | _windowsTaskManager.DisableTask(taskpath);
72 | SetTaskStatus(taskpath);
73 | LogWriter.LogInfo($"Scheduled Task DISABLED: {taskpath} - {displayName}");
74 | }
75 |
76 | private void TaggleTasks(object sender, EventArgs e)
77 | {
78 | var allTasksDisabled = Model.AllTasksDisabled;
79 | var tasks = Model.Tasks.Where(x => x.TaskExists).ToArray();
80 | foreach (var task in tasks)
81 | {
82 | if (allTasksDisabled)
83 | {
84 | EnableTask(task.TaskPath, task.DisplayName);
85 | }
86 | else if (task.IsTaskEnabled)
87 | {
88 | DisableTask(task.TaskPath, task.DisplayName);
89 | }
90 |
91 | AdvanceProgressBar();
92 | }
93 |
94 | BuildTaskStatus();
95 | ShowInfoMessage("Windows Scheduled Tasks updated.");
96 | }
97 |
98 | private void SetTaskStatus(string taskPath)
99 | {
100 | var taskModel = Model.Tasks.Single(x => x.TaskPath == taskPath);
101 | var task = _windowsTaskManager.GetTask(taskPath);
102 | taskModel.TaskExists = task != null;
103 | if (taskModel.TaskExists)
104 | {
105 | taskModel.IsTaskEnabled = task.Enabled;
106 | }
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/About.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | https://github.com/WereDev/Wu10Man/
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/About.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Windows;
3 | using System.Windows.Documents;
4 | using System.Windows.Navigation;
5 |
6 | namespace WereDev.Utils.Wu10Man.UserWindows
7 | {
8 | public partial class About : Window
9 | {
10 | public About()
11 | {
12 | InitializeComponent();
13 | var version = GetType().Assembly.GetName().Version;
14 | lblAppVersion.Text = "v" + version.ToString();
15 | }
16 |
17 | private void GitHub_RequestNavigate(object sender, RequestNavigateEventArgs e)
18 | {
19 | Hyperlink linkAnnouncements = (Hyperlink)sender;
20 | string site = linkAnnouncements.NavigateUri.ToString();
21 | Process.Start(new ProcessStartInfo(site));
22 | e.Handled = true;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using WereDev.Utils.Wu10Man.Core;
5 | using WereDev.Utils.Wu10Man.Core.Interfaces;
6 | using WereDev.Utils.Wu10Man.Services;
7 | using WereDev.Utils.Wu10Man.UserControls;
8 | using WereDev.Utils.Wu10Man.UserWindows.Models;
9 |
10 | namespace WereDev.Utils.Wu10Man.UserWindows
11 | {
12 | ///
13 | /// Interaction logic for MainWindow.xaml.
14 | ///
15 | public partial class MainWindow : Window
16 | {
17 | private readonly ILogWriter _logWriter;
18 | private readonly MainWindowModel _mainWindowModel;
19 |
20 | public MainWindow()
21 | {
22 | _logWriter = DependencyManager.LogWriter;
23 | _mainWindowModel = new MainWindowModel()
24 | {
25 | TabItems = new ITabItemModel[]
26 | {
27 | new TabItemModel { BackgroundColor = "#f25022", Header = "Windows Services" },
28 | new TabItemModel { BackgroundColor = "#01a4ef", Header = "Pause Updates" },
29 | new TabItemModel { BackgroundColor = "#ffb901", Header = "BETA - Declutter" },
30 | new TabItemModel { BackgroundColor = "#7fba00", Header = "BETA - Scheduled Tasks" },
31 | new TabItemModel { BackgroundColor = "LightGray", Header = "LEGACY - Hosts File", IsLegacy = true },
32 | new TabItemModel { BackgroundColor = "LightGray", Header = "LEGACY - Group Policy", IsLegacy = true },
33 | },
34 | };
35 |
36 | _logWriter.LogInfo("Main window initializing.");
37 | InitializeComponent();
38 | DataContext = _mainWindowModel;
39 | _logWriter.LogInfo("Main window initialized.");
40 | }
41 |
42 | protected override void OnClosed(EventArgs e)
43 | {
44 | Application.Current.Shutdown();
45 | base.OnClosed(e);
46 | }
47 |
48 | private void ExitItem_Click(object sender, RoutedEventArgs e)
49 | {
50 | Close();
51 | }
52 |
53 | private void AboutItem_Click(object sender, RoutedEventArgs e)
54 | {
55 | DisplayWindow(new About());
56 | }
57 |
58 | private void LogFilesItem_Click(object sender, RoutedEventArgs e)
59 | {
60 | System.Diagnostics.Process.Start((_logWriter as Wu10Logger)?.LogFolder);
61 | }
62 |
63 | private void ReadmeItem_Click(object sender, RoutedEventArgs e)
64 | {
65 | System.Diagnostics.Process.Start("https://weredev.com/developer/wu10man/");
66 | }
67 |
68 | private void DisplayWindow(Window window)
69 | {
70 | window.Left = Left + ((Width - window.Width) / 2);
71 | window.Top = Top + ((Height - window.Height) / 2);
72 | window.ShowDialog();
73 | }
74 |
75 | private void BuyMeACoffee_Click(object sender, RoutedEventArgs e)
76 | {
77 | System.Diagnostics.Process.Start("https://www.buymeacoffee.com/weredev");
78 | }
79 |
80 | private void ViewLegacy_Click(object sender, RoutedEventArgs e)
81 | {
82 | _mainWindowModel.ShowLegacy = !_mainWindowModel.ShowLegacy;
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/Models/ITabItemModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 |
3 | namespace WereDev.Utils.Wu10Man.UserWindows.Models
4 | {
5 | public interface ITabItemModel
6 | where T : UserControl, new()
7 | {
8 | string Header { get; }
9 |
10 | string BackgroundColor { get; }
11 |
12 | T UserControl { get; }
13 |
14 | bool IsLegacy { get; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/Models/MainWindowModel.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using WereDev.Utils.Wu10Man.UserControls.Models;
5 |
6 | namespace WereDev.Utils.Wu10Man.UserWindows.Models
7 | {
8 | public class MainWindowModel : ModelBase
9 | {
10 | private bool _showLegacy;
11 |
12 | public bool ShowLegacy
13 | {
14 | get
15 | {
16 | return _showLegacy;
17 | }
18 |
19 | set
20 | {
21 | _showLegacy = value;
22 | TriggerPropertyChanged(nameof(ShowLegacy), nameof(LegacyVisibility), nameof(VisibleTabItems));
23 | }
24 | }
25 |
26 | public Visibility LegacyVisibility => _showLegacy ? Visibility.Visible : Visibility.Hidden;
27 |
28 | public ITabItemModel[] TabItems { get; set; }
29 |
30 | public ITabItemModel[] VisibleTabItems => TabItems.Where(x => _showLegacy || !x.IsLegacy).ToArray();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Wu10Man/UserWindows/Models/TabItemModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace WereDev.Utils.Wu10Man.UserWindows.Models
5 | {
6 | public class TabItemModel : ITabItemModel
7 | where T : UserControl, new()
8 | {
9 | private T _userControl = null;
10 |
11 | public string Header { get; set; }
12 |
13 | public string BackgroundColor { get; set; }
14 |
15 | public T UserControl
16 | {
17 | get
18 | {
19 | _userControl = _userControl ?? new T();
20 | return _userControl;
21 | }
22 | }
23 |
24 | public bool IsLegacy { get; set; } = false;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Wu10Man/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
55 |
56 |
70 |
--------------------------------------------------------------------------------
/Wu10Man/nlog.config:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Wu10Man/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Wu10Man/question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WereDev/Wu10Man/e7886c0b0a0b26b47038e20850034cf3ac961300/Wu10Man/question.png
--------------------------------------------------------------------------------
/Wu10Man/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WereDev/Wu10Man/e7886c0b0a0b26b47038e20850034cf3ac961300/Wu10Man/warning.png
--------------------------------------------------------------------------------
/Wu10Man/wu10man.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WereDev/Wu10Man/e7886c0b0a0b26b47038e20850034cf3ac961300/Wu10Man/wu10man.ico
--------------------------------------------------------------------------------
/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
3 | "settings": {
4 | "documentationRules": {
5 | "copyrightText": "Licensed under the MIT license. See LICENSE file in the samples root for full license information.",
6 | "companyName": "WereDev",
7 | "xmlHeader": false,
8 | "documentExposedElements": false
9 | },
10 | "layoutRules": {
11 | "newlineAtEndOfFile": "require"
12 | },
13 | "indentation": {
14 | "indentationSize": 4,
15 | "useTabs": false
16 | },
17 | "namingRules": {},
18 | "orderingRules": {
19 | "systemUsingDirectivesFirst": false,
20 | "usingDirectivesPlacement": "outsideNamespace",
21 | "elementOrder": [
22 | "kind",
23 | "constant",
24 | "accessibility",
25 | "static",
26 | "readonly"
27 | ]
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------