25 Commits
v1.3 ... master

Author SHA1 Message Date
  he3als 97c2790bb8 Merge pull request 'Add de-amelioration & more' (#13) from review into master 1 week ago
  he3als ad8f622ffe
fix(de-ame): ChoicePrompt starts from 0, not 1 1 week ago
  he3als 69f5cb0be7
feat(de-ame): auto-uninstall of ExplorerPatcher 1 week ago
  he3als 2311044abc
fix(de-ame): no /Server for Win 10 1 week ago
  he3als a19de34df2
fix(deameliorate): remove debugging ReadKey 2 weeks ago
  he3als 8e3b009195
feat: deameliorate function 2 weeks ago
  he3als 544083e817
feat(SelectWindowsImage): return winver & check it 1 month ago
  he3als 8206fe87b4
feat(.NET): move Windows ISO mount to new class 1 month ago
  he3als 5f44c7cb79
fix: update all packages 1 month ago
  he3als a25c919eaa
feat: menu using WASD 1 month ago
  he3als e986cde90b
fix(.net 3.5): final touches (ejecting ISO, etc) 4 months ago
  he3als 96135bca0d
fix(.net 3.5): general fixes 4 months ago
  he3als e0d0bfd030
feat: .NET 3.5 with USB/folder 4 months ago
  he3als 8c6c9c3d3c
feat(users): password reconfirmation 4 months ago
  Styris d1858244ba Update README 8 months ago
  Styris 14359b9855 C# Update 8 months ago
  Styris 8fb460ba4f Update 'README.md' 1 year ago
  Styris bc8cec4dab Update 'README.md' 1 year ago
  Styris 8b04e77b8f Update 'README.md' 1 year ago
  Styris d5778d8e47 Update 'README.md' 1 year ago
  Styris 8688290afd Update README 1 year ago
  Styris 6ed9ff89f6 Update README 1 year ago
  Styris 09cece9a2b Release v1.4 1 year ago
  Joe 1d8824361f Remove Usage note from README 1 year ago
  Joe fe6a69b0b9 Release v1.3 1 year ago
45 changed files with 8499 additions and 4032 deletions
Unified View
  1. +559
    -0
      .gitignore
  2. +22
    -84
      README.md
  3. +0
    -3948
      amecs.cmd
  4. BIN
      screenshot.png
  5. BIN
      src/7z.dll
  6. +132
    -0
      src/Actions/.NET.cs
  7. +313
    -0
      src/Actions/AutoLogon.cs
  8. +239
    -0
      src/Actions/Deameliorate.cs
  9. +21
    -0
      src/Actions/Elevation.cs
  10. +1089
    -0
      src/Actions/Languages.cs
  11. +113
    -0
      src/Actions/Lockscreen.cs
  12. +124
    -0
      src/Actions/Profile.cs
  13. +220
    -0
      src/Actions/UserPass.cs
  14. +19
    -0
      src/Actions/UsernameRequirement.cs
  15. +299
    -0
      src/Actions/Users.cs
  16. +201
    -0
      src/Ameliorated.ConsoleUtils/ConsoleTUI/ConsoleTUI.cs
  17. +198
    -0
      src/Ameliorated.ConsoleUtils/ConsoleTUI/Frame.cs
  18. +397
    -0
      src/Ameliorated.ConsoleUtils/ConsoleTUI/FrameWriteMethods.cs
  19. +433
    -0
      src/Ameliorated.ConsoleUtils/ConsoleTUI/Menu.cs
  20. +196
    -0
      src/Ameliorated.ConsoleUtils/ConsoleTUI/MouseInterface.cs
  21. +604
    -0
      src/Ameliorated.ConsoleUtils/ConsoleTUI/Prompt.cs
  22. +250
    -0
      src/Ameliorated.ConsoleUtils/ConsoleUtils.cs
  23. +88
    -0
      src/Ameliorated.ConsoleUtils/Extensions.cs
  24. +74
    -0
      src/Ameliorated.ConsoleUtils/ParentProcess.cs
  25. +6
    -0
      src/Ameliorated.ConsoleUtils/Payload.cs
  26. +10
    -0
      src/App.config
  27. +342
    -0
      src/Extra/Extra.cs
  28. +281
    -0
      src/Extra/NVCP.cs
  29. +40
    -0
      src/Extra/WSH.cs
  30. +3
    -0
      src/FodyWeavers.xml
  31. +41
    -0
      src/Globals.cs
  32. +220
    -0
      src/Misc/FolderPicker.cs
  33. +261
    -0
      src/Misc/SelectWindowsImage.cs
  34. +525
    -0
      src/NSudo.cs
  35. +141
    -0
      src/Program.cs
  36. +35
    -0
      src/Properties/AssemblyInfo.cs
  37. +375
    -0
      src/Registry.cs
  38. +263
    -0
      src/amecs.cs
  39. +266
    -0
      src/amecs.csproj
  40. BIN
      src/amecs.ico
  41. BIN
      src/amecs.png
  42. +16
    -0
      src/amecs.sln
  43. BIN
      src/amecs_old.ico
  44. +17
    -0
      src/app.manifest
  45. +66
    -0
      src/packages.config

+ 559
- 0
.gitignore View File

@ -0,0 +1,559 @@
!*.gitkeep
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Nuget personal access tokens and Credentials
nuget.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
.idea/
*.sln.iml
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### vs ###
# User-specific files
# User-specific files (MonoDevelop/Xamarin Studio)
# Mono auto generated files
# Build results
# Visual Studio 2015/2017 cache/options directory
# Uncomment if you have tasks that create the project's static files in wwwroot
# Visual Studio 2017 auto generated files
# MSTest test Results
# NUnit
# Build Results of an ATL Project
# Benchmark Results
# .NET Core
# StyleCop
# Files built by Visual Studio
# Chutzpah Test files
# Visual C++ cache files
# Visual Studio profiler
# Visual Studio Trace Files
# TFS 2012 Local Workspace
# Guidance Automation Toolkit
# ReSharper is a .NET coding add-in
# TeamCity is a build add-in
# DotCover is a Code Coverage Tool
# AxoCover is a Code Coverage Tool
# Coverlet is a free, cross platform Code Coverage Tool
coverage*[.json, .xml, .info]
# Visual Studio code coverage results
# NCrunch
# MightyMoose
# Web workbench (sass)
# Installshield output folder
# DocProject is a documentation generator add-in
# Click-Once directory
# Publish Web Output
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
# NuGet Packages
# NuGet Symbol Packages
# The packages folder can be ignored because of Package Restore
# except build/, which is used as an MSBuild target.
# Uncomment if necessary however generally it will be regenerated when needed
# NuGet v3's project.json files produces more ignorable files
# Microsoft Azure Build Output
# Microsoft Azure Emulator
# Windows Store app package directories and files
# Visual Studio cache files
# files ending in .cache can be ignored
# but keep track of directories ending in .cache
# Others
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
# RIA/Silverlight projects
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
# SQL Server files
# Business Intelligence projects
# Microsoft Fakes
# GhostDoc plugin setting file
# Node.js Tools for Visual Studio
# Visual Studio 6 build log
# Visual Studio 6 workspace options file
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
# Visual Studio LightSwitch build output
# Paket dependency manager
# FAKE - F# Make
# CodeRush personal settings
# Python Tools for Visual Studio (PTVS)
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
# Telerik's JustMock configuration file
# BizTalk build output
# OpenCover UI analysis results
# Azure Stream Analytics local run output
# MSBuild Binary and Structured Log
# NVidia Nsight GPU debugger configuration file
# MFractors (Xamarin productivity tool) working folder
# Local History for Visual Studio
# BeatPulse healthcheck temp database
# Backup folder for Package Reference Convert tool in Visual Studio 2017
# Ionide (cross platform F# VS Code tools) working folder

+ 22
- 84
README.md View File

@ -6,29 +6,27 @@ Script for automating a large assortment of AME related actions.
## Usage ## Usage
*Note: using **Download Repository** > **ZIP** will result in a faulty amecs script.*
You can download the script by going to the [latest release](https://git.ameliorated.info/Styris/amecs/releases/latest) and selecting `amecs.exe` from the **Downloads** section. Once downloaded, simply run `amecs.exe`.
You can download the script by going to the [latest release](https://git.ameliorated.info/Joe/amecs/releases/latest) and selecting `amecs.zip` from the **Downloads** section. Once downloaded, simply extract `amecs.zip` and run `amecs.cmd`.
## Summary
Alternatively, you could clone the repository:
As part of the amelioration process, certain UI elements, such as the **Region and language** page in Windows Settings, have been removed, and require alternative ways to execute the tasks. This script fills in those gaps, and allows for automating a large variety of customization tasks.
git clone https://git.ameliorated.info/Joe/amecs.git
Once cloned, simply run `amecs.cmd`.
If you prefer manually executing commands for some of these tasks without a script, you can go through the step-by-step guides on [AME Guides](https://t.me/AMEGuides).
## Primary Functions ## Primary Functions
There are many actions in AME that require commands, the following functions essentially work as an interactive user interface for those.
There are many actions in AME that require commands or are otherwise unavailable. The following functions work as replacements for those actions.
#### Username/Password #### Username/Password
This function allows for changing the user's username or password. This function allows for changing the user's username or password.
At its core, the following command is used for changing the username:
The following command can also be used for changing a username:
wmic useraccount where "name='<User's Username>'" rename '<New Username>' wmic useraccount where "name='<User's Username>'" rename '<New Username>'
Similarly, the following command is used for changing the password:
Similarly, the following command can be for changing the password:
net user "<User's Username>" "<New Password>" net user "<User's Username>" "<New Password>"
@ -38,21 +36,17 @@ This function allows for changing the lockscreen image.
It works by taking ownership of the existing profile image files, and replacing them with the new image supplied by the user. It works by taking ownership of the existing profile image files, and replacing them with the new image supplied by the user.
This is a modified version of [LoganDark's lockscreen-img script](https://git.ameliorated.info/LoganDark/lockscreen-img).
#### Profile Image #### Profile Image
This function allows for changing the user's profile image (PFP). This function allows for changing the user's profile image (PFP).
It does this by taking ownership of the existing profile image files, and replacing them with the new image supplied by the user. Several necessary registry changes are made as well. It does this by taking ownership of the existing profile image files, and replacing them with the new image supplied by the user. Several necessary registry changes are made as well.
This is a modified version of [LoganDark's profile-img script](https://git.ameliorated.info/LoganDark/profile-img).
#### User Elevation #### User Elevation
This function allows for elevating or de-elevating the user to or from administrator. Elevating the user disables the password requirement when trying to run an executable as administrator. However, this has large security implications, thus why it is not the default setting. This function allows for elevating or de-elevating the user to or from administrator. Elevating the user disables the password requirement when trying to run an executable as administrator. However, this has large security implications, thus why it is not the default setting.
At its core, it uses the following command:
The following command can also be used for this purpose:
net localgroup administrators "<User's Username>" /add net localgroup administrators "<User's Username>" /add
@ -60,26 +54,6 @@ Or the following for de-elevating the user:
net localgroup administrators "<User's Username>" /delete net localgroup administrators "<User's Username>" /delete
#### Display Language
This function allows for changing the user's display language.
Firstly, it prompts the user to download a portion of a \~5.5GB language pack ISO file. Unfortunately, Microsoft no longer publicly distributes individual language pack files, so this is necessary.
Once the ISO is downloaded, it extracts the ISO file, and installs the language pack for the selected display language using the following commands:
7z e -y -o"<Script Path>\LangPacks" "<User's Desktop>\LangPacks.ISO" x64\langpacks\*.cab
lpksetup /i <Language/region ID> /p "<User's Desktop>\LangPacks\Microsoft-Windows-Client-Language-Pack_x64_<Language/region ID>.cab"
After the language pack is installed, the display language can finally be set. At its core, this is done by using the following commands:
PowerShell -NoP -C "Set-WinSystemLocale <Language/region ID>"
PowerShell -NoP -C "Set-WinUserLanguageList <Language/region ID>"
The Language/region ID for a given language can be found [here](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/available-language-packs-for-windows?view=windows-11#language-packs).
The script heavily enchances these simple commands. For instance, it keeps the existing keyboard input method (language), and let's the user decide whether or not to make the new language the default keyboard input method.
#### Keyboard Language #### Keyboard Language
These functions allow for adding or removing a keyboard language. These functions allow for adding or removing a keyboard language.
@ -100,7 +74,7 @@ To remove a keyboard language, it fetches the existing language list, filters ou
This function allows for disabling or enabling the username login requirement. This function allows for disabling or enabling the username login requirement.
At its core, it uses the following command:
The following command can also be used for this purpose:
reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v dontdisplaylastusername /f reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v dontdisplaylastusername /f
@ -112,9 +86,11 @@ Or the following for enabling the requirement:
This function allows for enabling or disabling the automatic login of the current user. This function allows for enabling or disabling the automatic login of the current user.
It does this by extracting an `AutoLogon.exe` file embedded within the script, and subsequently using it to enable AutoLogon.
It uses modified code from [rzander's AutoLogon program](https://github.com/rzander/AutoLogon), which can also be used for enabling AutoLogon.
#### .NET 3.5
The mentioned `AutoLogon.exe` program is a modified version of [rzander's AutoLogon program](https://github.com/rzander/AutoLogon).
This function allows for enabling or disabling .NET 3.5, requiring a Windows ISO or boot drive for installation.
## Extra Functions ## Extra Functions
@ -122,39 +98,7 @@ This section contains beta, legacy, or less used functions. Legacy functions are
#### Windows Subsystem for Linux (WSL) #### Windows Subsystem for Linux (WSL)
These functions allow for various WSL related actions.
##### Enable/Disable WSL
This function allows for enabling or disabling WSL functionality.
At its core, this is done by using the following command:
DISM /Online /Enable-Feature /FeatureName:Microsoft-Windows-Subsystem-Linux -NoRestart
Or the following for disabling the requirement:
DISM /Online /Disable-Feature /FeatureName:Microsoft-Windows-Subsystem-Linux -NoRestart
##### Install WSL Distro
This function allows for installing a WSL distribution.
Firstly, it fetches the distro download link from this git repository (`links.txt`), and downloads the distro from said link\*. Once the distro is downloaded, the script extracts and places the distro in `<User's Local AppData Folder>\AME-WSL`, and subsequently installs the distro by running the distro's `.exe` file contained within.
After the distro has been installed, the script sends several commands to the distro that apply the username and password(s) supplied by the user.
\*If the distro link includes apps.microsoft.com, [store.rg-adguard.net](https://store.rg-adguard.net/) is used to fetch the download link.
##### Remove WSL Distro
This function allows for removing a WSL distribution.
At its core, it does this by unregistering the distro using the following command:
WSL --unregister <WSL Distro>
And subsequently removing the distro's installation files located in `<User's Local AppData Folder>\AME-WSL`.
These functions are currently unavailable.
#### Hibernation #### Hibernation
@ -172,7 +116,7 @@ Or the following for disabling hibernation:
This function allows for enabling or disabling the Notification Center in the bottom right of the taskbar. This function allows for enabling or disabling the Notification Center in the bottom right of the taskbar.
At its core, it uses the following command:
The following command can also be used for this purpose:
reg add "HKU\<User's SID>\Software\Policies\Microsoft\Windows\Explorer" /v DisableNotificationCenter /t REG_DWORD /d 0 /f reg add "HKU\<User's SID>\Software\Policies\Microsoft\Windows\Explorer" /v DisableNotificationCenter /t REG_DWORD /d 0 /f
@ -184,7 +128,7 @@ Or the following for disabling the Notification Center:
This function allows for enabling or disabling desktop toast notifications. This function allows for enabling or disabling desktop toast notifications.
At its core, it uses the following command:
The following command can also be used for this purpose:
reg add "HKU\<User's SID>\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications" /v ToastEnabled /t REG_DWORD /d 1 /f reg add "HKU\<User's SID>\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications" /v ToastEnabled /t REG_DWORD /d 1 /f
@ -196,7 +140,7 @@ Or the following for disabling desktop notifications:
This function allows for enabling or disabling Windows Script Host (WSH). WSH is necessary for some programs. This function allows for enabling or disabling Windows Script Host (WSH). WSH is necessary for some programs.
At its core, the following commands are used:
The following command can also be used for this purpose:
reg add "HKU\<User's SID>\SOFTWARE\Microsoft\Windows Script Host\Settings" /v Enabled /t REG_DWORD /d 1 /f reg add "HKU\<User's SID>\SOFTWARE\Microsoft\Windows Script Host\Settings" /v Enabled /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings" /v Enabled /t REG_DWORD /d 1 /f reg add "HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings" /v Enabled /t REG_DWORD /d 1 /f
@ -210,7 +154,7 @@ Or the following for disabling WSH:
This function allows for enabling or disabling Visual Basic Script (VBS). VBS is necessary for some programs. This function allows for enabling or disabling Visual Basic Script (VBS). VBS is necessary for some programs.
At its core, the following command is used:
The following command can also be used for this purpose:
assoc .vbs=VBSFile assoc .vbs=VBSFile
@ -222,7 +166,7 @@ Or the following for disabling VBS:
This function allows for enabling or disabling NCSI Active Probing. Some applications require this to be enabled. This function allows for enabling or disabling NCSI Active Probing. Some applications require this to be enabled.
At its core, it uses the following command:
The following command can also be used for this purpose:
reg add "HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet" /v EnableActiveProbing /t REG_DWORD /d 1 /f reg add "HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet" /v EnableActiveProbing /t REG_DWORD /d 1 /f
@ -230,12 +174,6 @@ Or the following for disabling NCSI Active Probing:
reg add "HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet" /v EnableActiveProbing /t REG_DWORD /d 0 /f reg add "HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet" /v EnableActiveProbing /t REG_DWORD /d 0 /f
#### New User
This function allows for creating partially functional and pre-configured users in Windows AME.
To do this, it uses a standard user creation command, followed by many registry edits to make the new user usable.
#### NVIDIA Control Panel #### NVIDIA Control Panel
This function allows for installing or uninstalling NVIDIA Control Panel. This is useful since NVIDIA Control Panel no longer properly installs during a driver installation* due to it using an APPX deployment (Not supported in AME). This function allows for installing or uninstalling NVIDIA Control Panel. This is useful since NVIDIA Control Panel no longer properly installs during a driver installation* due to it using an APPX deployment (Not supported in AME).
@ -244,10 +182,10 @@ Firstly, it fetches the store link from this git repository (`links.txt`), and f
For removal, it simply removes the `<System Drive>\Program Files\NVIDIA Control Panel` directory, as well as the start menu shortcut. For removal, it simply removes the `<System Drive>\Program Files\NVIDIA Control Panel` directory, as well as the start menu shortcut.
Note: Even though NVIDIA Control Panel installation failes during a driver installation, it still creates the necessary NVIDIA Control Panel files in `<System Drive>\Program Files\WindowsApps`. If this is the case, the script will attempt to use those files instead of downloading them.
Note: Even though NVIDIA Control Panel installation fails during a driver installation, it still creates the necessary NVIDIA Control Panel files in `<System Drive>\Program Files\WindowsApps`. If this is the case, the script will attempt to use those files instead of downloading them.
\*Standard drivers do not have this issue, however those have been discontinued by NVIDIA.
\*Standard drivers do not have this issue, however, those have been discontinued by NVIDIA.
## Known Issues ## Known Issues
Some keyboard languages may not work, and a few are improperly tagged.
Some keyboard languages may not work, and a few may be improperly tagged.

+ 0
- 3948
amecs.cmd
File diff suppressed because it is too large
View File


BIN
screenshot.png View File

Before After
Width: 732  |  Height: 590  |  Size: 30 KiB Width: 732  |  Height: 538  |  Size: 34 KiB

BIN
src/7z.dll View File


+ 132
- 0
src/Actions/.NET.cs View File

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using amecs.Misc;
using Ameliorated.ConsoleUtils;
using Microsoft.Dism;
namespace amecs.Actions
{
public class _NET
{
private static string _mountedPath;
private static string _isoPath;
private static void Unmount()
{
if (_isoPath == "none")
return;
SelectWindowsImage.DismountIso(_isoPath);
}
public static bool Install()
{
(_mountedPath, _isoPath, _, _, _) = SelectWindowsImage.GetMediaPath(true);
if (_mountedPath == null) return false;
if (!Directory.Exists(_mountedPath + @"\sources\sxs") || !Directory.GetFiles(_mountedPath + @"\sources\sxs", "*netfx3*").Any())
{
Unmount();
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("ISO/USB/folder does not contain the required files.",
ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " });
return false;
}
ConsoleTUI.OpenFrame.WriteCentered("\r\nInstalling .NET 3.5");
var topCache = Console.CursorTop;
var leftCache = Console.CursorLeft;
Console.WriteLine();
var inProgress = false;
try
{
using var indicator = new ConsoleUtils.LoadingIndicator();
DismApi.Initialize(DismLogLevel.LogErrors);
using (var session = DismApi.OpenOnlineSession())
{
var stdout = GetStdHandle(-11);
var indicatorStopped = false;
var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5);
DismApi.EnableFeatureByPackagePath(session, "NetFX3", null, true, true, new List<string>() { _mountedPath + @"\sources\sxs" }, delegate(DismProgress progress)
{
inProgress = true;
if (!indicatorStopped)
{
indicator.Stop();
Console.SetCursorPosition(leftCache, topCache);
Console.WriteLine(" ");
}
indicatorStopped = true;
var progressPercentage = progress.Current / 10;
var currentHashTags = (int)Math.Ceiling(Math.Min(((double)progressPercentage / 100) * maxHashTags, maxHashTags));
var spaces = maxHashTags - currentHashTags + (4 - progressPercentage.ToString().Length);
var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + progressPercentage + "%");
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out _);
inProgress = false;
});
session.Close();
Thread.Sleep(100);
var sb = new StringBuilder(new string('#', maxHashTags) + " 100%");
uint throwaway;
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway);
}
DismApi.Shutdown();
Unmount();
} catch (Exception e)
{
while (inProgress)
{
Thread.Sleep(50);
}
Unmount();
Console.WriteLine();
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("DISM error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt()
{
AnyKey = true,
Text = "Press any key to return to the Menu: "
});
return false;
}
Console.WriteLine();
Console.WriteLine();
ConsoleTUI.OpenFrame.Close(".NET 3.5 installed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
AnyKey = true,
Text = "Press any key to return to the Menu: "
});
return true;
}
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public COORD(short X, short Y)
{
this.X = X;
this.Y = Y;
}
};
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteConsoleOutputCharacter(IntPtr hConsoleOutput, StringBuilder lpCharacter, uint nLength, Languages.COORD dwWriteCoord, out uint lpNumberOfCharsWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
}
}

+ 313
- 0
src/Actions/AutoLogon.cs View File

@ -0,0 +1,313 @@
using System;
using System.DirectoryServices.AccountManagement;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Ameliorated.ConsoleUtils;
namespace amecs.Actions
{
public class AutoLogon
{
internal static class SafeNativeMethods
{
#region Structures
[StructLayout(LayoutKind.Sequential)]
public struct LSA_UNICODE_STRING : IDisposable
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr Buffer;
public void Dispose()
{
this = new LSA_UNICODE_STRING();
}
}
public struct LSA_OBJECT_ATTRIBUTES
{
public int Length;
public IntPtr RootDirectory;
public LSA_UNICODE_STRING ObjectName;
public UInt32 Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
public enum LSA_AccessPolicy : long
{
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,
POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,
POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,
POLICY_TRUST_ADMIN = 0x00000008L,
POLICY_CREATE_ACCOUNT = 0x00000010L,
POLICY_CREATE_SECRET = 0x00000020L,
POLICY_CREATE_PRIVILEGE = 0x00000040L,
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,
POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,
POLICY_AUDIT_LOG_ADMIN = 0x00000200L,
POLICY_SERVER_ADMIN = 0x00000400L,
POLICY_LOOKUP_NAMES = 0x00000800L,
POLICY_NOTIFICATION = 0x00001000L
}
#endregion
#region DLL Imports
[DllImport("advapi32")]
public static extern IntPtr FreeSid(IntPtr pSid);
[DllImport("advapi32.dll", PreserveSig = true)]
public static extern UInt32 LsaOpenPolicy(
ref LSA_UNICODE_STRING SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
Int32 DesiredAccess,
out IntPtr PolicyHandle);
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaStorePrivateData(
IntPtr PolicyHandle,
LSA_UNICODE_STRING[] KeyName,
LSA_UNICODE_STRING[] PrivateData);
[DllImport("advapi32.dll", PreserveSig = true)]
public static extern uint LsaRetrievePrivateData(
IntPtr PolicyHandle,
LSA_UNICODE_STRING[] KeyName,
out IntPtr PrivateData);
[DllImport("advapi32.dll", PreserveSig = true)]
public static extern uint LsaNtStatusToWinError(uint status);
[DllImport("advapi32.dll")]
public static extern uint LsaClose(IntPtr ObjectHandle);
#endregion
}
#region Functions
/// <summary>
/// Store Encrypted Data
/// </summary>
/// <param name="keyName"></param>
/// <param name="Data"></param>
/// <returns></returns>
public static long StoreData(String keyName, String Data)
{
long winErrorCode = 0;
IntPtr sid = IntPtr.Zero;
int sidSize = 0;
//allocate buffers
sid = Marshal.AllocHGlobal(sidSize);
//initialize an empty unicode-string
SafeNativeMethods.LSA_UNICODE_STRING systemName = new SafeNativeMethods.LSA_UNICODE_STRING();
//Set desired access rights (requested rights)
int access = (int)(SafeNativeMethods.LSA_AccessPolicy.POLICY_CREATE_SECRET);
//initialize a pointer for the policy handle
IntPtr policyHandle = IntPtr.Zero;
//these attributes are not used, but LsaOpenPolicy wants them to exists
SafeNativeMethods.LSA_OBJECT_ATTRIBUTES ObjectAttributes = new SafeNativeMethods.LSA_OBJECT_ATTRIBUTES();
ObjectAttributes.Length = 0;
ObjectAttributes.RootDirectory = IntPtr.Zero;
ObjectAttributes.Attributes = 0;
ObjectAttributes.SecurityDescriptor = IntPtr.Zero;
ObjectAttributes.SecurityQualityOfService = IntPtr.Zero;
//get a policy handle
uint resultPolicy = SafeNativeMethods.LsaOpenPolicy(ref systemName, ref ObjectAttributes, access, out policyHandle);
winErrorCode = SafeNativeMethods.LsaNtStatusToWinError(resultPolicy);
if (winErrorCode != 0)
{
ConsoleTUI.OpenFrame.WriteCenteredLine("OpenPolicy failed: " + winErrorCode);
}
else
{
//initialize an unicode-string for the keyName
SafeNativeMethods.LSA_UNICODE_STRING[] uKeyName = new SafeNativeMethods.LSA_UNICODE_STRING[1];
uKeyName[0] = new SafeNativeMethods.LSA_UNICODE_STRING();
uKeyName[0].Buffer = Marshal.StringToHGlobalUni(keyName);
uKeyName[0].Length = (UInt16)(keyName.Length * UnicodeEncoding.CharSize);
uKeyName[0].MaximumLength = (UInt16)((keyName.Length + 1) * UnicodeEncoding.CharSize);
//initialize an unicode-string for the Data to encrypt
SafeNativeMethods.LSA_UNICODE_STRING[] uData = new SafeNativeMethods.LSA_UNICODE_STRING[1];
uData[0] = new SafeNativeMethods.LSA_UNICODE_STRING();
uData[0].Buffer = Marshal.StringToHGlobalUni(Data);
uData[0].Length = (UInt16)(Data.Length * UnicodeEncoding.CharSize);
uData[0].MaximumLength = (UInt16)((Data.Length + 1) * UnicodeEncoding.CharSize);
//Store Encrypted Data:
SafeNativeMethods.LsaStorePrivateData(policyHandle, uKeyName, uData);
//winErrorCode = LsaNtStatusToWinError(res);
if (winErrorCode != 0)
{
ConsoleTUI.OpenFrame.WriteCenteredLine("LsaStorePrivateData failed: " + winErrorCode);
}
SafeNativeMethods.LsaClose(policyHandle);
}
SafeNativeMethods.FreeSid(sid);
return winErrorCode;
}
/// <summary>
/// Retrieve Encrypted Data
/// </summary>
/// <param name="keyName"></param>
/// <returns></returns>
public static string RetrieveData(String keyName)
{
string sout = "";
long winErrorCode = 0;
IntPtr sid = IntPtr.Zero;
int sidSize = 0;
//allocate buffers
sid = Marshal.AllocHGlobal(sidSize);
//initialize an empty unicode-string
SafeNativeMethods.LSA_UNICODE_STRING systemName = new SafeNativeMethods.LSA_UNICODE_STRING();
//Set desired access rights (requested rights)
int access = (int)(SafeNativeMethods.LSA_AccessPolicy.POLICY_CREATE_SECRET);
//initialize a pointer for the policy handle
IntPtr policyHandle = IntPtr.Zero;
//these attributes are not used, but LsaOpenPolicy wants them to exists
SafeNativeMethods.LSA_OBJECT_ATTRIBUTES ObjectAttributes = new SafeNativeMethods.LSA_OBJECT_ATTRIBUTES();
ObjectAttributes.Length = 0;
ObjectAttributes.RootDirectory = IntPtr.Zero;
ObjectAttributes.Attributes = 0;
ObjectAttributes.SecurityDescriptor = IntPtr.Zero;
ObjectAttributes.SecurityQualityOfService = IntPtr.Zero;
//get a policy handle
uint resultPolicy = SafeNativeMethods.LsaOpenPolicy(ref systemName, ref ObjectAttributes, access, out policyHandle);
winErrorCode = SafeNativeMethods.LsaNtStatusToWinError(resultPolicy);
if (winErrorCode != 0)
{
ConsoleTUI.OpenFrame.WriteCenteredLine("OpenPolicy failed: " + winErrorCode);
}
else
{
//initialize an unicode-string for the keyName
SafeNativeMethods.LSA_UNICODE_STRING[] uKeyName = new SafeNativeMethods.LSA_UNICODE_STRING[1];
uKeyName[0] = new SafeNativeMethods.LSA_UNICODE_STRING();
uKeyName[0].Buffer = Marshal.StringToHGlobalUni(keyName);
uKeyName[0].Length = (UInt16)(keyName.Length * UnicodeEncoding.CharSize);
uKeyName[0].MaximumLength = (UInt16)((keyName.Length + 1) * UnicodeEncoding.CharSize);
//Store Encrypted Data:
IntPtr pData;
long result = SafeNativeMethods.LsaRetrievePrivateData(policyHandle, uKeyName, out pData);
//winErrorCode = LsaNtStatusToWinError(res);
if (winErrorCode != 0)
{
ConsoleTUI.OpenFrame.WriteCenteredLine("LsaStorePrivateData failed: " + winErrorCode);
}
SafeNativeMethods.LSA_UNICODE_STRING ss = (SafeNativeMethods.LSA_UNICODE_STRING)Marshal.PtrToStructure(pData, typeof(SafeNativeMethods.LSA_UNICODE_STRING));
sout = Marshal.PtrToStringAuto(ss.Buffer);
SafeNativeMethods.LsaClose(policyHandle);
}
SafeNativeMethods.FreeSid(sid);
return sout;
}
#endregion
private const string LogonKey = @"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon";
public static bool Disable() => amecs.RunBasicAction("Disabling AutoLogon", "AutoLogon disabled successfully", new Action(() =>
{
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultUserName", Data = "", Type = Reg.RegistryValueType.REG_SZ}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoAdminLogon", Operation = Reg.RegistryValueOperation.Delete}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoLogonCount", Operation = Reg.RegistryValueOperation.Delete}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "ForceAutoLogon", Operation = Reg.RegistryValueOperation.Delete}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "DisableCAD", Operation = Reg.RegistryValueOperation.Delete}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultPassword", Operation = Reg.RegistryValueOperation.Delete}.Apply();
StoreData("DefaultPassword", "");
Thread.Sleep(1700);
}));
public static bool Enable()
{
PrincipalContext context = new PrincipalContext(ContextType.Machine);
string password = "";
while (true)
{
password = new InputPrompt() { MaskInput = true, Text = "Enter your password, or press escape to quit: " }.Start();
if (password == null)
return true;
if (String.IsNullOrEmpty(password))
{
try
{
Globals.User.ChangePassword("", "");
break;
} catch {}
}
else if (context.ValidateCredentials(Globals.Username, password))
break;
ConsoleTUI.OpenFrame.WriteLine("Incorrect password.");
Console.WriteLine();
}
try
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nEnabling AutoLogon");
using (new ConsoleUtils.LoadingIndicator(true))
{
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultUserName", Data = Globals.Username, Type = Reg.RegistryValueType.REG_SZ}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultDomainName", Data = Environment.MachineName, Type = Reg.RegistryValueType.REG_SZ}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoAdminLogon", Data = 1, Type = Reg.RegistryValueType.REG_DWORD}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoLogonCount", Operation = Reg.RegistryValueOperation.Delete}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "DisableCAD", Data = 1, Type = Reg.RegistryValueType.REG_DWORD}.Apply();
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultPassword", Operation = Reg.RegistryValueOperation.Delete}.Apply();
StoreData("DefaultPassword", password);
Thread.Sleep(1700);
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt()
{
AnyKey = true,
Text = "Press any key to return to the Menu: "
});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close($"AutoLogon enabled successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
AnyKey = true,
Text = "Press any key to return to the Menu: "
});
return true;
}
}
}

+ 239
- 0
src/Actions/Deameliorate.cs View File

@ -0,0 +1,239 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Principal;
using System.Threading;
using amecs.Misc;
using Ameliorated.ConsoleUtils;
using Microsoft.Win32;
namespace amecs.Actions
{
public class Deameliorate
{
private static string _mountedPath;
private static string _winVer;
private static string _win11Setup = "";
private static bool _win11 = Environment.OSVersion.Version.Build >= 22000;
private const string ExplorerPatcherId = "D17F1E1A-5919-4427-8F89-A1A8503CA3EB";
public static bool DeAme()
{
if (new ChoicePrompt()
{
Text = @"
This will de-ameliorate by reinstalling Windows.
Although user data should be kept, we strongly recommend
making backups of any important user data.
Continue? (Y/N): "
}.Start().Value == 1) return true;
Program.Frame.Clear();
(_mountedPath, _, _winVer, _, _) = SelectWindowsImage.GetMediaPath();
if (_mountedPath == null) return false;
if (new ChoicePrompt {Text = $"\r\nYour Windows image is {_winVer}. Continue? (Y/N): "}.Start().Value == 1)
return true;
var fc = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
string userSid = null;
try
{
NSudo.GetSystemPrivilege();
NSudo.RunAsUser(() =>
{
userSid = WindowsIdentity.GetCurrent().User.ToString();
});
}
catch
{
// do nothing
}
try
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling AME-installed UI software...");
string openShellId = null;
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (var item in key.GetSubKeyNames())
{
try
{
if (((string)key.OpenSubKey(item).GetValue("DisplayName")).Equals("Open-Shell"))
openShellId = item;
}
catch
{
// do nothing
}
}
if (openShellId != null)
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling Open-Shell...");
Process.Start("MsiExec.exe", $"/X{openShellId} /quiet")?.WaitForExit();
if (userSid != null)
{
var appData = (string)Registry.Users.OpenSubKey(userSid + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders").GetValue("AppData");
if (Directory.Exists(Path.Combine(appData, "OpenShell")))
Directory.Delete(Path.Combine(appData, "OpenShell"), true);
}
}
var epSetupPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}\ExplorerPatcher\ep_setup.exe";
if (File.Exists(epSetupPath))
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling ExplorerPatcher...");
var winlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
winlogon?.SetValue("AutoRestartShell", 0);
// kill processes that the files use
foreach (var processName in new[] {"explorer.exe", "rundll32.exe", "dllhost.exe", "ShellExperienceHost.exe", "StartMenuExperienceHost.exe"})
{
foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(processName)))
{
process.Kill();
process.WaitForExit();
}
}
// delete DWM service that removes rounded corners
Process.Start("sc", $"stop \"ep_dwm_{ExplorerPatcherId}\"")?.WaitForExit();
Process.Start("sc", $"delete \"ep_dwm_{ExplorerPatcherId}\"")?.WaitForExit();
// remove registered DLL
var explorerPatcherDllPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "ExplorerPatcher", "ExplorerPatcher.amd64.dll");
Process.Start("regsvr32.exe", $"/s /u \"{explorerPatcherDllPath}\"")?.WaitForExit();
// delete files
foreach (var file in new[]
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"SystemApps\ShellExperienceHost_cw5n1h2txyewy\dxgi.dll"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"SystemApps\ShellExperienceHost_cw5n1h2txyewy\wincorlib.dll"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"SystemApps\ShellExperienceHost_cw5n1h2txyewy\wincorlib_orig.dll"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\dxgi.dll"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\wincorlib.dll"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\wincorlib_orig.dll"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
"dxgi.dll")
})
{
if (File.Exists(file)) File.Delete(file);
}
foreach (var folder in new[]
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
"ExplorerPatcher"),
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
@"Microsoft\Windows\Start Menu\Programs\ExplorerPatcher")
})
{
if (Directory.Exists(folder)) Directory.Delete(folder, true);
}
winlogon?.SetValue("AutoRestartShell", 1);
}
Program.Frame.Clear();
} catch (Exception e)
{
ConsoleTUI.OpenFrame.Close(
"Error when uninstalling software: " + e.Message,
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = "Press any key to continue anyways: " });
Program.Frame.Clear();
ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without uninstalling software...\r\n");
}
// restart Explorer
if (Process.GetProcessesByName("explorer").Length == 0)
NSudo.RunProcessAsUser(NSudo.GetUserToken(), "explorer.exe", "", 0);
// all policies are cleared as a user that's de-ameliorating is unlikely to have their own policies in the first place
// also clear ExplorerPatcher Registry entries
ConsoleTUI.OpenFrame.WriteCentered("\r\nClearing policies...");
foreach (var keyPath in new[] {
$@"HKU\{userSid}\Software\Microsoft\Windows\CurrentVersion\Policies",
$@"HKU\{userSid}\Software\Policies",
$@"HKU\{userSid}\Software\ExplorerPatcher",
$@"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{{ExplorerPatcherId}}}_ExplorerPatcher",
@"HKLM\Software\Microsoft\Windows\CurrentVersion\Policies",
@"HKLM\Software\Policies",
@"HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies"
})
{
var hive = RegistryHive.LocalMachine;
if (keyPath.StartsWith("HKU"))
hive = RegistryHive.Users;
var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default);
var subKeyPath = keyPath.Substring(keyPath.IndexOf('\\') + 1);
var key = baseKey.OpenSubKey(subKeyPath, true);
if (key == null) continue;
try
{
baseKey.DeleteSubKeyTree(subKeyPath);
}
catch
{
// do nothing - some values might fail, but almost all are deleted
}
key.Close();
}
Thread.Sleep(3000);
Program.Frame.Clear();
ConsoleTUI.OpenFrame.WriteCentered("\r\nCompleted initial setup!", ConsoleColor.Green);
if (_win11)
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nWindows Setup will display as 'Windows Server,' but it's not actually installing Windows Server and is only set as such to bypass hardware requirements.");
Console.WriteLine();
}
ConsoleTUI.OpenFrame.WriteCentered("\r\nWaiting 10 seconds and starting Windows Setup...");
Console.ForegroundColor = fc;
Thread.Sleep(10000);
Console.WriteLine();
try
{
if (_win11) _win11Setup = "/Product Server";
Process.Start(Path.Combine(_mountedPath, "setup.exe"), $"/Auto Upgrade /DynamicUpdate Disable {_win11Setup}");
} catch (Exception e)
{
ConsoleTUI.OpenFrame.Close(
$"There was an error when trying to run the Windows Setup: {e}\r\nTry running the Windows Setup manually from File Explorer.",
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = $"Press any key to exit: " });
return false;
}
ConsoleTUI.OpenFrame.Close(
"Completed, Windows Setup should have started.",
ConsoleColor.Cyan, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = $"Press any key to go back: " });
return true;
}
}
}

+ 21
- 0
src/Actions/Elevation.cs View File

@ -0,0 +1,21 @@
using System;
using System.Threading;
namespace amecs.Actions
{
public class Elevation
{
public static bool Elevate() => amecs.RunBasicAction("Elevating user to Administrator", "The current user is now an Administrator", new Action(() =>
{
Globals.Administrators.Members.Add(Globals.User);
Globals.Administrators.Save();
Thread.Sleep(1000);
}), true);
public static bool DeElevate() => amecs.RunBasicAction("Revoking Admin rights from the current user", "Admin rights have been revoked for the current user", new Action(() =>
{
Globals.Administrators.Members.Remove(Globals.User);
Globals.Administrators.Save();
Thread.Sleep(1000);
}), true);
}
}

+ 1089
- 0
src/Actions/Languages.cs
File diff suppressed because it is too large
View File


+ 113
- 0
src/Actions/Lockscreen.cs View File

@ -0,0 +1,113 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading;
using Ameliorated.ConsoleUtils;
using Microsoft.Win32;
using System.Windows.Forms;
namespace amecs.Actions
{
public class Lockscreen
{
public static bool ChangeImage()
{
ConsoleTUI.OpenFrame.WriteCenteredLine("Select an image");
Thread.Sleep(1000);
var dialog = new System.Windows.Forms.OpenFileDialog();
dialog.Filter = "Image Files (*.jpg; *.jpeg; *.png; *.bmp; *.jfif)| *.jpg; *.jpeg; *.png; *.bmp; *.jfif"; // Filter files by extension
dialog.Multiselect = false;
dialog.InitialDirectory = Globals.UserFolder;
NativeWindow window = new NativeWindow();
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle);
if (dialog.ShowDialog(window) == DialogResult.OK)
{
string file;
try
{
file = dialog.FileName;
}
catch (SecurityException e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Security error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
var choice = new ChoicePrompt() { Text = "Remove lockscreen blur? (Y/N): " }.Start();
if (!choice.HasValue) return true;
bool blur = choice == 0;
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting lockscreen image");
using (new ConsoleUtils.LoadingIndicator(true))
{
Thread.Sleep(500);
try
{
if (blur)
new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Policies\Microsoft\Windows\System",
ValueName = "DisableAcrylicBackgroundOnLogon",
Type = Reg.RegistryValueType.REG_DWORD,
Data = 1,
}.Apply();
else
new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Policies\Microsoft\Windows\System",
ValueName = "DisableAcrylicBackgroundOnLogon",
Type = Reg.RegistryValueType.REG_DWORD,
Data = 0,
}.Apply();
} catch { }
new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Creative\" + Globals.UserSID,
ValueName = "RotatingLockScreenEnabled",
Type = Reg.RegistryValueType.REG_DWORD,
Data = 0,
}.Apply();
new Reg.Value()
{
KeyName = @$"HKU\{Globals.UserSID}\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager",
ValueName = "RotatingLockScreenEnabled",
Type = Reg.RegistryValueType.REG_DWORD,
Data = 0,
}.Apply();
File.Delete(Environment.ExpandEnvironmentVariables(@"%WINDIR%\Web\Screen\img100.jpg"));
File.Copy(file, Environment.ExpandEnvironmentVariables(@"%WINDIR%\Web\Screen\img100.jpg"));
foreach (var dataDir in Directory.EnumerateDirectories(Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\Microsoft\Windows\SystemData")))
{
var subDir = Path.Combine(dataDir, "ReadOnly");
if (!Directory.Exists(subDir))
continue;
Directory.GetDirectories(subDir, "Lockscreen_*").ToList().ForEach(x => Directory.Delete(x, true));
}
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Lockscreen image changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
else
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("You must select an image.", new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
}
}
}

+ 124
- 0
src/Actions/Profile.cs View File

@ -0,0 +1,124 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading;
using System.Windows.Forms;
using Ameliorated.ConsoleUtils;
using System.Drawing;
using System.Security.AccessControl;
using System.Security.Principal;
namespace amecs.Actions
{
public class Profile
{
public static bool ChangeImage()
{
ConsoleTUI.OpenFrame.WriteCenteredLine("Select an image");
Thread.Sleep(1000);
var dialog = new System.Windows.Forms.OpenFileDialog();
dialog.Filter = "Image Files (*.jpg; *.jpeg; *.png; *.bmp; *.jfif)| *.jpg; *.jpeg; *.png; *.bmp; *.jfif"; // Filter files by extension
dialog.Multiselect = false;
dialog.InitialDirectory = Globals.UserFolder;
NativeWindow window = new NativeWindow();
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle);
if (dialog.ShowDialog(window) == DialogResult.OK)
{
string file;
try
{
file = dialog.FileName;
}
catch (SecurityException e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Security error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting profile image");
using (new ConsoleUtils.LoadingIndicator(true))
{
var pfpDir = Path.Combine(Environment.ExpandEnvironmentVariables("%PUBLIC%\\AccountPictures"), Globals.UserSID);
if (Directory.Exists(pfpDir))
{
try
{
Directory.Delete(pfpDir, true);
} catch (Exception e)
{
var logdi = new DirectoryInfo(pfpDir) { Attributes = FileAttributes.Normal };
try
{
NSudo.GetOwnershipPrivilege();
var logdirsec = logdi.GetAccessControl();
logdirsec.SetOwner(WindowsIdentity.GetCurrent().User);
logdi.SetAccessControl(logdirsec);
logdirsec = new DirectorySecurity();
logdirsec.AddAccessRule(new FileSystemAccessRule(WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
logdi.SetAccessControl(logdirsec);
} catch (Exception exception)
{
}
foreach (var info in logdi.GetFileSystemInfos("*", SearchOption.AllDirectories))
{
info.Attributes = FileAttributes.Normal;
}
Directory.Delete(pfpDir, true);
}
}
Directory.CreateDirectory(pfpDir);
var image = Image.FromFile(file);
var pfpKey = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\" + Globals.UserSID;
new Reg.Key() { KeyName = pfpKey, Operation = RegistryOperation.Delete }.Apply();
foreach (var res in new [] { 32, 40, 48, 64, 96, 192, 208, 240, 424, 448, 1080 })
{
var bitmap = new Bitmap(res, res);
var graph = Graphics.FromImage(bitmap);
graph.DrawImage(image, 0, 0, res, res);
var saveLoc = Path.Combine(pfpDir, $"{res}x{res}.png");
bitmap.Save(saveLoc);
new Reg.Value() { KeyName = pfpKey, ValueName = "Image" + res, Type = Reg.RegistryValueType.REG_SZ, Data = saveLoc }.Apply();
}
new Reg.Value() { KeyName = pfpKey, ValueName = "UserPicturePath", Type = Reg.RegistryValueType.REG_SZ, Data = Path.Combine(pfpDir, $"448x448.png") }.Apply();
try
{
Process proc = new Process();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.FileName = "gpupdate.exe";
proc.StartInfo.Arguments = "/force";
proc.Start();
proc.WaitForExit(20000);
} catch { }
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Profile image changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
else
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("You must select an image.", new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
}
}
}

+ 220
- 0
src/Actions/UserPass.cs View File

@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using Ameliorated.ConsoleUtils;
using System.Linq;
using System.Security;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace amecs.Actions
{
public static class UserPass
{
public static bool ShowMenu()
{
var mainMenu = new Ameliorated.ConsoleUtils.Menu()
{
Choices =
{
new Menu.MenuItem("Change Username", new Func<bool>(ChangeUsername)),
new Menu.MenuItem("Change Password", new Func<bool>(ChangePassword)),
new Menu.MenuItem("Change Display Name", new Func<bool>(ChangeDisplayName)),
new Menu.MenuItem("Change Administrator Password", new Func<bool>(ChangeAdminPassword)),
Menu.MenuItem.Blank,
new Menu.MenuItem("Return to Menu", new Func<bool>(() => true)),
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)),
},
SelectionForeground = ConsoleColor.Green
};
mainMenu.Write();
var result = (Func<bool>)mainMenu.Load();
return result.Invoke();
}
public static bool ChangeUsername()
{
try
{
while (true)
{
var username = new InputPrompt() { Text = "Enter new username, or press escape to quit: " }.Start();
if (username == null)
return true;
if (String.IsNullOrEmpty(username) || !Regex.Match(username, @"^\w[\w\.\- ]{0,19}$").Success)
{
ConsoleTUI.OpenFrame.WriteLine("Username is invalid.");
Console.WriteLine();
continue;
}
if (Globals.Username.Equals(username))
{
ConsoleTUI.OpenFrame.WriteLine("Username matches the current username.");
Console.WriteLine();
continue;
}
try
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new username");
using (new ConsoleUtils.LoadingIndicator(true))
{
DirectoryEntry entry = (DirectoryEntry)Globals.User.GetUnderlyingObject();
entry.Rename(username);
entry.CommitChanges();
PrincipalContext context = new PrincipalContext(ContextType.Machine);
PrincipalSearcher userPrincipalSearcher = new PrincipalSearcher(new UserPrincipal(context));
Globals.User = userPrincipalSearcher.FindAll().FirstOrDefault(x => (x is UserPrincipal) && x.Sid.Value == Globals.UserSID) as UserPrincipal;
break;
}
} catch (System.Runtime.InteropServices.COMException e)
{
if (e.ErrorCode != -2147022694)
throw e;
ConsoleTUI.OpenFrame.WriteLine("Username is invalid.");
Console.WriteLine();
}
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
if ((int?)ConsoleTUI.OpenFrame.Close("Username changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
TextForeground = ConsoleColor.Yellow,
Text = "Logoff to apply changes? (Y/N): "
}) == 0) amecs.RestartWindows(true);
return true;
}
public static bool ChangePassword()
{
try
{
while (true)
{
var password = new InputPrompt() { MaskInput = true, Text = "Enter new password, or press escape to quit: " }.Start();
if (password == null)
return true;
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new password");
try
{
using (new ConsoleUtils.LoadingIndicator(true))
{
if (String.IsNullOrEmpty(password))
{
Globals.User.SetPassword("");
}
else
{
Globals.User.SetPassword(password);
}
Thread.Sleep(800);
break;
}
} catch (PasswordException e)
{
ConsoleTUI.OpenFrame.WriteLine("Could not set password: " + e.Message);
Console.WriteLine();
}
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Password changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
public static bool ChangeAdminPassword()
{
try
{
PrincipalContext context = new PrincipalContext(ContextType.Machine);
PrincipalSearcher userPrincipalSearcher = new PrincipalSearcher(new UserPrincipal(context));
var administrator = userPrincipalSearcher.FindAll().FirstOrDefault(x => (x is UserPrincipal) && x.Name == "Administrator") as UserPrincipal;
while (true)
{
var password = new InputPrompt() { MaskInput = true, Text = "Enter new Administrator password,\r\nor press escape to quit: " }.Start();
if (password == null)
return true;
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new password");
try
{
using (new ConsoleUtils.LoadingIndicator(true))
{
if (String.IsNullOrEmpty(password))
{
administrator.SetPassword("");
}
else
{
administrator.SetPassword(password);
}
Thread.Sleep(1000);
break;
}
} catch (PasswordException e)
{
ConsoleTUI.OpenFrame.WriteLine("Could not set password: " + e.Message);
Console.WriteLine();
}
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Administrator password changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
public static bool ChangeDisplayName()
{
try
{
var name = new InputPrompt() { Text = "Enter new display name, or press escape to quit: " }.Start();
if (name == null)
return true;
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new display name");
using (new ConsoleUtils.LoadingIndicator(true))
{
Globals.User.DisplayName = name;
Globals.User.Save();
Thread.Sleep(800);
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Display name changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
}
}

+ 19
- 0
src/Actions/UsernameRequirement.cs View File

@ -0,0 +1,19 @@
using System;
using System.Threading;
namespace amecs.Actions
{
public class UsernameRequirement
{
public static bool Enable() => amecs.RunBasicAction("Enabling username login requirement", "The username login requirement is now enabled", new Action(() =>
{
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", ValueName = "dontdisplaylastusername", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
Thread.Sleep(1700);
}));
public static bool Disable() => amecs.RunBasicAction("Disabling username login requirement", "The username login requirement is now disabled", new Action(() =>
{
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", ValueName = "dontdisplaylastusername", Operation = Reg.RegistryValueOperation.Delete }.Apply();
Thread.Sleep(1700);
}));
}
}

+ 299
- 0
src/Actions/Users.cs View File

@ -0,0 +1,299 @@
using System;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
using System.ServiceProcess;
using System.Text.RegularExpressions;
using System.Threading;
using Ameliorated.ConsoleUtils;
using Microsoft.Win32;
namespace amecs.Actions
{
public class Users
{
public static bool ShowMenu()
{
while (true)
{
Program.Frame.Clear();
var mainMenu = new Ameliorated.ConsoleUtils.Menu()
{
Choices =
{
Globals.WinVer <= 19043 ?
new Menu.MenuItem("Create New User (Legacy)", new Func<bool>(CreateNewUserLegacy)) :
new Menu.MenuItem("Create New User", new Func<bool>(CreateNewUser)),
Menu.MenuItem.Blank,
new Menu.MenuItem("Return to Menu", null),
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit))
},
SelectionForeground = ConsoleColor.Green
};
Func<bool> result;
try
{
mainMenu.Write();
var res = mainMenu.Load();
if (res == null)
return true;
result = (Func<bool>)res;
} catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
return false;
}
try
{
result.Invoke();
} catch (Exception e)
{
ConsoleTUI.ShowErrorBox("Error while running an action: " + e.ToString(), null);
}
}
}
private static bool CreateNewUserLegacy()
{
var choice = new ChoicePrompt() { Text = "WARNING: This is a deprecated action, and the new user\r\nwill not be fully functional. Continue? (Y/N): ", TextForeground = ConsoleColor.Yellow}.Start();
if (choice == null || choice == 1)
return false;
ConsoleTUI.OpenFrame.WriteLine();
try
{
if (CreateUser() == false)
return true;
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
ConsoleTUI.OpenFrame.WriteCentered("\r\nConfiguring user");
try
{
using (new ConsoleUtils.LoadingIndicator(true))
{
try { ServiceController.GetServices().First(x => x.ServiceName.Equals("AppReadiness")).Stop(); } catch (Exception e) { }
NSudo.GetOwnershipPrivilege();
Reg.AcquirePrivileges();
var subKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\AppReadiness\Parameters", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);
if (subKey != null)
{
var sec = subKey.GetAccessControl();
sec.SetOwner(new NTAccount("SYSTEM"));
subKey.SetAccessControl(sec);
subKey.Close();
subKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\AppReadiness\Parameters", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions);
sec = subKey.GetAccessControl();
sec.AddAccessRule(new RegistryAccessRule("SYSTEM", RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
subKey.SetAccessControl(sec);
}
new Reg.Key() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\AppReadiness" }.Apply();
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Policies\Microsoft\Windows\OOBE", ValueName = "DisablePrivacyExperience", Data = 1, Type = Reg.RegistryValueType.REG_DWORD}.Apply();
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", ValueName = "EnableFirstLogonAnimation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD}.Apply();
Reg.LoadDefaultUserHive();
try
{
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\OpenShell", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\OpenShell\Settings", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer\Settings", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer", ValueName = "ShowedToolbar", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer", ValueName = "NewLine", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer\Settings", ValueName = "ShowStatusBar", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "ShowedStyle2", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "CSettingsDlg", Data = "c80100001a0100000000000000000000360d00000100000000000000", Type = Reg.RegistryValueType.REG_BINARY }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "OldItems", Data = "00", Type = Reg.RegistryValueType.REG_BINARY }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "ItemRanks", Data = "00", Type = Reg.RegistryValueType.REG_BINARY }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\MRU", ValueName = "0", Data = @"%SYSTEMDRIVE%\Windows\regedit.exe", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "Version", Data = 04040098, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "AllProgramsMetro", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "RecentMetroApps", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "StartScreenShortcut", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SearchInternet", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "GlassOverride", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "GlassColor", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkinW7", Data = "Fluent-Metro", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkinVariationW7", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkipMetro", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "MenuItems7", Data = @"Item1.Command=user_files\0Item1.Settings=NOEXPAND\0Item2.Command=user_documents\0Item2.Settings=NOEXPAND\0Item3.Command=user_pictures\0Item3.Settings=NOEXPAND\0Item4.Command=user_music\0Item4.Settings=NOEXPAND\0Item5.Command=user_videos\0Item5.Settings=NOEXPAND\0Item6.Command=downloads\0Item6.Settings=NOEXPAND\0Item7.Command=homegroup\0Item7.Settings=ITEM_DISABLED\0Item8.Command=separator\0Item9.Command=games\0Item9.Settings=TRACK_RECENT|NOEXPAND|ITEM_DISABLED\0Item10.Command=favorites\0Item10.Settings=ITEM_DISABLED\0Item11.Command=recent_documents\0Item12.Command=computer\0Item12.Settings=NOEXPAND\0Item13.Command=network\0Item13.Settings=ITEM_DISABLED\0Item14.Command=network_connections\0Item14.Settings=ITEM_DISABLED\0Item15.Command=separator\0Item16.Command=control_panel\0Item16.Settings=TRACK_RECENT\0Item17.Command=pc_settings\0Item17.Settings=TRACK_RECENT\0Item18.Command=admin\0Item18.Settings=TRACK_RECENT|ITEM_DISABLED\0Item19.Command=devices\0Item19.Settings=ITEM_DISABLED\0Item20.Command=defaults\0Item20.Settings=ITEM_DISABLED\0Item21.Command=help\0Item21.Settings=ITEM_DISABLED\0Item22.Command=run\0Item23.Command=apps\0Item23.Settings=ITEM_DISABLED\0Item24.Command=windows_security\0Item24.Settings=ITEM_DISABLED\0", Type = Reg.RegistryValueType.REG_MULTI_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkinOptionsW7", Data = @"DARK_MAIN=0\0METRO_MAIN=0\0LIGHT_MAIN=0\0AUTOMODE_MAIN=1\0DARK_SUBMENU=0\0METRO_SUBMENU=0\0LIGHT_SUBMENU=0\0AUTOMODE_SUBMENU=1\0SUBMENU_SEPARATORS=1\0DARK_SEARCH=0\0METRO_SEARCH=0\0LIGHT_SEARCH=0\0AUTOMODE_SEARCH=1\0SEARCH_FRAME=1\0SEARCH_COLOR=0\0MODERN_SEARCH=1\0SEARCH_ITALICS=0\0NONE=0\0SEPARATOR=0\0TWO_TONE=1\0CLASSIC_SELECTOR=1\0HALF_SELECTOR=0\0CURVED_MENUSEL=1\0CURVED_SUBMENU=0\0SELECTOR_REVEAL=1\0TRANSPARENT=0\0OPAQUE_SUBMENU=1\0OPAQUE_MENU=0\0OPAQUE=0\0STANDARD=0\0SMALL_MAIN2=1\0SMALL_ICONS=0\0COMPACT_SUBMENU=0\0PRESERVE_MAIN2=0\0LESS_PADDING=0\0EXTRA_PADDING=1\024_PADDING=0\0LARGE_PROGRAMS=0\0TRANSPARENT_SHUTDOWN=0\0OUTLINE_SHUTDOWN=0\0BUTTON_SHUTDOWN=1\0EXPERIMENTAL_SHUTDOWN=0\0LARGE_FONT=0\0CONNECTED_BORDER=1\0FLOATING_BORDER=0\0LARGE_SUBMENU=0\0LARGE_LISTS=0\0THIN_MAIN2=0\0EXPERIMENTAL_MAIN2=1\0USER_IMAGE=1\0USER_OUTSIDE=0\0SCALING_USER=1\056=0\064=0\0TRANSPARENT_USER=0\0UWP_SCROLLBAR=0\0MODERN_SCROLLBAR=1\0SMALL_ARROWS=0\0ARROW_BACKGROUND=1\0ICON_FRAME=0\0SEARCH_SEPARATOR=0\0NO_PROGRAMS_BUTTON=0\0", Type = Reg.RegistryValueType.REG_MULTI_SZ }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "SearchboxTaskbarMode", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "ShowTaskViewButton", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer", ValueName = "EnableAutoTray", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo", ValueName = "Enabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost", ValueName = "EnableWebContentEvaluation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\Control Panel\International\User Profile", ValueName = "HttpAcceptLanguageOptOut", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Policies\Microsoft\Windows\Explorer", ValueName = "DisableNotificationCenter", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR", ValueName = "AppCaptureEnabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\System\GameConfigStore", ValueName = "GameDVR_Enabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Attachments", ValueName = "SaveZoneInformation", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost", ValueName = "ContentEvaluation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\Control Panel\Desktop", ValueName = "WaitToKillAppTimeOut", Data = "2000", Type = Reg.RegistryValueType.REG_SZ }.Apply();
new Reg.Key() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\StorageSense" }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "BingSearchEnabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "CortanaConsent", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "CortanaInAmbientMode", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "HistoryViewEnabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "HasAboveLockTips", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "AllowSearchToUseLocation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\SearchSettings", ValueName = "SafeSearchMode", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Policies\Microsoft\Windows\Explorer", ValueName = "DisableSearchBoxSuggestions", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization", ValueName = "RestrictImplicitTextCollection", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization", ValueName = "RestrictImplicitInkCollection", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization\TrainedDataStore", ValueName = "AcceptedPrivacyPolicy", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization\TrainedDataStore", ValueName = "HarvestContacts", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Personalization\Settings", ValueName = "AcceptedPrivacyPolicy", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Policies\Microsoft\Windows\Explorer", ValueName = "DisableSearchBoxSuggestions", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "NavPaneShowAllFolders", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "LaunchTo", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "HideFileExt", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "Hidden", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply();
} catch (Exception e)
{
Reg.UnloadDefaultUserHive();
throw e;
}
Reg.UnloadDefaultUserHive();
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("User created successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
private static bool CreateNewUser()
{
try
{
if (CreateUser() == false)
return true;
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("User created successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
private static bool CreateUser()
{
var choice = new ChoicePrompt() { Text = "Make user an Administrator? (Y/N): " }.Start();
if (choice == null)
return false;
bool makeAdmin = choice == 0;
Console.WriteLine();
while (true)
{
var username = new InputPrompt() { Text = "Enter name of new user, or press\r\nescape to quit: " }.Start();
if (username == null)
return false;
if (String.IsNullOrEmpty(username) || !Regex.Match(username, @"^\w[\w\.\- ]{0,19}$").Success)
{
ConsoleTUI.OpenFrame.WriteLine("Username is invalid.");
Console.WriteLine();
continue;
}
if (Globals.Username.Equals(username))
{
ConsoleTUI.OpenFrame.WriteLine("Specified user already exists.");
Console.WriteLine();
continue;
}
var password = new InputPrompt() { MaskInput = true, Text = "\r\nEnter password for new user, or press\r\nescape to quit: " }.Start();
if (password == null)
return false;
var passwordConfirmation = new InputPrompt() { MaskInput = true, Text = "\r\nRe-enter your password, or press\r\nescape to quit: " }.Start();
if (passwordConfirmation == null)
return false;
if (password != passwordConfirmation)
{
ConsoleTUI.OpenFrame.WriteLine("The password re-entered does not match your original password.");
Console.WriteLine();
continue;
}
try
{
ConsoleTUI.OpenFrame.WriteCentered("\r\nCreating user");
using (new ConsoleUtils.LoadingIndicator(true))
{
DirectoryEntry AD = new DirectoryEntry("WinNT://" +
Environment.MachineName + ",computer");
DirectoryEntry NewUser = AD.Children.Add(username, "user");
NewUser.Invoke("SetPassword", new object[] { password });
NewUser.Invoke("Put", new object[] { "Description", "Normal User" });
NewUser.CommitChanges();
var ugrp = AD.Children.Find("Users", "group");
ugrp.Invoke("Add", new object[] { NewUser.Path.ToString() });
ugrp.CommitChanges();
if (makeAdmin)
{
var agrp = AD.Children.Find("Administrators", "group");
agrp.Invoke("Add", new object[] { NewUser.Path.ToString() });
agrp.CommitChanges();
}
}
} catch (System.Runtime.InteropServices.COMException e)
{
if (e.ErrorCode != -2147022694)
throw e;
ConsoleTUI.OpenFrame.WriteLine("Username is invalid.");
Console.WriteLine();
}
return true;
}
}
}
}

+ 201
- 0
src/Ameliorated.ConsoleUtils/ConsoleTUI/ConsoleTUI.cs View File

@ -0,0 +1,201 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using amecs;
namespace Ameliorated.ConsoleUtils
{
public static partial class ConsoleTUI
{
private const int MF_BYCOMMAND = 0x00000000;
private const int SC_CLOSE = 0xF060;
private const int SC_MINIMIZE = 0xF020;
private const int SC_MAXIMIZE = 0xF030;
private const int SC_SIZE = 0xF000; //resize
private const uint CHECK_QUICK_EDIT = 0x0040;
private const int ENABLE_QUICK_EDIT = 0x40 | 0x80;
// STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
private const int STD_INPUT_HANDLE = -10;
private static string PreviousTitle;
private static int PreviousBufferHeight = 26;
private static int PreviousBufferWidth = 80;
private static int PreviousSizeHeight = 26;
private static int PreviousSizeWidth = 80;
private static bool IsInitialized;
private static int InitializedWidth = 80;
public static void ShowErrorBox(string message, string caption)
{
NativeWindow window = new NativeWindow();
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle);
MessageBox.Show(window, message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public enum BackdropType
{
None = 1,
Mica = 2,
Acrylic = 3,
Tabbed = 4
}
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attribute, ref int pvAttribute, int cbAttribute);
public static void Initialize(string title, int width = 80, int height = 26, bool resize = false, bool quickedit = false)
{
if (width < 2) throw new ArgumentException("Width must be greater than one.");
IsInitialized = true;
PreviousSizeHeight = Console.WindowHeight;
PreviousSizeWidth = Console.WindowWidth;
PreviousBufferHeight = Console.BufferHeight;
PreviousBufferWidth = Console.BufferWidth;
Console.SetWindowSize(width, height);
Console.SetBufferSize(width, height);
Console.SetWindowSize(width, height);
InitializedWidth = width;
Console.Clear();
Console.CursorVisible = false;
PreviousTitle = Console.Title;
Console.Title = title;
try
{
if ((Console.CursorLeft == 0 && Console.CursorTop == 0) || ParentProcess.ProcessName.Equals("Explorer", StringComparison.OrdinalIgnoreCase))
{
var bd = (int)BackdropType.Mica;
var trueA = 0x01;
if (Globals.WinVer >= 22523)
{
var handle = Process.GetCurrentProcess().MainWindowHandle;
DwmSetWindowAttribute(handle, 38, ref bd, Marshal.SizeOf<int>());
DwmSetWindowAttribute(handle, 20, ref trueA, Marshal.SizeOf<int>());
}
}
} catch (Exception e) { }
if (!resize)
try
{
DisableResize();
} catch (Exception e)
{
ConsoleUtils.WriteError("Error disabling window resize - " + e.Message);
}
if (!quickedit)
try
{
DisableQuickEdit();
} catch (Exception e)
{
ConsoleUtils.WriteError("Error disabling quickedit - " + e.Message);
}
}
public static void Close()
{
if (!IsInitialized) throw new MethodAccessException("Console TUI must be initialized before calling other TUI functions.");
IsInitialized = false;
var parent = ParentProcess.ProcessName;
if (parent.Equals("Explorer", StringComparison.CurrentCultureIgnoreCase)) return;
try
{
EnableResize();
} catch (Exception e)
{
ConsoleUtils.WriteError("Error enabling window resize - " + e.Message);
}
try
{
EnableQuickEdit();
} catch (Exception e)
{
ConsoleUtils.WriteError("Error enabling quickedit - " + e.Message);
}
Console.CursorVisible = true;
Console.Clear();
Console.Title = PreviousTitle;
Console.SetWindowSize(PreviousSizeWidth, PreviousSizeHeight);
Console.SetBufferSize(PreviousBufferWidth, PreviousBufferHeight);
}
[DllImport("user32.dll")]
public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GetConsoleWindow();
private static void DisableResize()
{
var handle = GetConsoleWindow();
var sysMenu = GetSystemMenu(handle, false);
if (handle != IntPtr.Zero)
{
//DeleteMenu(sysMenu, SC_CLOSE, MF_BYCOMMAND);
//DeleteMenu(sysMenu, SC_MINIMIZE, MF_BYCOMMAND);
DeleteMenu(sysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(sysMenu, SC_SIZE, MF_BYCOMMAND); //resize
}
}
private static void EnableResize()
{
var handle = GetConsoleWindow();
GetSystemMenu(handle, true);
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll")]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
private static void DisableQuickEdit()
{
var consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
// get current console mode
uint consoleMode;
GetConsoleMode(consoleHandle, out consoleMode);
// set the new mode
SetConsoleMode(consoleHandle, consoleMode &= ~CHECK_QUICK_EDIT);
}
private static void EnableQuickEdit()
{
var consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
// get current console mode
uint consoleMode;
GetConsoleMode(consoleHandle, out consoleMode);
// set the new mode
SetConsoleMode(consoleHandle, consoleMode | ENABLE_QUICK_EDIT);
}
}
}

+ 198
- 0
src/Ameliorated.ConsoleUtils/ConsoleTUI/Frame.cs View File

@ -0,0 +1,198 @@
using System;
using System.Linq;
namespace Ameliorated.ConsoleUtils
{
public static partial class ConsoleTUI
{
public static Frame OpenFrame;
public partial class Frame
{
private int _displayWidth;
private int _sidePadding;
/// <summary>
/// Sets the visual "frame" to be used later.
/// </summary>
/// <param name="header">The header to be displayed just under the top of the frame.</param>
/// <param name="ignoreHeader">
/// Indicates whether an exception should be raised if the header cannot be aligned with the
/// frame.
/// </param>
/// <exception cref="MethodAccessException">Function was called before a TUI initialization.</exception>
public Frame(string header, bool throwOnMisalignedHeader = true)
{
if (!IsInitialized) throw new MethodAccessException("Console TUI must be initialized before calling other TUI functions.");
if (header.Split(new[]
{ "\r\n", "\n" }, StringSplitOptions.None).Any(x => x.Length > InitializedWidth)) throw new ArgumentException("Header must not be longer than the window width.");
int frameWidth;
if (InitializedWidth.IsEven())
{
if (!header.Length.IsEven() && throwOnMisalignedHeader) throw new ArgumentException("Header length should be even while window width is even.");
frameWidth = (.725 * InitializedWidth).RoundToEven();
} else
{
if (header.Length.IsEven() && throwOnMisalignedHeader) throw new ArgumentException("Header length should be odd while window width is odd.");
frameWidth = (.725 * InitializedWidth).RoundToOdd();
}
Header = header;
FrameWidth = frameWidth;
DisplayWidth = frameWidth - SidePadding * 2;
DisplayOffset = (InitializedWidth - DisplayWidth) / 2;
}
public string Header { get; set; }
public char FrameChar { get; set; } = '_';
public int FrameWidth { get; set; }
public int SidePadding
{
get => _sidePadding;
set
{
_sidePadding = value;
DisplayWidth = FrameWidth - value * 2;
DisplayOffset = (InitializedWidth - DisplayWidth) / 2;
}
}
public int DisplayWidth
{
get => _displayWidth;
set
{
_displayWidth = value;
DisplayOffset = (InitializedWidth - value) / 2;
}
}
internal int DisplayOffset { get; private set; }
internal int DisplayHeight { get; } = Console.WindowHeight - 13;
public void Open(bool paddingLines = true)
{
Console.WriteLine();
var frameOffset = (InitializedWidth - FrameWidth) / 2;
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth));
Console.WriteLine();
WriteCenteredLine(Header);
if (paddingLines)
{
Console.WriteLine();
Console.WriteLine();
}
OpenFrame = this;
}
public object Close(Prompt prompt = null, bool alignToBottom = false)
{
OpenFrame = null;
if (alignToBottom)
Console.SetCursorPosition(0, Console.WindowHeight - 7);
Console.WriteLine();
Console.WriteLine();
var frameOffset = (InitializedWidth - FrameWidth) / 2;
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth));
Console.WriteLine();
if (prompt != null)
{
if (!prompt.MaxLength.HasValue)
prompt.MaxLength = DisplayWidth - prompt.Text.LastLine().Length;
prompt.BindToOpenFrame = false;
prompt.Text = new string(' ', frameOffset) + prompt.Text;
try { return ((ChoicePrompt)prompt).Start(); } catch (InvalidCastException) {}
try { return ((InputPrompt)prompt).Start(); } catch (InvalidCastException) {}
}
return null;
}
public object Close(string text, Prompt prompt = null, bool alignToBottom = false)
{
OpenFrame = null;
if (alignToBottom)
Console.SetCursorPosition(0, Console.WindowHeight - 7);
Console.WriteLine();
WriteCenteredLine(text, true);
var frameOffset = (InitializedWidth - FrameWidth) / 2;
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth));
Console.WriteLine();
if (prompt != null)
{
if (!prompt.MaxLength.HasValue)
prompt.MaxLength = DisplayWidth - prompt.Text.LastLine().Length;
prompt.BindToOpenFrame = false;
prompt.Text = new string(' ', frameOffset) + prompt.Text;
try { return ((ChoicePrompt)prompt).Start(); } catch (InvalidCastException) {}
try { return ((InputPrompt)prompt).Start(); } catch (InvalidCastException) {}
}
return null;
}
public object Close(string text, ConsoleColor foreground, ConsoleColor background, Prompt prompt = null, bool alignToBottom = false)
{
OpenFrame = null;
if (alignToBottom)
Console.SetCursorPosition(0, Console.WindowHeight - 7);
Console.WriteLine();
WriteCenteredLine(text, foreground, background, true);
var frameOffset = (InitializedWidth - FrameWidth) / 2;
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth));
Console.WriteLine();
if (prompt != null)
{
if (!prompt.MaxLength.HasValue)
prompt.MaxLength = DisplayWidth - prompt.Text.LastLine().Length;
prompt.BindToOpenFrame = false;
prompt.Text = new string(' ', frameOffset) + prompt.Text;
try { return ((ChoicePrompt)prompt).Start(); } catch (InvalidCastException) {}
try { return ((InputPrompt)prompt).Start(); } catch (InvalidCastException) {}
}
return null;
}
public void Clear(int bottomOffset = 2)
{
for (int i = 0; i < Console.WindowHeight - (6 + bottomOffset); i++)
{
Console.SetCursorPosition(DisplayOffset, i + 6);
Console.Write(new string(' ', DisplayWidth));
}
Console.SetCursorPosition(0, 6);
OpenFrame = this;
}
public int AvailableLines()
{
var totalLines = DisplayHeight - (Math.Max(Console.CursorTop - 6, 0));
return totalLines;
}
public int AvailableChars()
{
var totalChars = Math.Max(Console.CursorLeft - DisplayOffset, 0) + (AvailableLines() * DisplayWidth);
return totalChars;
}
}
}
}

+ 397
- 0
src/Ameliorated.ConsoleUtils/ConsoleTUI/FrameWriteMethods.cs View File

@ -0,0 +1,397 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
namespace Ameliorated.ConsoleUtils
{
public partial class ConsoleTUI
{
public partial class Frame
{
/// <summary>
/// Centered Line
/// </summary>
public enum LineCenterOptions
{
Word = 0,
Character = 1
}
/// <summary>
/// Normal (Indented) Line
/// </summary>
public void WriteLine()
{
Console.WriteLine();
}
public void Write(string text)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines.Take(lines.Length - 1))
{
Console.WriteLine(line.Insert(0, new string(' ', DisplayOffset)));
}
Console.Write(lines.Last().Insert(0, new string(' ', DisplayOffset)));
}
public void WriteLine(string text)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines)
{
Console.WriteLine(line.Insert(0, new string(' ', DisplayOffset)));
}
}
public void WriteLine(string text, ConsoleColor? foreground)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines)
{
Console.Write(new string(' ', DisplayOffset));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public void WriteLine(string text, ConsoleColor? foreground, ConsoleColor? background)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines)
{
Console.Write(new string(' ', DisplayOffset));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(text);
ConsoleUtils.ResetColor();
}
}
public void WriteLine(string text, int offset)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines)
{
Console.WriteLine(line.Insert(0, new string(' ', DisplayOffset + offset)));
}
}
public void WriteLine(string text, int offset, ConsoleColor? foreground)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines)
{
Console.Write(new string(' ', DisplayOffset + offset));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public void WriteLine(string text, int offset, ConsoleColor? foreground, ConsoleColor? background)
{
var lines = text.SplitByLine();
if (lines.Length > AvailableLines())
Clear();
foreach (var line in lines)
{
Console.Write(new string(' ', DisplayOffset + offset));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public void WriteCenteredLine(string text, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
var centeredLines = CenterLines(text, options);
if (centeredLines.Count > AvailableLines() && !ignoreDisplayHeight)
{
Clear();
centeredLines = CenterLines(text.TrimStart('\r').TrimStart('\n'), options);
}
foreach (var line in centeredLines) Console.WriteLine(line.Value);
}
public void WriteCenteredLine(string text, int maxWidth, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
Contract.Requires<ArgumentException>(maxWidth > 1);
var centeredLines = CenterLines(text, options, maxWidth);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines) Console.WriteLine(line.Value);
}
public void WriteCenteredLine(string text, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
var centeredLines = CenterLines(text, options);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines)
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
}
public void WriteCenteredLine(string text, int maxWidth, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
Contract.Requires<ArgumentException>(maxWidth > 1);
var centeredLines = CenterLines(text, options, maxWidth);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines)
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
}
public void WriteCenteredLine(string text, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
var centeredLines = CenterLines(text, options);
if (centeredLines.Count > AvailableLines() && !ignoreDisplayHeight)
{
Clear();
centeredLines = CenterLines(text.TrimStart('\r').TrimStart('\n'), options);
}
foreach (var line in centeredLines)
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
}
public void WriteCenteredLine(string text, int maxWidth, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
Contract.Requires<ArgumentException>(maxWidth > 1);
var centeredLines = CenterLines(text, options, maxWidth);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines)
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
}
public void WriteCentered(string text, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
var centeredLines = CenterLines(text, options);
if (centeredLines.Count > AvailableLines() && !ignoreDisplayHeight)
{
Clear();
centeredLines = CenterLines(text.TrimStart('\r').TrimStart('\n'), options);
}
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) Console.WriteLine(line.Value);
Console.Write(centeredLines.Last().Value);
}
public void WriteCentered(string text, int maxWidth, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
Contract.Requires<ArgumentException>(maxWidth > 1);
var centeredLines = CenterLines(text, options, maxWidth);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) Console.WriteLine(line.Value);
Console.Write(centeredLines.Last().Value);
}
public void WriteCentered(string text, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
var centeredLines = CenterLines(text, options);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines.Take(centeredLines.Count - 1))
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
Console.Write(new string(' ', centeredLines.Last().LeaderLength));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(centeredLines.Last().RawString);
ConsoleUtils.ResetColor();
}
public void WriteCentered(string text, int maxWidth, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
Contract.Requires<ArgumentException>(maxWidth > 1);
var centeredLines = CenterLines(text, options, maxWidth);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines.Take(centeredLines.Count - 1))
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
Console.Write(new string(' ', centeredLines.Last().LeaderLength));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(centeredLines.Last().RawString);
ConsoleUtils.ResetColor();
}
public void WriteCentered(string text, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
var centeredLines = CenterLines(text, options);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines.Take(centeredLines.Count - 1))
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
Console.Write(new string(' ', centeredLines.Last().LeaderLength));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(centeredLines.Last().RawString);
ConsoleUtils.ResetColor();
}
public void WriteCentered(string text, int maxWidth, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word)
{
Contract.Requires<ArgumentException>(maxWidth > 1);
var centeredLines = CenterLines(text, options, maxWidth);
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight)
Clear();
foreach (var line in centeredLines.Take(centeredLines.Count - 1))
{
Console.Write(new string(' ', line.LeaderLength));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(line.RawString);
ConsoleUtils.ResetColor();
}
Console.Write(new string(' ', centeredLines.Last().LeaderLength));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(centeredLines.Last().RawString);
ConsoleUtils.ResetColor();
}
// TODO: Fix this splitting lines when a piece of text can fit on one line
private List<CenteredString> CenterLines(string text, LineCenterOptions options, int maxWidth = 0)
{
var _maxWidth = DisplayWidth;
if (maxWidth != 0) _maxWidth = maxWidth;
var list = new List<CenteredString>();
var lines = new List<string>();
foreach (var line in text.SplitByLine())
{
if (line == "")
{
list.Add(new CenteredString
{ Value = "", LeaderLength = 0 });
continue;
}
if (line.Length > _maxWidth)
{
for (var index = 0; index < line.Length;)
{
var splitLine = line.Substring(index, Math.Min(_maxWidth, line.Length - index));
var trimmedLength = splitLine.Length - splitLine.Trim(' ').Length;
splitLine = splitLine.Trim(' ');
var wordIndex = splitLine.LastIndexOf(' ');
if (wordIndex != -1 && options == LineCenterOptions.Word) splitLine = splitLine.Substring(0, wordIndex);
index += splitLine.Length + trimmedLength;
list.Add(CenterLine(splitLine));
}
continue;
}
list.Add(CenterLine(line));
}
return list;
}
private CenteredString CenterLine(string text, int maxWidth = 0)
{
var _maxWidth = DisplayWidth;
if (maxWidth != 0) _maxWidth = maxWidth;
var centeredString = new CenteredString();
var space = "";
if (!(text.Length % 2).Equals(0) && text.Length != _maxWidth) space = " ";
var leadingLength = (_maxWidth - text.Length) / 2;
centeredString.Value = space + text.PadLeft(text.Length + leadingLength, ' ').Insert(0, new string(' ', DisplayOffset));
centeredString.LeaderLength = leadingLength + DisplayOffset + space.Length;
centeredString.RawString = text;
return centeredString;
}
private class CenteredString
{
public int LeaderLength;
public string RawString;
public string Value;
}
}
}
}

+ 433
- 0
src/Ameliorated.ConsoleUtils/ConsoleTUI/Menu.cs View File

@ -0,0 +1,433 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using amecs;
namespace Ameliorated.ConsoleUtils
{
public class Menu
{
public List<MenuItem> Choices { get; set; } = new List<MenuItem>();
private int TotalOffset = 2;
private int? _offset = null;
public int Offset
{
get
{
if (_offset == null)
_offset = BindToOpenFrame ? 5 : 2;
return _offset.Value;
}
set { _offset = value; }
}
public ConsoleColor? SelectionForeground { get; set; } = ConsoleColor.Green;
public ConsoleColor? SelectionBackgound { get; set; } = null;
public bool CloseFrame { get; set; } = true;
private bool _bindToOpenFrame;
public bool BindToOpenFrame { get; set; } = true;
private int menuStart;
private int pages;
private int choicesPerPage;
public void Write()
{
if (Choices.Count < 1) throw new ArgumentException("Property Choices must have at least one choice.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
int totalStaticChoices = Choices.Count(x => x.IsStatic || x.IsNextButton || x.IsPreviousButton);
if (_bindToOpenFrame)
{
pages = (int)Math.Ceiling(((double)Choices.Count - totalStaticChoices) / (double)(ConsoleTUI.OpenFrame.DisplayHeight - totalStaticChoices + 1));
choicesPerPage = (ConsoleTUI.OpenFrame.DisplayHeight - totalStaticChoices + 1);
}
else
{
pages = (int)Math.Ceiling(((double)Choices.Count - totalStaticChoices) / (double)(((Console.WindowHeight - Console.CursorTop) - totalStaticChoices)));
choicesPerPage = (Console.WindowHeight - Console.CursorTop) - totalStaticChoices;
}
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Clear();
TotalOffset = _bindToOpenFrame ? ConsoleTUI.OpenFrame.DisplayOffset + Offset : Offset;
menuStart = Console.CursorTop;
if (_bindToOpenFrame)
{
Console.SetCursorPosition(TotalOffset, Console.CursorTop);
}
var fluidChoices = Choices.Where(x => !x.IsStatic && !x.IsNextButton && !x.IsPreviousButton).Take(choicesPerPage);
var staticChoices = Choices.Where(x => x.IsStatic || (pages > 1 && x.IsNextButton));
WriteChoiceList(fluidChoices.Concat(staticChoices));
Frame = ConsoleTUI.OpenFrame;
if (_bindToOpenFrame && CloseFrame)
{
try
{
var offset = ConsoleTUI.OpenFrame.DisplayOffset;
if (pages == 1)
ConsoleTUI.OpenFrame.Close();
else
ConsoleTUI.OpenFrame.Close($"Page 1/{pages}");
Console.WriteLine(new string(' ', offset) + "Use the arrow keys to navigate");
} catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
private void WriteChoiceList(IEnumerable<MenuItem> list)
{
bool selectedWritten = false;
Console.SetCursorPosition(0, Console.CursorTop);
foreach (MenuItem choice in list)
{
if (_bindToOpenFrame)
{
Console.Write(
new string(' ', TotalOffset));
if (choice.IsEnabled && !selectedWritten)
{
choice.WriteSelected(SelectionForeground, SelectionBackgound);
selectedWritten = true;
Console.WriteLine();
continue;
}
choice.Write();
}
else
{
Console.Write(
new string(' ', TotalOffset));
if (choice.IsEnabled && !selectedWritten)
{
choice.WriteSelected(SelectionForeground, SelectionBackgound);
selectedWritten = true;
Console.WriteLine();
continue;
}
choice.Write();
}
Console.WriteLine();
}
Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 1);
}
private List<MenuItem> ValidChoices = new List<MenuItem>();
private ConsoleTUI.Frame Frame;
public object Load()
{
var visCache = Console.CursorVisible;
Console.CursorVisible = false;
int index = Math.Max(Choices.FindIndex(x => x.IsEnabled), 0);
int validIndex = 0;
ConsoleKey keyPressed;
Console.SetCursorPosition(Console.CursorLeft, menuStart + index);
var allFluidChoices = Choices.Where(x => !x.IsStatic && !x.IsNextButton && !x.IsPreviousButton).ToList();
var allStaticChoices = Choices.Where(x => x.IsStatic || x.IsNextButton || x.IsPreviousButton).ToList();
int pageIndex = 1;
ConsoleUtils.ClearInputBuffer();
var currentChoices = allFluidChoices.Take(choicesPerPage).Concat(Choices.Where(x => x.IsStatic || (pages > 1 && x.IsNextButton))).ToList();
var currentValidChoices = currentChoices.Where(x => x.IsEnabled).ToList();
while (true)
{
keyPressed = Console.ReadKey(true).Key;
if (keyPressed == ConsoleKey.DownArrow || keyPressed == ConsoleKey.S)
{
if (validIndex >= currentValidChoices.Count - 1) continue;
Console.SetCursorPosition(Math.Max(TotalOffset - 2, 0), Console.CursorTop);
Console.Write(" ");
currentValidChoices[validIndex].Write();
var fromTop = currentChoices.Skip(index + 1).TakeWhile(x => !x.IsEnabled).Count() + 1;
var choice = currentChoices.Skip(index + 1).First(x => x.IsEnabled);
Console.SetCursorPosition(TotalOffset, Console.CursorTop + fromTop);
choice.WriteSelected(SelectionForeground, SelectionBackgound);
index += fromTop;
validIndex += 1;
}
if (keyPressed == ConsoleKey.UpArrow || keyPressed == ConsoleKey.W)
{
if (!(validIndex > 0)) continue;
Console.SetCursorPosition(Math.Max(TotalOffset - 2, 0), Console.CursorTop);
Console.Write(" ");
currentValidChoices[validIndex].Write();
var fromTop = -currentChoices.Take(index).Reverse().TakeWhile(x => !x.IsEnabled).Count() - 1;
var choice = currentChoices.Take(index).Last(x => x.IsEnabled);
Console.SetCursorPosition(TotalOffset, Console.CursorTop + fromTop);
choice.WriteSelected(SelectionForeground, SelectionBackgound);
index += fromTop;
validIndex -= 1;
}
if (keyPressed == ConsoleKey.RightArrow || keyPressed == ConsoleKey.A || keyPressed == ConsoleKey.PageUp ||
(keyPressed == ConsoleKey.Enter && currentValidChoices[validIndex].IsNextButton))
{
if (pageIndex == pages)
continue;
Frame.Clear();
pageIndex++;
var pIndex = pageIndex;
var fluidChoices = allFluidChoices.Skip((pIndex - 1) * choicesPerPage).Take(choicesPerPage).ToList();
var staticChoices = allStaticChoices.Where(x => !(pages <= pIndex && x.IsNextButton));
Console.SetCursorPosition(Console.CursorLeft, menuStart);
currentChoices = fluidChoices.Concat(staticChoices).ToList();
WriteChoiceList(currentChoices);
if (_bindToOpenFrame && CloseFrame)
{
try
{
var offset = ConsoleTUI.OpenFrame.DisplayOffset;
if (pages == 1)
ConsoleTUI.OpenFrame.Close();
else
ConsoleTUI.OpenFrame.Close($"Page {pIndex}/{pages}");
Console.WriteLine(new string(' ', offset) + "Use the arrow keys to navigate");
} catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
Console.SetCursorPosition(Console.CursorLeft, menuStart);
currentValidChoices = currentChoices.Where(x => x.IsEnabled).ToList();
index = 0;
validIndex = 0;
continue;
}
if (keyPressed == ConsoleKey.LeftArrow || keyPressed == ConsoleKey.D || keyPressed == ConsoleKey.PageDown ||
(keyPressed == ConsoleKey.Enter && currentValidChoices[validIndex].IsPreviousButton))
{
if (pageIndex == 1)
continue;
Frame.Clear();
pageIndex--;
var pIndex = pageIndex;
var fluidChoices = allFluidChoices.Skip((pIndex - 1) * choicesPerPage).Take(choicesPerPage).ToList();
var staticChoices = allStaticChoices.Where(x => !(pIndex <= 1 && x.IsPreviousButton));
Console.SetCursorPosition(Console.CursorLeft, menuStart);
currentChoices = fluidChoices.Concat(staticChoices).ToList();
WriteChoiceList(currentChoices);
if (_bindToOpenFrame && CloseFrame)
{
try
{
var offset = ConsoleTUI.OpenFrame.DisplayOffset;
if (pages == 1)
ConsoleTUI.OpenFrame.Close();
else
ConsoleTUI.OpenFrame.Close($"Page {pIndex}/{pages}");
Console.WriteLine(new string(' ', offset) + "Use the arrow keys to navigate");
} catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
Console.SetCursorPosition(Console.CursorLeft, menuStart);
currentValidChoices = currentChoices.Where(x => x.IsEnabled).ToList();
index = 0;
validIndex = 0;
continue;
}
if (keyPressed == ConsoleKey.Enter)
{
break;
}
}
if (CloseFrame)
Frame.Clear();
Console.CursorVisible = visCache;
return currentValidChoices[validIndex].ReturnValue;
}
private bool NextButtonPresent()
{
return Choices.Any(x => x.IsNextButton);
}
private bool PreviousButtonPresent()
{
return Choices.Any(x => x.IsNextButton);
}
public class MenuItem
{
public object ReturnValue { get; set; }
public static readonly MenuItem Blank = new MenuItem("", null);
public static readonly MenuItem BlankStatic = new MenuItem("", null) { IsStatic = true };
public bool IsNextButton { get; set; } = false;
public bool IsPreviousButton { get; set; } = false;
public bool IsStatic { get; set; } = false;
public string PrimaryText { get; set; } = "";
public string SecondaryText { get; set; } = "";
public MenuItem(string primaryText, object returnValue)
{
PrimaryText = primaryText;
ReturnValue = returnValue;
}
public bool AddBetweenSpace { get; set; } = true;
private ConsoleColor? _primaryTextForeground = null;
public ConsoleColor? PrimaryTextForeground
{
get
{
if (_primaryTextForeground.HasValue)
return _primaryTextForeground;
if (IsEnabled) return null;
if (Console.ForegroundColor == ConsoleColor.White) return ConsoleColor.DarkGray;
if (Console.ForegroundColor == ConsoleColor.White) return ConsoleColor.DarkGray;
return null;
}
set { _primaryTextForeground = value; }
}
public ConsoleColor? PrimaryTextBackground { get; set; } = null;
public ConsoleColor? SecondaryTextForeground { get; set; } = null;
public ConsoleColor? SecondaryTextBackground { get; set; } = null;
private bool? _isEnabled = null;
public bool IsEnabled
{
get
{
if (_isEnabled.HasValue)
return _isEnabled.Value;
if (!String.IsNullOrEmpty(PrimaryText) || !String.IsNullOrEmpty(SecondaryText))
{
return true;
}
return false;
}
set { _isEnabled = value; }
}
public bool StretchSelection = false;
public void Write()
{
if (!String.IsNullOrEmpty(PrimaryText))
{
ConsoleUtils.SetColor(PrimaryTextForeground, PrimaryTextBackground);
Console.Write(PrimaryText);
ConsoleUtils.ResetColor();
if (AddBetweenSpace)
Console.Write(' ');
}
if (String.IsNullOrEmpty(SecondaryText))
return;
ConsoleUtils.SetColor(SecondaryTextForeground, SecondaryTextBackground);
Console.Write(SecondaryText);
ConsoleUtils.ResetColor();
}
public void WriteSelected(ConsoleColor? foreground, ConsoleColor? background)
{
Console.SetCursorPosition(Console.CursorLeft - 2, Console.CursorTop);
if (!String.IsNullOrEmpty(PrimaryText))
{
ConsoleUtils.SetColor(foreground, background);
Console.Write("> " + PrimaryText);
if (!StretchSelection)
ConsoleUtils.ResetColor();
if (AddBetweenSpace)
Console.Write(' ');
}
if (String.IsNullOrEmpty(SecondaryText))
{
if (StretchSelection)
ConsoleUtils.ResetColor();
return;
}
if (!String.IsNullOrEmpty(PrimaryText) && !StretchSelection)
ConsoleUtils.SetColor(SecondaryTextForeground, SecondaryTextBackground);
Console.Write(SecondaryText);
ConsoleUtils.ResetColor();
}
}
}
}

+ 196
- 0
src/Ameliorated.ConsoleUtils/ConsoleTUI/MouseInterface.cs View File

@ -0,0 +1,196 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Ameliorated.ConsoleUtils
{
// TODO: Integrate this into ConsoleTUI.cs
// https://stackoverflow.com/questions/1944481/console-app-mouse-click-x-y-coordinate-detection-comparison
/*
public class MouseInterface
{
public static class ConsoleListener
{
public static event ConsoleMouseEvent MouseEvent;
public static event ConsoleKeyEvent KeyEvent;
public static event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent;
private static bool Run = false;
public static void Start()
{
if (!Run)
{
Run = true;
IntPtr handleIn = GetStdHandle(STD_INPUT_HANDLE);
new Thread(() =>
{
while (true)
{
uint numRead = 0;
INPUT_RECORD[] record = new INPUT_RECORD[1];
record[0] = new INPUT_RECORD();
ReadConsoleInput(handleIn, record, 1, ref numRead);
if (Run)
switch (record[0].EventType)
{
case INPUT_RECORD.MOUSE_EVENT:
MouseEvent?.Invoke(record[0].MouseEvent);
break;
case INPUT_RECORD.KEY_EVENT:
KeyEvent?.Invoke(record[0].KeyEvent);
break;
case INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:
WindowBufferSizeEvent?.Invoke(record[0].WindowBufferSizeEvent);
break;
}
else
{
uint numWritten = 0;
WriteConsoleInput(handleIn, record, 1, ref numWritten);
return;
}
}
}).Start();
}
}
public static void Stop() => Run = false;
public delegate void ConsoleMouseEvent(MOUSE_EVENT_RECORD r);
public delegate void ConsoleKeyEvent(KEY_EVENT_RECORD r);
public delegate void ConsoleWindowBufferSizeEvent(WINDOW_BUFFER_SIZE_RECORD r);
// NATIVE METHODS
public struct COORD
{
public short X;
public short Y;
public COORD(short x, short y)
{
X = x;
Y = y;
}
}
[StructLayout(LayoutKind.Explicit)]
public struct INPUT_RECORD
{
public const ushort KEY_EVENT = 0x0001,
MOUSE_EVENT = 0x0002,
WINDOW_BUFFER_SIZE_EVENT = 0x0004; //more
[FieldOffset(0)] public ushort EventType;
[FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent;
[FieldOffset(4)] public MOUSE_EVENT_RECORD MouseEvent;
[FieldOffset(4)] public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
/*
and:
MENU_EVENT_RECORD MenuEvent;
FOCUS_EVENT_RECORD FocusEvent;
~/ <--- end comment
}
public struct MOUSE_EVENT_RECORD
{
public COORD dwMousePosition;
public const uint FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001,
FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004,
FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008,
FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010,
RIGHTMOST_BUTTON_PRESSED = 0x0002;
public uint dwButtonState;
public const int CAPSLOCK_ON = 0x0080,
ENHANCED_KEY = 0x0100,
LEFT_ALT_PRESSED = 0x0002,
LEFT_CTRL_PRESSED = 0x0008,
NUMLOCK_ON = 0x0020,
RIGHT_ALT_PRESSED = 0x0001,
RIGHT_CTRL_PRESSED = 0x0004,
SCROLLLOCK_ON = 0x0040,
SHIFT_PRESSED = 0x0010;
public uint dwControlKeyState;
public const int DOUBLE_CLICK = 0x0002,
MOUSE_HWHEELED = 0x0008,
MOUSE_MOVED = 0x0001,
MOUSE_WHEELED = 0x0004;
public uint dwEventFlags;
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct KEY_EVENT_RECORD
{
[FieldOffset(0)] public bool bKeyDown;
[FieldOffset(4)] public ushort wRepeatCount;
[FieldOffset(6)] public ushort wVirtualKeyCode;
[FieldOffset(8)] public ushort wVirtualScanCode;
[FieldOffset(10)] public char UnicodeChar;
[FieldOffset(10)] public byte AsciiChar;
public const int CAPSLOCK_ON = 0x0080,
ENHANCED_KEY = 0x0100,
LEFT_ALT_PRESSED = 0x0002,
LEFT_CTRL_PRESSED = 0x0008,
NUMLOCK_ON = 0x0020,
RIGHT_ALT_PRESSED = 0x0001,
RIGHT_CTRL_PRESSED = 0x0004,
SCROLLLOCK_ON = 0x0040,
SHIFT_PRESSED = 0x0010;
[FieldOffset(12)] public uint dwControlKeyState;
}
public struct WINDOW_BUFFER_SIZE_RECORD
{
public COORD dwSize;
}
public const uint STD_INPUT_HANDLE = unchecked((uint)-10),
STD_OUTPUT_HANDLE = unchecked((uint)-11),
STD_ERROR_HANDLE = unchecked((uint)-12);
[DllImport("kernel32.dll")]
public static extern IntPtr GetStdHandle(uint nStdHandle);
public const uint ENABLE_MOUSE_INPUT = 0x0010,
ENABLE_QUICK_EDIT_MODE = 0x0040,
ENABLE_EXTENDED_FLAGS = 0x0080,
ENABLE_ECHO_INPUT = 0x0004,
ENABLE_WINDOW_INPUT = 0x0008; //more
[DllImportAttribute("kernel32.dll")]
public static extern bool GetConsoleMode(IntPtr hConsoleInput, ref uint lpMode);
[DllImportAttribute("kernel32.dll")]
public static extern bool SetConsoleMode(IntPtr hConsoleInput, uint dwMode);
[DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern bool ReadConsoleInput(IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsRead);
[DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern bool WriteConsoleInput(IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsWritten);
}
}
*/
}

+ 604
- 0
src/Ameliorated.ConsoleUtils/ConsoleTUI/Prompt.cs View File

@ -0,0 +1,604 @@
using System;
using System.Collections;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using JetBrains.Annotations;
namespace Ameliorated.ConsoleUtils
{
/// <summary>
/// Represents a input prompt to be used with the Start method.
/// </summary>
public class ChoicePrompt : Prompt
{
public string Choices { get; set; } = "YN";
public bool BeepSound { get; set; } = true;
public bool CaseSensitive { get; set; } = false;
public bool AllowEscape { get; set; } = true;
public bool AnyKey { get; set; } = false;
public ConsoleColor? TextForeground { get; set; }
private bool _bindToOpenFrame;
[CanBeNull]
public new int? Start()
{
if (Choices.Length < 1 && !AnyKey) throw new ArgumentException("There must be at least 1 choice.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1)
ConsoleTUI.OpenFrame.Clear();
if (TextForeground.HasValue)
ConsoleUtils.SetColor(TextForeground);
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Write(Text);
else
Console.Write(Text);
if (TextForeground.HasValue)
ConsoleUtils.ResetColor();
var cursorVisibility = Console.CursorVisible;
int? result;
while (true)
{
Console.CursorVisible = true;
ConsoleUtils.ClearInputBuffer();
var key = Console.ReadKey(true);
if (AnyKey)
{
Console.CursorVisible = cursorVisibility;
return key.KeyChar;
}
if (key.Key == ConsoleKey.Escape && AllowEscape)
{
Console.CursorVisible = cursorVisibility;
return null;
}
if (CaseSensitive)
result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.Ordinal);
else
result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.OrdinalIgnoreCase);
if (result >= 0)
{
if (InputForeground.HasValue && InputBackground.HasValue) ConsoleUtils.SetColor(InputForeground.Value, InputBackground.Value);
else if (InputForeground.HasValue) ConsoleUtils.SetColor(InputForeground.Value);
else if (InputBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, InputBackground.Value);
if (!CaseSensitive) Console.Write(key.KeyChar.ToString().ToUpper());
else Console.Write(key.KeyChar.ToString());
if (InputForeground.HasValue || InputBackground.HasValue) ConsoleUtils.ResetColor();
break;
}
else if (BeepSound) Console.Beep();
}
Console.CursorVisible = cursorVisibility;
Console.WriteLine();
return result.Value;
}
}
public class InputPrompt : Prompt
{
[Optional] public ConsoleColor? BoxBackground { get; set; }
public bool MaskInput { get; set; } = false;
public bool AlignInput { get; set; } = true;
[Optional] public int? SplitWidth { get; set; }
private bool _bindToOpenFrame;
private int? _splitWidth;
[CanBeNull]
public new string Start()
{
if (SplitWidth.HasValue && !AlignInput) throw new ArgumentException("Property SplitWidth must not be used without property AlignInput set to true.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1)
ConsoleTUI.OpenFrame.Clear();
if (!MaxLength.HasValue)
MaxLength = AlignInput ? ConsoleTUI.OpenFrame.AvailableChars() - (Text.LastLine().Length * ConsoleTUI.OpenFrame.AvailableLines()) : ConsoleTUI.OpenFrame.AvailableChars();
int startLeft = Console.CursorLeft + Text.LastLine().Length;
_splitWidth = null;
if (AlignInput && !_bindToOpenFrame)
{
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = Console.WindowWidth - startLeft;
}
if (_bindToOpenFrame)
{
if (SplitWidth.HasValue && (SplitWidth.Value + startLeft + ConsoleTUI.OpenFrame.DisplayOffset >= Console.WindowWidth))
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
// TODO: BAD WORDING
if (Text.LastLine().Length > ConsoleTUI.OpenFrame.DisplayWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth - (startLeft);
if (!AlignInput)
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth;
}
if (SplitWidth.HasValue)
{
if (SplitWidth.Value + startLeft >= Console.WindowWidth)
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = SplitWidth.Value;
}
/*
int maxLines = Console.WindowHeight - Console.CursorTop;
if (_bindToOpenFrame)
{
maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
if (maxLines < 2)
{
ConsoleTUI.OpenFrame.Clear();
if (_bindToOpenFrame) maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
}
}
*/
ConsoleUtils.ClearInputBuffer();
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Write(Text);
else
Console.Write(Text);
if (BoxBackground.HasValue && _splitWidth.HasValue)
{
if (AlignInput)
WriteBackground(_splitWidth.Value, BoxBackground.Value);
else
WriteBackground(_splitWidth.Value - Text.LastLine().Length, BoxBackground.Value);
}
if (BoxBackground.HasValue && !_splitWidth.HasValue) WriteBackground(Console.WindowWidth - Console.CursorLeft, BoxBackground.Value);
var cursorVisibility = Console.CursorVisible;
var input = new StringBuilder();
ConsoleKeyInfo key;
do
{
Console.CursorVisible = true;
key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Backspace)
{
if (input.Length <= 0) continue;
input.Remove(input.Length - 1, 1);
bool movedLines = false;
if (_bindToOpenFrame)
{
if ((((input.Length + 1) - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(ConsoleTUI.OpenFrame.DisplayWidth) || input.Length + 1 == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value - (Console.CursorLeft - ConsoleTUI.OpenFrame.DisplayOffset), Console.BackgroundColor);
Console.SetCursorPosition((ConsoleTUI.OpenFrame.DisplayOffset) + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
else if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset + startLeft + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
}
else if (AlignInput)
{
if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value))
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(startLeft + _splitWidth.Value, Console.CursorTop - 1);
movedLines = true;
}
}
else
{
if (((input.Length + 1) - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length + 1 == Console.WindowWidth - startLeft)
{
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth, Console.BackgroundColor);
Console.SetCursorPosition(Console.WindowWidth - 1, Console.CursorTop - 1);
movedLines = true;
}
}
if (movedLines)
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write(" \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
else
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write("\b \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
if (MaxLength.HasValue && MaxLength.Value - 1 == input.Length) Console.CursorVisible = true;
continue;
}
if (Char.IsControl(key.KeyChar)) continue;
if (MaxLength.HasValue && MaxLength.Value <= input.Length)
{
ConsoleUtils.SetColor(ConsoleColor.DarkRed, InputBackground);
Console.CursorVisible = false;
Console.Write("!");
Thread.Sleep(200);
ConsoleUtils.ClearInputBuffer();
ConsoleUtils.ResetColor();
ConsoleUtils.SetColor(null, BoxBackground);
Console.Write("\b \b");
ConsoleUtils.ResetColor();
continue;
}
input.Append(key.KeyChar);
ConsoleUtils.SetColor(InputForeground, InputBackground);
if (MaskInput) Console.Write("*");
else Console.Write(key.KeyChar);
ConsoleUtils.ResetColor();
if (MaxLength.HasValue && MaxLength.Value <= input.Length + 1)
continue;
if (_bindToOpenFrame)
{
if (((input.Length - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(_splitWidth.Value) || input.Length == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
else if (input.Length.IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
Console.SetCursorPosition(startLeft + ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else if (AlignInput)
{
if (input.Length.IsDivisibleBy(_splitWidth.Value))
{
if (SplitWidth.HasValue)
Console.SetCursorPosition(startLeft, Console.CursorTop + 1);
else
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else
{
if ((input.Length - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length == Console.WindowWidth - startLeft)
{
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft - Text.LastLine().Length, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth - (startLeft - Text.LastLine().Length), BoxBackground.Value);
}
}
} while (key.Key != ConsoleKey.Enter && (!AllowEscape || (AllowEscape && key.Key != ConsoleKey.Escape)));
if (input.Length == 0)
{
ConsoleUtils.SetColor(ConsoleColor.DarkGray);
Console.Write("None");
ConsoleUtils.ResetColor();
}
Console.CursorVisible = cursorVisibility;
Console.WriteLine();
if (key.Key == ConsoleKey.Escape && AllowEscape) return null;
return input.ToString();
}
}
public class SecureInputPrompt : Prompt
{
[Optional] public ConsoleColor? BoxBackground { get; set; }
public bool MaskInput { get; set; } = true;
public bool AlignInput { get; set; } = true;
[Optional] public int? SplitWidth { get; set; }
private bool _bindToOpenFrame;
private int? _splitWidth;
[CanBeNull]
public new SecureString Start()
{if (SplitWidth.HasValue && !AlignInput) throw new ArgumentException("Property SplitWidth must not be used without property AlignInput set to true.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1)
ConsoleTUI.OpenFrame.Clear();
if (!MaxLength.HasValue)
MaxLength = AlignInput ? ConsoleTUI.OpenFrame.AvailableChars() - (Text.LastLine().Length * ConsoleTUI.OpenFrame.AvailableLines()) : ConsoleTUI.OpenFrame.AvailableChars();
int startLeft = Console.CursorLeft + Text.LastLine().Length;
_splitWidth = null;
if (AlignInput && !_bindToOpenFrame)
{
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = Console.WindowWidth - startLeft;
}
if (_bindToOpenFrame)
{
if (SplitWidth.HasValue && (SplitWidth.Value + startLeft + ConsoleTUI.OpenFrame.DisplayOffset >= Console.WindowWidth))
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
// TODO: BAD WORDING
if (Text.LastLine().Length > ConsoleTUI.OpenFrame.DisplayWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth - (startLeft);
if (!AlignInput)
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth;
}
if (SplitWidth.HasValue)
{
if (SplitWidth.Value + startLeft >= Console.WindowWidth)
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = SplitWidth.Value;
}
/*
int maxLines = Console.WindowHeight - Console.CursorTop;
if (_bindToOpenFrame)
{
maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
if (maxLines < 2)
{
ConsoleTUI.OpenFrame.Clear();
if (_bindToOpenFrame) maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
}
}
*/
ConsoleUtils.ClearInputBuffer();
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Write(Text);
else
Console.Write(Text);
if (BoxBackground.HasValue && _splitWidth.HasValue)
{
if (AlignInput)
WriteBackground(_splitWidth.Value, BoxBackground.Value);
else
WriteBackground(_splitWidth.Value - Text.LastLine().Length, BoxBackground.Value);
}
if (BoxBackground.HasValue && !_splitWidth.HasValue) WriteBackground(Console.WindowWidth - Console.CursorLeft, BoxBackground.Value);
var cursorVisibility = Console.CursorVisible;
var input = new SecureString();
ConsoleKeyInfo key;
do
{
Console.CursorVisible = true;
key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Backspace)
{
if (input.Length <= 0) continue;
input.RemoveAt(input.Length - 1);
bool movedLines = false;
if (_bindToOpenFrame)
{
if ((((input.Length + 1) - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(ConsoleTUI.OpenFrame.DisplayWidth) || input.Length + 1 == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value - (Console.CursorLeft - ConsoleTUI.OpenFrame.DisplayOffset), Console.BackgroundColor);
Console.SetCursorPosition((ConsoleTUI.OpenFrame.DisplayOffset) + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
else if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset + startLeft + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
}
else if (AlignInput)
{
if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value))
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(startLeft + _splitWidth.Value, Console.CursorTop - 1);
movedLines = true;
}
}
else
{
if (((input.Length + 1) - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length + 1 == Console.WindowWidth - startLeft)
{
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth, Console.BackgroundColor);
Console.SetCursorPosition(Console.WindowWidth - 1, Console.CursorTop - 1);
movedLines = true;
}
}
if (movedLines)
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write(" \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
else
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write("\b \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
if (MaxLength.HasValue && MaxLength.Value - 1 == input.Length) Console.CursorVisible = true;
}
if (Char.IsControl(key.KeyChar)) continue;
if (MaxLength.HasValue && MaxLength.Value <= input.Length)
{
ConsoleUtils.SetColor(ConsoleColor.DarkRed, InputBackground);
Console.CursorVisible = false;
Console.Write("!");
Thread.Sleep(200);
ConsoleUtils.ClearInputBuffer();
ConsoleUtils.ResetColor();
ConsoleUtils.SetColor(null, BoxBackground);
Console.Write("\b \b");
ConsoleUtils.ResetColor();
continue;
}
input.AppendChar(key.KeyChar);
ConsoleUtils.SetColor(InputForeground, InputBackground);
if (MaskInput) Console.Write("*");
else Console.Write(key.KeyChar);
ConsoleUtils.ResetColor();
if (MaxLength.HasValue && MaxLength.Value <= input.Length + 1)
continue;
if (_bindToOpenFrame)
{
if (((input.Length - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(_splitWidth.Value) || input.Length == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
else if (input.Length.IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
Console.SetCursorPosition(startLeft + ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else if (AlignInput)
{
if (input.Length.IsDivisibleBy(_splitWidth.Value))
{
if (SplitWidth.HasValue)
Console.SetCursorPosition(startLeft, Console.CursorTop + 1);
else
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else
{
if ((input.Length - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length == Console.WindowWidth - startLeft)
{
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft - Text.LastLine().Length, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth - (startLeft - Text.LastLine().Length), BoxBackground.Value);
}
}
} while (key.Key != ConsoleKey.Enter && (!AllowEscape || (AllowEscape && key.Key != ConsoleKey.Escape)));
if (input.Length == 0)
{
ConsoleUtils.SetColor(ConsoleColor.Gray);
Console.Write("None");
ConsoleUtils.ResetColor();
}
Console.CursorVisible = cursorVisibility;
Console.WriteLine();
if (key.Key == ConsoleKey.Escape && AllowEscape) return null;
return input;
}
}
public abstract class Prompt
{
/// <summary>
/// Text to be displayed before the input.
/// </summary>
[Optional]
public string Text { get; set; } = "";
[Optional] public int? MaxLength { get; set; }
/// <summary>
/// (Optional)
/// </summary>
[Optional]
public ConsoleColor? InputForeground { get; set; } = null;
[Optional] public ConsoleColor? InputBackground { get; set; } = null;
public bool BindToOpenFrame { get; set; } = true;
public bool AllowEscape { get; set; } = true;
internal static void WriteBackground(int length, ConsoleColor color)
{
if (Console.CursorLeft + length > Console.WindowWidth) throw new Exception("Critical Error");
int leftStart = Console.CursorLeft;
int topStart = Console.CursorTop;
ConsoleUtils.SetColor(Console.ForegroundColor, color);
Console.Write(new string(' ', length));
ConsoleUtils.ResetColor();
Console.SetCursorPosition(leftStart, topStart);
}
}
}

+ 250
- 0
src/Ameliorated.ConsoleUtils/ConsoleUtils.cs View File

@ -0,0 +1,250 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Ameliorated.ConsoleUtils
{
[AttributeUsage(AttributeTargets.Property)]
internal sealed class OptionalAttribute : Attribute
{
}
public static class ConsoleUtils
{
public class LoadingIndicator : IDisposable
{
public LoadingIndicator() {}
public LoadingIndicator(bool start)
{
if (start)
StartAsync();
}
private CancellationTokenSource cts = new CancellationTokenSource();
Task currentTask = Task.CompletedTask;
public async Task StartAsync()
{
Console.CursorVisible = false;
cts = new CancellationTokenSource();
currentTask = Task.Run(() =>
{
if (cts.IsCancellationRequested)
{
Console.WriteLine("...");
return;
}
Console.Write('.');
while (true)
{
Thread.Sleep(500);
Console.Write('.');
Thread.Sleep(500);
Console.Write('.');
Thread.Sleep(500);
if (cts.IsCancellationRequested)
{
Console.WriteLine();
return;
}
Console.Write("\b \b\b \b");
}
});
await currentTask;
}
public void Stop()
{
cts.Cancel();
currentTask.Wait();
}
public void Dispose()
{
Stop();
this.currentTask = null;
this.cts = null;
}
}
public static bool DisplayErrors { get; set; } = true;
public static void ClearInputBuffer()
{
while (Console.KeyAvailable) Console.ReadKey(true);
}
internal static void WriteError(string text)
{
if (DisplayErrors) Console.WriteLine("ConsoleUtils: " + text);
}
private static ConsoleColor foregroundCache;
private static ConsoleColor backgroundCache;
private static bool? foregroundOnly;
internal static void SetColor([CanBeNull] ConsoleColor? foreground)
{
foregroundCache = Console.ForegroundColor;
if (foreground.HasValue)
Console.ForegroundColor = foreground.Value;
foregroundOnly = true;
}
internal static void SetColor([CanBeNull] ConsoleColor? foreground, [CanBeNull] ConsoleColor? background)
{
foregroundCache = Console.ForegroundColor;
backgroundCache = Console.BackgroundColor;
if (foreground.HasValue)
Console.ForegroundColor = foreground.Value;
if (background.HasValue)
Console.BackgroundColor = background.Value;
foregroundOnly = false;
}
internal static void ResetColor()
{
if (!foregroundOnly.HasValue) throw new MethodAccessException("SetColor must be used before calling ResetColor.");
if (foregroundOnly.Value)
{
Console.ForegroundColor = foregroundCache;
} else
{
Console.ForegroundColor = foregroundCache;
Console.BackgroundColor = backgroundCache;
}
foregroundOnly = null;
}
public static void WriteLine(string text, ConsoleColor? foreground)
{
foreach (var line in text.SplitByLine())
{
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public static void WriteLine(string text, ConsoleColor? foreground, ConsoleColor? background)
{
foreach (var line in text.SplitByLine())
{
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public static void WriteLine(string text, int offset)
{
foreach (var line in text.SplitByLine())
{
Console.WriteLine(line.Insert(0, new string(' ', offset)));
}
}
public static void WriteLine(string text, int offset, ConsoleColor? foreground)
{
foreach (var line in text.SplitByLine())
{
Console.Write(new string(' ', offset));
ConsoleUtils.SetColor(foreground);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public static void WriteLine(string text, int offset, ConsoleColor? foreground, ConsoleColor? background)
{
foreach (var line in text.SplitByLine())
{
Console.Write(new string(' ', offset));
ConsoleUtils.SetColor(foreground, background);
Console.WriteLine(line);
ConsoleUtils.ResetColor();
}
}
public static void Write(string text, ConsoleColor? foreground)
{
foreach (var line in text.SplitByLine())
{
ConsoleUtils.SetColor(foreground);
Console.Write(line);
ConsoleUtils.ResetColor();
}
}
public static void Write(string text, ConsoleColor? foreground, ConsoleColor? background)
{
foreach (var line in text.SplitByLine())
{
ConsoleUtils.SetColor(foreground);
Console.Write(line);
ConsoleUtils.ResetColor();
}
}
public static void Write(string text, int offset)
{
foreach (var line in text.SplitByLine())
{
Console.Write(line.Insert(0, new string(' ', offset)));
}
}
public static void Write(string text, int offset, ConsoleColor? foreground)
{
foreach (var line in text.SplitByLine())
{
Console.Write(new string(' ', offset));
ConsoleUtils.SetColor(foreground);
Console.Write(line);
ConsoleUtils.ResetColor();
}
}
public static void Write(string text, int offset, ConsoleColor? foreground, ConsoleColor? background)
{
foreach (var line in text.SplitByLine())
{
Console.Write(new string(' ', offset));
ConsoleUtils.SetColor(foreground, background);
Console.Write(line);
ConsoleUtils.ResetColor();
}
}
}
}

+ 88
- 0
src/Ameliorated.ConsoleUtils/Extensions.cs View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ameliorated.ConsoleUtils
{
public static class Extensions
{
public static bool IsEven(this int number)
{
return number % 2 == 0;
}
/// <summary>
/// Checks if number is divisble by a divisor.
/// <param name="divisor">Divisor.</param>
/// <param name="returnFalseOnZeroOrNegative">Indicates whether to return false on numbers that are zero or below. Default is true.</param>
/// </summary>
public static bool IsDivisibleBy(this int number, int divisor, bool returnFalseOnZeroOrNegative = true)
{
if (returnFalseOnZeroOrNegative && number <= 0) return false;
return number % divisor == 0;
}
public static int RoundToEven(this double number)
{
var rounded = (int)Math.Round(number);
if (!rounded.IsEven()) return rounded - 1;
return rounded;
}
public static int RoundToEven(this int number)
{
if (!number.IsEven()) return number - 1;
return number;
}
public static int RoundToOdd(this double number)
{
if (!((int)Math.Ceiling(number)).IsEven()) return (int)Math.Ceiling(number);
if (!((int)Math.Floor(number)).IsEven()) return (int)Math.Floor(number);
return (int)Math.Truncate(number) - 1;
}
public static int RoundToOdd(this int number)
{
if (!number.IsEven()) return number - 1;
return number;
}
public static string[] SplitByLine(this string text, StringSplitOptions options = StringSplitOptions.None)
{
return text.Split(new[]
{ "\r\n", "\n" }, options);
}
public static string LastLine(this string text, StringSplitOptions options = StringSplitOptions.None)
{
return text.SplitByLine().Last();
}
public static void ReplaceItem(this List<Menu.MenuItem> list, Menu.MenuItem oldItem, Menu.MenuItem newItem)
{
var index = list.IndexOf(oldItem);
if (index == -1) throw new ArgumentException("Could not find item index.");
list.RemoveAt(index);
list.Insert(index, newItem);
}
public static Menu.MenuItem Clone(this Menu.MenuItem item)
{
return new Menu.MenuItem(item.PrimaryText, item.ReturnValue)
{
AddBetweenSpace = item.AddBetweenSpace,
IsEnabled = item.IsEnabled,
IsNextButton = item.IsNextButton,
IsPreviousButton = item.IsPreviousButton,
IsStatic = item.IsStatic,
PrimaryTextBackground = item.PrimaryTextBackground,
PrimaryTextForeground = item.PrimaryTextForeground,
SecondaryText = item.SecondaryText,
SecondaryTextBackground = item.SecondaryTextBackground,
SecondaryTextForeground = item.SecondaryTextForeground,
StretchSelection = item.StretchSelection,
};
}
}
}

+ 74
- 0
src/Ameliorated.ConsoleUtils/ParentProcess.cs View File

@ -0,0 +1,74 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Ameliorated.ConsoleUtils
{
public static class ParentProcess
{
private static readonly uint TH32CS_SNAPPROCESS = 2;
public static string ProcessName = Get().ProcessName;
public static Process Get()
{
try
{
var iParentPid = 0;
var iCurrentPid = Process.GetCurrentProcess().Id;
var oHnd = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (oHnd == IntPtr.Zero)
return null;
var oProcInfo = new PROCESSENTRY32();
oProcInfo.dwSize =
(uint)Marshal.SizeOf(typeof(PROCESSENTRY32));
if (Process32First(oHnd, ref oProcInfo) == false)
return null;
do
{
if (iCurrentPid == oProcInfo.th32ProcessID)
iParentPid = (int)oProcInfo.th32ParentProcessID;
} while (iParentPid == 0 && Process32Next(oHnd, ref oProcInfo));
if (iParentPid > 0)
return Process.GetProcessById(iParentPid);
return null;
} catch (Exception e)
{
return null;
}
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
[DllImport("kernel32.dll")]
private static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll")]
private static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szExeFile;
}
}
}

+ 6
- 0
src/Ameliorated.ConsoleUtils/Payload.cs View File

@ -0,0 +1,6 @@
namespace Ameliorated.ConsoleUtils
{
public class Payload
{
}
}

+ 10
- 0
src/App.config View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?><configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

+ 342
- 0
src/Extra/Extra.cs View File

@ -0,0 +1,342 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.Http;
using System.ServiceProcess;
using System.Threading;
using amecs.Actions;
using Ameliorated.ConsoleUtils;
namespace amecs.Extra
{
public static partial class Extra
{
public static bool ShowMenu()
{
while (true)
{
Program.Frame.Clear();
bool hibernation = new Reg.Value()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\Power",
ValueName = "HibernateEnabled",
Data = 1,
}.IsEqual()
&&
new Reg.Value()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\Power",
ValueName = "HiberFileType",
Data = 2,
}.IsEqual();
bool notifications = new Reg.Value()
{
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications",
ValueName = "ToastEnabled",
Data = 1,
}.IsEqual();
bool notificationCenter = !new Reg.Value()
{
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Policies\Microsoft\Windows\Explorer",
ValueName = "DisableNotificationCenter",
Data = 1,
}.IsEqual();
bool vbsEnabled = new Reg.Value()
{
KeyName = @"HKCR\.vbs",
ValueName = "",
Data = "VBSFile",
Type = Reg.RegistryValueType.REG_SZ
}.IsEqual();
bool ncsiEnabled = new Reg.Value()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet",
ValueName = "EnableActiveProbing",
Data = 1,
}.IsEqual();
var mainMenu = new Ameliorated.ConsoleUtils.Menu()
{
Choices =
{
new Menu.MenuItem("Manage WSL", null) {IsEnabled = false, SecondaryText = "[Not Supported]", PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red},
hibernation ?
new Menu.MenuItem("Disable Hibernation", new Func<bool>(DisableHibernation)) :
new Menu.MenuItem("Enable Hibernation", new Func<bool>(EnableHibernation)),
notificationCenter ?
new Menu.MenuItem("Disable Notification Center", new Func<bool>(DisableNotifCen)) :
new Menu.MenuItem("Enable Notification Center", new Func<bool>(EnableNotifCen)),
notifications ?
new Menu.MenuItem("Disable Desktop Notifications", new Func<bool>(DisableNotifications)) :
new Menu.MenuItem("Enable Desktop Notifications", new Func<bool>(EnableNotifications)),
GetWSHItem(),
vbsEnabled ?
new Menu.MenuItem("Disable Visual Basic Script [VBS] (Legacy)", new Func<bool>(DisableVBS)) :
new Menu.MenuItem("Enable Visual Basic Script [VBS] (Legacy)", new Func<bool>(EnableVBS)),
ncsiEnabled ?
new Menu.MenuItem("Disable NCSI Active Probing (Legacy)", new Func<bool>(DisableNCSI)) :
new Menu.MenuItem("Enable NCSI Active Probing (Legacy)", new Func<bool>(EnableNCSI)),
GetNVCPItem(),
Menu.MenuItem.Blank,
new Menu.MenuItem("Return to Menu", null),
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit))
},
SelectionForeground = ConsoleColor.Green
};
Func<bool> result;
try
{
mainMenu.Write();
var res = mainMenu.Load();
if (res == null)
return true;
result = (Func<bool>)res;
} catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
return false;
}
try
{
result.Invoke();
} catch (Exception e)
{
ConsoleTUI.ShowErrorBox("Error while running an action: " + e.ToString(), null);
}
}
}
private static Menu.MenuItem GetNVCPItem()
{
if (File.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\NVIDIA Control Panel\nvcplui.exe")))
return new Menu.MenuItem("Uninstall NVIDIA Control Panel", new Func<bool>(NVCP.Uninstall));
if (Globals.WinVer > 19043)
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Not Supported]"};
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT NAME FROM Win32_VideoController");
bool foundGPU = false;
foreach (ManagementObject mo in searcher.Get())
{
PropertyData Name = mo.Properties["Name"];
if (Name.Value != null)
{
var name = ((string)Name.Value);
if (name.Contains("NVIDIA") || name.Contains("GeForce") || name.Contains("GTX") || name.Contains("RTX"))
{
foundGPU = true;
break;
}
}
}
if (!foundGPU)
{
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[No NVIDIA GPU]"};
}
} catch {}
try
{
if (!ServiceController.GetServices().Any(x => x.ServiceName.Equals("NVDisplay.ContainerLocalSystem")))
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[No NVIDIA Driver]"};
} catch { }
try
{
var dir = Directory.EnumerateDirectories(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\WindowsApps")).First(x => x.Contains("NVIDIACorp.NVIDIAControlPanel"));
if (File.Exists(Path.Combine(dir, "nvcplui.exe")))
return new Menu.MenuItem("Install NVIDIA Control Panel", new Func<bool>(() => NVCP.Install(dir)));
} catch { }
if (!amecs.IsInternetAvailable())
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Internet Required]"};
if (!amecs.InternetCheckConnection("https://store.rg-adguard.net", 1, 0))
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Server Unavailable]"};
if (!amecs.InternetCheckConnection("https://git.ameliorated.info/", 1, 0))
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Git Unavailable]"};
try
{
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = client.GetAsync("https://store.rg-adguard.net/").Result)
{
using (HttpContent content = response.Content)
{
string result = content.ReadAsStringAsync().Result;
if (result.Contains("Cloudflare Ray ID"))
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Server Unavailable]"};
}
}
}
} catch { }
return new Menu.MenuItem("Install NVIDIA Control Panel", new Func<bool>(NVCP.InstallFromNetwork));
}
private static Menu.MenuItem GetWSHItem()
{
if (new Reg.Value()
{
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 1,
}.IsEqual())
return new Menu.MenuItem("Disable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Disable));
if (new Reg.Value()
{
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 0,
}.IsEqual())
return new Menu.MenuItem("Enable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Enable));
return new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 0,
}.IsEqual() ? new Menu.MenuItem("Disable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Enable)) : new Menu.MenuItem("Disable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Disable));
}
private static bool EnableHibernation() =>amecs.RunBasicAction("Enabling hibernation","Enabled hibernation successfully",() =>
{
Thread.Sleep(1600);
Process proc = new Process();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.FileName = "powercfg.exe";
proc.StartInfo.Arguments = "/HIBERNATE /TYPE FULL";
proc.Start();
proc.WaitForExit(20000);
if (proc.ExitCode != 0)
throw new Exception("powercfg exited with a non-zero exitcode.\r\nHibernation may not be supported by your hardware.");
});
private static bool DisableHibernation() =>amecs.RunBasicAction("Disabling hibernation","Disabled hibernation successfully",() =>
{
Thread.Sleep(1600);
Process proc = new Process();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.FileName = "powercfg.exe";
proc.StartInfo.Arguments = "/HIBERNATE OFF";
proc.Start();
proc.WaitForExit(20000);
if (proc.ExitCode != 0)
throw new Exception("powercfg exited with a non-zero exitcode.");
Thread.Sleep(1600);
});
private static bool EnableNotifCen() =>amecs.RunBasicAction("Enabling Notification Center","Notification Center enabled successfully",() =>
{
new Reg.Value()
{
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Policies\Microsoft\Windows\Explorer",
ValueName = "DisableNotificationCenter",
Operation = Reg.RegistryValueOperation.Delete
}.Apply();
Thread.Sleep(1600);
}, true);
private static bool DisableNotifCen() =>amecs.RunBasicAction("Disabling Notification Center","Notification Center disabled successfully",() =>
{
new Reg.Value()
{
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Policies\Microsoft\Windows\Explorer",
ValueName = "DisableNotificationCenter",
Data = 1,
}.Apply();
Thread.Sleep(1600);
}, true);
private static bool EnableNotifications() =>amecs.RunBasicAction("Enabling desktop notifications","Enabled desktop notifications successfully",() =>
{
new Reg.Value()
{
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications",
ValueName = "ToastEnabled",
Data = 1,
}.Apply();
Thread.Sleep(1600);
}, true);
private static bool DisableNotifications() =>amecs.RunBasicAction("Disabling desktop notifications","Disabled desktop notifications successfully",() =>
{
new Reg.Value()
{
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications",
ValueName = "ToastEnabled",
Data = 0,
}.Apply();
Thread.Sleep(1600);
}, true);
private static bool EnableVBS() =>amecs.RunBasicAction("Enabling Visual Basic Script","Enabled VBS successfully",() =>
{
new Reg.Value()
{
KeyName = @"HKCR\.vbs",
ValueName = "",
Data = "VBSFile",
Type = Reg.RegistryValueType.REG_SZ
}.Apply();
Thread.Sleep(1600);
});
private static bool DisableVBS() =>amecs.RunBasicAction("Disabling Visual Basic Script","Disabled VBS successfully",() =>
{
new Reg.Value()
{
KeyName = @"HKCR\.vbs",
ValueName = "",
Data = "",
Type = Reg.RegistryValueType.REG_SZ
}.Apply();
Thread.Sleep(1600);
});
private static bool EnableNCSI() =>amecs.RunBasicAction("Enabling NCSI Active Probing","Enabled NCSI Active Probing successfully",() =>
{
new Reg.Value()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet",
ValueName = "EnableActiveProbing",
Data = 1,
}.Apply();
Thread.Sleep(1600);
}, false, true);
private static bool DisableNCSI() =>amecs.RunBasicAction("Disabling NCSI Active Probing","Disabled NCSI Active Probing successfully",() =>
{
new Reg.Value()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet",
ValueName = "EnableActiveProbing",
Data = 0,
}.Apply();
Thread.Sleep(1600);
}, false, true);
}
}

+ 281
- 0
src/Extra/NVCP.cs View File

@ -0,0 +1,281 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using amecs.Actions;
using Ameliorated.ConsoleUtils;
using IWshRuntimeLibrary;
using File = System.IO.File;
namespace amecs.Extra
{
public class NVCP
{
private static readonly string DestinationDir = Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\NVIDIA Control Panel");
public static bool Install(string NVCP) => amecs.RunBasicAction("Installing NVIDIA Control Panel", "NVIDIA Control Panel installed successfully", () =>
{
Thread.Sleep(4000);
try
{
foreach (var proc in Process.GetProcessesByName("nvcplui"))
proc.Kill();
} catch
{
}
if (Directory.Exists(DestinationDir))
Directory.Delete(DestinationDir, true);
Directory.Move(NVCP, DestinationDir);
var di = new DirectoryInfo(DestinationDir);
var sec = di.GetAccessControl();
sec.AddAccessRule(new FileSystemAccessRule("Administrators", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
sec.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.ReadAndExecute, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
di.SetAccessControl(sec);
Config();
});
public static bool InstallFromNetwork()
{
try
{
foreach (var proc in Process.GetProcessesByName("nvcplui"))
proc.Kill();
} catch
{
}
if (Directory.Exists(DestinationDir))
Directory.Delete(DestinationDir, true);
var choice = new ChoicePrompt() {Text = "NVIDIA Control Panel must be downloaded\r\nContinue? (Y/N): "}.Start();
if (!choice.HasValue || choice == 1)
return false;
string link;
string filter;
string size;
ConsoleTUI.OpenFrame.WriteCentered("\r\nFetching download link");
try
{
using (new ConsoleUtils.LoadingIndicator(true))
{
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = client.GetAsync("https://git.ameliorated.info/Styris/amecs/src/branch/master/links.txt").Result)
{
using (HttpContent content = response.Content)
{
string result = content.ReadAsStringAsync().Result;
var line = result.SplitByLine().First(x => x.Contains("NVIDIA-Control-Panel = "));
var split = line.Split('|');
link = split[1];
filter = split[3];
if (link == "REMOVED")
throw new Exception("Link is no longer available.");
}
}
var values = new Dictionary<string, string>
{
{ "type", "url" },
{ "url", link },
{ "ring", "Retail" }
};
var request = new FormUrlEncodedContent(values);
using (HttpResponseMessage response = client.PostAsync("https://store.rg-adguard.net/api/GetFiles", request).Result)
{
using (HttpContent content = response.Content)
{
string result = content.ReadAsStringAsync().Result;
var regex = new Regex($".*{filter}.*");
var match = regex.Match(result).Value;
var split = match.Split('"');
link = split[3];
size = split[12].Remove(0, 1).Remove(split[12].Length - 11);
if (!size.Contains("MB") && !size.Contains("KB") && !size.Contains("GB"))
size = "0 MB";
}
}
}
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Could not fetch link: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
var temp = Environment.ExpandEnvironmentVariables(@"%TEMP%\[amecs]-NVCP-" + new Random().Next(0, 9999) + ".zip");
try
{
ConsoleTUI.OpenFrame.WriteCenteredLine($"\r\nDownloading NVIDIA Control Panel ({size})");
using (WebClient wc = new WebClient())
{
var stdout = GetStdHandle(-11);
var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5);
wc.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
{
var currentHashTags = (int)Math.Ceiling(Math.Min(((double)e.ProgressPercentage / 100) * maxHashTags, maxHashTags));
var spaces = maxHashTags - currentHashTags + (4 - e.ProgressPercentage.ToString().Length);
var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + e.ProgressPercentage + "%");
uint throwaway;
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway);
};
var task = wc.DownloadFileTaskAsync(new Uri(link), temp);
task.Wait();
Thread.Sleep(100);
var sb = new StringBuilder(new string('#', maxHashTags) + " 100%");
uint throwaway;
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway);
}
Console.WriteLine();
ZipFile.ExtractToDirectory(temp, DestinationDir);
if (!File.Exists(Path.Combine(DestinationDir, "nvcplui.exe")))
{
try { Directory.Delete(DestinationDir, true);} catch {}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Download is missing critical executable.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Config();
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return false;
}
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("NVIDIA Control Panel installed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
public static bool Uninstall() => amecs.RunBasicAction("Uninstalling NVIDIA Control Panel", "NVIDIA Control Panel uninstalled successfully", () =>
{
var linkPath = Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\NVIDIA Control Panel.lnk");
if (File.Exists(linkPath))
File.Delete(linkPath);
Directory.Delete(DestinationDir, true);
Thread.Sleep(2000);
});
public static void Config()
{
try
{
new Reg.Value() { KeyName = @"HKLM\System\CurrentControlSet\Services\nvlddmkm\Global\NVTweak", ValueName = "DisableStoreNvCplNotifications", Type = Reg.RegistryValueType.REG_DWORD, Data = 1 }.Apply();
} catch (Exception e)
{
ConsoleTUI.ShowErrorBox("Could not disable NVIDIA Microsoft Store notification: " + e.ToString(), "Error");
}
var linkPath = Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\NVIDIA Control Panel.lnk");
if (File.Exists(linkPath))
File.Delete(linkPath);
try
{
IShellLink link = (IShellLink)new ShellLink();
link.SetDescription("NVIDIA Control Panel");
link.SetPath(Path.Combine(DestinationDir, "nvcplui.exe"));
IPersistFile file = (IPersistFile)link;
file.Save(linkPath, false);
} catch
{
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(linkPath);
shortcut.Description = "NVIDIA Control Panel";
shortcut.TargetPath = Path.Combine(DestinationDir, "nvcplui.exe");
shortcut.Save();
}
new Reg.Value() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NVDisplay.ContainerLocalSystem", ValueName = "Start", Type = Reg.RegistryValueType.REG_DWORD, Data = 2 }.Apply();
try { ServiceController.GetServices().First(x => x.ServiceName.Equals("NVDisplay.ContainerLocalSystem")).Start(); } catch (Exception e) { }
}
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteConsoleOutputCharacter(IntPtr hConsoleOutput, StringBuilder lpCharacter, uint nLength, COORD dwWriteCoord, out uint lpNumberOfCharsWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public COORD(short X, short Y)
{
this.X = X;
this.Y = Y;
}
};
}
[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")]
internal class ShellLink
{
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
internal interface IShellLink
{
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags);
void GetIDList(out IntPtr ppidl);
void SetIDList(IntPtr pidl);
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
void GetHotkey(out short pwHotkey);
void SetHotkey(short wHotkey);
void GetShowCmd(out int piShowCmd);
void SetShowCmd(int iShowCmd);
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
void Resolve(IntPtr hwnd, int fFlags);
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
}

+ 40
- 0
src/Extra/WSH.cs View File

@ -0,0 +1,40 @@
namespace amecs.Extra
{
public class WSH
{
public static bool Enable() => amecs.RunBasicAction("Enabling Windows Script Host", "Enabled WSH successfully", i =>
{
new Reg.Value()
{
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 1,
Type = Reg.RegistryValueType.REG_DWORD
}.Apply();
new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 1,
Type = Reg.RegistryValueType.REG_DWORD
}.Apply();
});
public static bool Disable() => amecs.RunBasicAction("Disabling Windows Script Host", "Disabled WSH successfully", i =>
{
new Reg.Value()
{
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 0,
Type = Reg.RegistryValueType.REG_DWORD
}.Apply();
new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings",
ValueName = "Enabled",
Data = 0,
Type = Reg.RegistryValueType.REG_DWORD
}.Apply();
});
}
}

+ 3
- 0
src/FodyWeavers.xml View File

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>

+ 41
- 0
src/Globals.cs View File

@ -0,0 +1,41 @@
using System;
using System.DirectoryServices.AccountManagement;
using System.Threading.Tasks;
using Ameliorated.ConsoleUtils;
using Microsoft.Win32;
namespace amecs
{
public static class Globals
{
public static string Username = null;
public static string UserDomain = null;
public static string UserSID = null;
public static string UserFolder = null;
public static bool UserElevated = false;
public static string UserHive
{
get
{
return "HKU\\" + UserSID;
}
}
public static Task UserLoadTask = Task.CompletedTask;
public static ConsoleUtils.LoadingIndicator CurrentIndicator = new ConsoleUtils.LoadingIndicator();
public static GroupPrincipal Administrators;
public static UserPrincipal User;
public static bool Exit()
{
ConsoleTUI.Close();
Environment.Exit(0);
return true;
}
public static readonly int WinVer = int.Parse(Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue("CurrentBuildNumber").ToString());
}
}

+ 220
- 0
src/Misc/FolderPicker.cs View File

@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace amecs.Misc
{
public class FolderPicker
{
private readonly List<string> _resultPaths = new List<string>();
private readonly List<string> _resultNames = new List<string>();
public IReadOnlyList<string> ResultPaths => _resultPaths;
public IReadOnlyList<string> ResultNames => _resultNames;
public string ResultPath => ResultPaths.FirstOrDefault();
public string ResultName => ResultNames.FirstOrDefault();
public virtual string InputPath { get; set; }
public virtual bool ForceFileSystem { get; set; }
public virtual bool Multiselect { get; set; }
public virtual string Title { get; set; }
public virtual string OkButtonLabel { get; set; }
public virtual string FileNameLabel { get; set; }
protected virtual int SetOptions(int options)
{
if (ForceFileSystem)
{
options |= (int)FOS.FOS_FORCEFILESYSTEM;
}
if (Multiselect)
{
options |= (int)FOS.FOS_ALLOWMULTISELECT;
}
return options;
}
// for all .NET
public virtual bool? ShowDialog(IntPtr owner, bool throwOnError = false)
{
var dialog = (IFileOpenDialog)new FileOpenDialog();
if (!string.IsNullOrEmpty(InputPath))
{
if (CheckHr(SHCreateItemFromParsingName(InputPath, null, typeof(IShellItem).GUID, out var item), throwOnError) != 0)
return null;
dialog.SetFolder(item);
}
var options = FOS.FOS_PICKFOLDERS;
options = (FOS)SetOptions((int)options);
dialog.SetOptions(options);
if (Title != null)
{
dialog.SetTitle(Title);
}
if (OkButtonLabel != null)
{
dialog.SetOkButtonLabel(OkButtonLabel);
}
if (FileNameLabel != null)
{
dialog.SetFileName(FileNameLabel);
}
if (owner == IntPtr.Zero)
{
owner = Process.GetCurrentProcess().MainWindowHandle;
if (owner == IntPtr.Zero)
{
owner = GetDesktopWindow();
}
}
var hr = dialog.Show(owner);
if (hr == ERROR_CANCELLED)
return null;
if (CheckHr(hr, throwOnError) != 0)
return null;
if (CheckHr(dialog.GetResults(out var items), throwOnError) != 0)
return null;
items.GetCount(out var count);
for (var i = 0; i < count; i++)
{
items.GetItemAt(i, out var item);
CheckHr(item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out var path), throwOnError);
CheckHr(item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEEDITING, out var name), throwOnError);
if (path != null || name != null)
{
_resultPaths.Add(path);
_resultNames.Add(name);
}
}
return true;
}
private static int CheckHr(int hr, bool throwOnError)
{
if (hr != 0 && throwOnError) Marshal.ThrowExceptionForHR(hr);
return hr;
}
[DllImport("shell32")]
private static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);
[DllImport("user32")]
private static extern IntPtr GetDesktopWindow();
#pragma warning disable IDE1006 // Naming Styles
private const int ERROR_CANCELLED = unchecked((int)0x800704C7);
#pragma warning restore IDE1006 // Naming Styles
[ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] // CLSID_FileOpenDialog
private class FileOpenDialog { }
[ComImport, Guid("d57c7288-d4ad-4768-be02-9d969532d960"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IFileOpenDialog
{
[PreserveSig] int Show(IntPtr parent); // IModalWindow
[PreserveSig] int SetFileTypes(); // not fully defined
[PreserveSig] int SetFileTypeIndex(int iFileType);
[PreserveSig] int GetFileTypeIndex(out int piFileType);
[PreserveSig] int Advise(); // not fully defined
[PreserveSig] int Unadvise();
[PreserveSig] int SetOptions(FOS fos);
[PreserveSig] int GetOptions(out FOS pfos);
[PreserveSig] int SetDefaultFolder(IShellItem psi);
[PreserveSig] int SetFolder(IShellItem psi);
[PreserveSig] int GetFolder(out IShellItem ppsi);
[PreserveSig] int GetCurrentSelection(out IShellItem ppsi);
[PreserveSig] int SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
[PreserveSig] int GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
[PreserveSig] int SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
[PreserveSig] int SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
[PreserveSig] int SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
[PreserveSig] int GetResult(out IShellItem ppsi);
[PreserveSig] int AddPlace(IShellItem psi, int alignment);
[PreserveSig] int SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
[PreserveSig] int Close(int hr);
[PreserveSig] int SetClientGuid(); // not fully defined
[PreserveSig] int ClearClientData();
[PreserveSig] int SetFilter([MarshalAs(UnmanagedType.IUnknown)] object pFilter);
[PreserveSig] int GetResults(out IShellItemArray ppenum);
[PreserveSig] int GetSelectedItems([MarshalAs(UnmanagedType.IUnknown)] out object ppsai);
}
[ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItem
{
[PreserveSig] int BindToHandler(); // not fully defined
[PreserveSig] int GetParent(); // not fully defined
[PreserveSig] int GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
[PreserveSig] int GetAttributes(); // not fully defined
[PreserveSig] int Compare(); // not fully defined
}
[ComImport, Guid("b63ea76d-1f85-456f-a19c-48159efa858b"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItemArray
{
[PreserveSig] int BindToHandler(); // not fully defined
[PreserveSig] int GetPropertyStore(); // not fully defined
[PreserveSig] int GetPropertyDescriptionList(); // not fully defined
[PreserveSig] int GetAttributes(); // not fully defined
[PreserveSig] int GetCount(out int pdwNumItems);
[PreserveSig] int GetItemAt(int dwIndex, out IShellItem ppsi);
[PreserveSig] int EnumItems(); // not fully defined
}
#pragma warning disable CA1712 // Do not prefix enum values with type name
private enum SIGDN : uint
{
SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
SIGDN_FILESYSPATH = 0x80058000,
SIGDN_NORMALDISPLAY = 0,
SIGDN_PARENTRELATIVE = 0x80080001,
SIGDN_PARENTRELATIVEEDITING = 0x80031001,
SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
SIGDN_PARENTRELATIVEPARSING = 0x80018001,
SIGDN_URL = 0x80068000
}
[Flags]
private enum FOS
{
FOS_OVERWRITEPROMPT = 0x2,
FOS_STRICTFILETYPES = 0x4,
FOS_NOCHANGEDIR = 0x8,
FOS_PICKFOLDERS = 0x20,
FOS_FORCEFILESYSTEM = 0x40,
FOS_ALLNONSTORAGEITEMS = 0x80,
FOS_NOVALIDATE = 0x100,
FOS_ALLOWMULTISELECT = 0x200,
FOS_PATHMUSTEXIST = 0x800,
FOS_FILEMUSTEXIST = 0x1000,
FOS_CREATEPROMPT = 0x2000,
FOS_SHAREAWARE = 0x4000,
FOS_NOREADONLYRETURN = 0x8000,
FOS_NOTESTFILECREATE = 0x10000,
FOS_HIDEMRUPLACES = 0x20000,
FOS_HIDEPINNEDPLACES = 0x40000,
FOS_NODEREFERENCELINKS = 0x100000,
FOS_OKBUTTONNEEDSINTERACTION = 0x200000,
FOS_DONTADDTORECENT = 0x2000000,
FOS_FORCESHOWHIDDEN = 0x10000000,
FOS_DEFAULTNOMINIMODE = 0x20000000,
FOS_FORCEPREVIEWPANEON = 0x40000000,
FOS_SUPPORTSTREAMABLEITEMS = unchecked((int)0x80000000)
}
#pragma warning restore CA1712 // Do not prefix enum values with type name
}
}

+ 261
- 0
src/Misc/SelectWindowsImage.cs View File

@ -0,0 +1,261 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security;
using System.Windows.Forms;
using Ameliorated.ConsoleUtils;
using Microsoft.Dism;
// Asks user to select Windows installation media, and mounts it if applicable
// Returns path to where it's mounted
namespace amecs.Misc
{
public static class SelectWindowsImage
{
private static string _fileViolationTest;
private static bool CheckFileViolation(string inputFile)
{
try
{
_fileViolationTest = inputFile;
}
catch (SecurityException e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Security exception: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " });
return true;
}
return false;
}
public static string GetWindowsVersion(float majorMinor, int isoBuild)
{
return (majorMinor, isoBuild) switch
{
(6, _) => "Windows Vista",
(6.1f, _) => "Windows 7",
(6.2f, _) => "Windows 8",
(6.3f, _) => "Windows 8.1",
(10, var a) when a < 19041 => "Windows 10 (Old)",
(10, var a) when a >= 22000 => "Windows 11",
(10, _) => "Windows 10",
_ => "Unknown"
};
}
public static bool DismountIso(string imagePath)
{
var startInfo = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
FileName = "PowerShell.exe",
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = $"-NoP -C \"Dismount-DiskImage '{imagePath}'\"",
RedirectStandardOutput = true
};
var proc = Process.Start(startInfo);
if (proc == null) return false;
proc.WaitForExit();
return true;
}
private static string _mountedPath;
private static string _isoPath;
private static string _isoWinVer;
private static int _isoBuild;
/// <summary>
/// Asks user to select Windows installation media, mounts it if applicable, and checks its version
/// </summary>
/// <param name="winVersionsMustMatch">If true when ISO and host versions mismatch, prompts user that things can break if they continue</param>
/// <param name="isoBuildMustBeReturned">If true and the ISO build can't be retrieved, prompts a user with an error</param>
public static (
string MountedPath, string IsoPath, string Winver, int? Build, bool? VersionsMatch
) GetMediaPath(bool winVersionsMustMatch = false, bool isoBuildMustBeReturned = false)
{
var error = ((string)null, "none", (string)null, (int?)null, (bool?)null);
var choice =
new ChoicePrompt { Text = "To continue, Windows installation media is needed.\r\nDo you have a Windows USB instead of an ISO file? (Y/N): " }.Start();
if (!choice.HasValue) return error;
// Folder/drive chosen
var usingFolder = choice == 0;
if (usingFolder)
{
var dlg = new FolderPicker
{
InputPath = Globals.UserFolder
};
if (dlg.ShowDialog(IntPtr.Zero).GetValueOrDefault())
{
if (CheckFileViolation(dlg.ResultPath))
return error;
_mountedPath = dlg.ResultPath;
}
else
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("\r\nYou must select a folder or drive containing Windows installation media.",
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " });
return error;
}
}
else
{
// Mounting the ISO
var dialog = new OpenFileDialog();
dialog.Filter = "ISO Files (*.ISO)| *.ISO";
dialog.Multiselect = false;
dialog.InitialDirectory = Globals.UserFolder;
var window = new NativeWindow();
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle);
if (dialog.ShowDialog(window) == DialogResult.OK)
{
_isoPath = dialog.FileName;
if (CheckFileViolation(_isoPath)) return error;
Console.WriteLine();
ConsoleTUI.OpenFrame.WriteCentered("\r\nMounting ISO");
}
else
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("\r\nYou must select an ISO.",
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " });
return error;
}
using (new ConsoleUtils.LoadingIndicator(true))
{
var startInfo = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
FileName = "PowerShell.exe",
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = $"-NoP -C \"(Mount-DiskImage '{_isoPath}' -PassThru | Get-Volume).DriveLetter + ':\'\"",
RedirectStandardOutput = true
};
var proc = Process.Start(startInfo);
if (proc == null) return error;
proc.WaitForExit();
_mountedPath = proc.StandardOutput.ReadLine();
}
}
// Check WIM version
var wimOrEsdPath = new[] { $@"{_mountedPath}\sources\install.esd", $@"{_mountedPath}\sources\install.wim" }.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(wimOrEsdPath))
{
try
{
DismApi.Initialize(DismLogLevel.LogErrors);
string previousIndexVersion = null;
string isoFullVersion = null;
var multiVersion = false;
var imageInfos = DismApi.GetImageInfo(wimOrEsdPath);
foreach (var imageInfo in imageInfos)
{
isoFullVersion = imageInfo.ProductVersion.ToString();
if (isoFullVersion != previousIndexVersion && previousIndexVersion != null)
{
// If it's multi-version, WinVer will be "Unknown" as well
multiVersion = true;
isoFullVersion = "0.0.0.0";
break;
}
previousIndexVersion = isoFullVersion;
}
switch (multiVersion)
{
case true when isoBuildMustBeReturned:
ConsoleTUI.OpenFrame.Close(
"Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. Please use an unmodified Windows ISO.",
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " });
return error;
case true when winVersionsMustMatch:
ConsoleTUI.OpenFrame.Close(
"Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. If your Windows version doesn't match the ISO, there will be problems.",
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = "Press any key to continue anyways: " });
Program.Frame.Clear();
ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check...\r\n");
break;
}
var buildSplit = isoFullVersion.Split('.');
_isoBuild = int.Parse(buildSplit[2]);
_isoWinVer = GetWindowsVersion(float.Parse($"{buildSplit[0]}.{buildSplit[1]}"), _isoBuild);
}
catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close(
"Error checking ISO version: " + e.Message.TrimEnd('\n').TrimEnd('\r'),
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " });
return error;
}
finally
{
try
{
DismApi.Shutdown();
}
catch
{
// do nothing
}
}
// Check the current OS version
var hostVersion = Environment.OSVersion.Version;
var hostWinver = GetWindowsVersion(float.Parse($"{hostVersion.Major}.{hostVersion.Minor}"), hostVersion.Build);
// If it all matches & winVersionsMustMatch
if (hostWinver == _isoWinVer) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, true);
// If ISO version doesn't match host version & winVersionsMustMatch
if (hostWinver != _isoWinVer && winVersionsMustMatch)
{
if (!string.IsNullOrEmpty(_isoPath)) DismountIso(_isoPath);
ConsoleTUI.OpenFrame.Close(
$"You're on {hostWinver}, but the selected image is {_isoWinVer}. You can only use an ISO that matches your Windows version.",
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " });
return error;
}
// If ISO version doesn't match host version, and winVersionsMustMatch is true
if (hostWinver != _isoWinVer) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, false);
}
var noWimText = isoBuildMustBeReturned
? "Press any key to return to the Menu"
: "Press any key to continue anyways";
ConsoleTUI.OpenFrame.Close(
"No Windows installation image was found inside the selected Windows media. No version check can be done, things might break.",
ConsoleColor.Red, Console.BackgroundColor,
new ChoicePrompt { AnyKey = true, Text = $"{noWimText}: " });
Program.Frame.Clear();
ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check\r\n");
return isoBuildMustBeReturned ? error : (_mountedPath, _isoPath, null, null, null);
}
}
}

+ 525
- 0
src/NSudo.cs View File

@ -0,0 +1,525 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;
namespace amecs
{
[StructLayout(LayoutKind.Sequential)]
public class NSudo
{
private struct SECURITY_ATTRIBUTES
{
public int nLength;
public unsafe byte* lpSecurityDescriptor;
public int bInheritHandle;
}
private enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
private enum TOKEN_TYPE {
TokenPrimary = 1,
TokenImpersonation
}
[StructLayout(LayoutKind.Sequential)]
private struct LUID {
public uint LowPart;
public uint HighPart;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct LUID_AND_ATTRIBUTES {
public LUID Luid;
public UInt32 Attributes;
}
private struct TOKEN_PRIVILEGES {
public int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
private static UInt32 MAXIMUM_ALLOWED = (UInt32)TokenAccessLevels.MaximumAllowed;
[DllImport("advapi32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool OpenProcessToken(IntPtr ProcessHandle,
UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
IntPtr lpTokenAttributes,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
TOKEN_TYPE TokenType,
out IntPtr phNewToken );
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpTokenAttributes,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
TOKEN_TYPE TokenType,
out IntPtr phNewToken );
[DllImport("advapi32.dll")]
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName,
ref LUID lpLuid);
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
// Use this signature if you do not want the previous state
[DllImport("advapi32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
[MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
ref TOKEN_PRIVILEGES NewState,
UInt32 Zero,
IntPtr Null1,
IntPtr Null2);
[System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
private static extern bool SetThreadToken(IntPtr pHandle,
IntPtr hToken);
[DllImport("wtsapi32.dll", SetLastError=true)]
static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
[DllImport("advapi32.dll", SetLastError = true)]
static extern Boolean SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
ref UInt32 TokenInformation, UInt32 TokenInformationLength);
[DllImport("userenv.dll", SetLastError=true)]
static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit );
public static bool GetUserPrivilege(IntPtr Token)
{
IntPtr NewToken;
DuplicateTokenEx(Token, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out NewToken);
SetThreadToken(IntPtr.Zero, NewToken);
return true;
}
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[Flags]
enum CreationFlags
{
CREATE_SUSPENDED = 0x00000004,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
CREATE_NO_WINDOW = 0x08000000,
CREATE_NEW_CONSOLE = 0x00000010
}
[DllImport("advapi32.dll", SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LogonUser(
[MarshalAs(UnmanagedType.LPStr)] string pszUserName,
[MarshalAs(UnmanagedType.LPStr)] string pszDomain,
[MarshalAs(UnmanagedType.LPStr)] string pszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
public static int? RunProcessAsUser(IntPtr Token, string Executable, string Arguments, uint timeout = 0xFFFFFFFF)
{
GetAssignPrivilege();
GetQuotaPrivilege();
var startupInfo = new STARTUPINFO();
startupInfo.cb = Marshal.SizeOf(startupInfo);
startupInfo.dwFlags = 0x00000001;
startupInfo.wShowWindow = 1;
var procAttrs = new SECURITY_ATTRIBUTES();
var threadAttrs = new SECURITY_ATTRIBUTES();
procAttrs.nLength = Marshal.SizeOf(procAttrs);
threadAttrs.nLength = Marshal.SizeOf(threadAttrs);
// Log on user temporarily in order to start console process in its security context.
var hUserTokenDuplicate = IntPtr.Zero;
var pEnvironmentBlock = IntPtr.Zero;
DuplicateTokenEx(Token, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out hUserTokenDuplicate);
CreateEnvironmentBlock(out pEnvironmentBlock, Token, false);
PROCESS_INFORMATION _processInfo;
if (!CreateProcessAsUser(hUserTokenDuplicate, null, String.IsNullOrEmpty(Arguments) ? $"\"{Executable}\"" : $"\"{Executable}\" {Arguments}",
ref procAttrs, ref threadAttrs, false, (uint)CreationFlags.CREATE_NO_WINDOW |
(uint)CreationFlags.CREATE_UNICODE_ENVIRONMENT,
pEnvironmentBlock, null, ref startupInfo, out _processInfo)) return null;
uint exitCode;
WaitForSingleObject(_processInfo.hProcess, timeout);
GetExitCodeProcess(_processInfo.hProcess, out exitCode);
return (int)exitCode;
/*
uint dwCreationFlags = (uint)CreationFlags.CREATE_UNICODE_ENVIRONMENT;
startupInfo.cb = Marshal.SizeOf(startupInfo);
SECURITY_ATTRIBUTES throwaway = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES throwaway2 = new SECURITY_ATTRIBUTES();
Console.WriteLine(Marshal.GetLastWin32Error() + "-3");
Console.WriteLine(CreateProcessAsUser(hUserToken, String.Empty, "\"C:\\Windows\\notepad.exe\"", ref throwaway, ref throwaway2, false, 0, IntPtr.Zero, String.Empty, ref StartupInfo, out ProcessInfo));
Console.WriteLine(Marshal.GetLastWin32Error() + "-4");
return Process.GetProcessById(ProcessInfo.dwProcessId);
*/
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
[DllImport("kernel32.dll", SetLastError=true)]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct STARTUPINFO
{
public Int32 cb;
public IntPtr lpReserved;
public IntPtr lpDesktop;
public IntPtr lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
public static IntPtr GetUserToken()
{
IntPtr Token;
WTSQueryUserToken((uint)SessionID, out Token);
return Token;
}
private static int SessionID = -1;
public static bool GetSystemPrivilege()
{
IntPtr CurrentProcessToken;
OpenProcessToken(Process.GetCurrentProcess().Handle, MAXIMUM_ALLOWED, out CurrentProcessToken);
IntPtr DuplicatedCurrentProcessToken;
DuplicateTokenEx(CurrentProcessToken, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out DuplicatedCurrentProcessToken);
LUID_AND_ATTRIBUTES RawPrivilege = new LUID_AND_ATTRIBUTES();
LookupPrivilegeValue(IntPtr.Zero, "SeDebugPrivilege", ref RawPrivilege.Luid);
RawPrivilege.Attributes = SE_PRIVILEGE_ENABLED;
TOKEN_PRIVILEGES TokenPrivilege = new TOKEN_PRIVILEGES();
TokenPrivilege.Privileges = new LUID_AND_ATTRIBUTES[] { RawPrivilege };
TokenPrivilege.PrivilegeCount = 1;
AdjustTokenPrivileges(DuplicatedCurrentProcessToken, false, ref TokenPrivilege, 0, IntPtr.Zero, IntPtr.Zero);
SetThreadToken(IntPtr.Zero, DuplicatedCurrentProcessToken);
SessionID = GetActiveSession();
IntPtr OriginalProcessToken = new IntPtr(-1);
CreateSystemToken((int)MAXIMUM_ALLOWED, SessionID, ref OriginalProcessToken);
IntPtr SystemToken;
DuplicateTokenEx(OriginalProcessToken, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out SystemToken);
SetThreadToken(IntPtr.Zero, SystemToken);
return true;
}
[DllImport("advapi32.dll", SetLastError=true)]
static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
int TokenInformationLength,
out int ReturnLength);
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}
private static int GetActiveSession()
{
IntPtr pSessionInfo = IntPtr.Zero;
Int32 Count = 0;
var retval = WTSEnumerateSessions((IntPtr)null, 0, 1, ref pSessionInfo, ref Count);
Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
Int64 current = (Int64)pSessionInfo;
int result = -1;
if (retval != 0)
{
for (int i = 0; i < Count; i++)
{
WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
current += dataSize;
if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive)
{
result = si.SessionID;
break;
}
}
WTSFreeMemory(pSessionInfo);
}
return result;
}
private static void CreateSystemToken(int DesiredAccess, int dwSessionID, ref IntPtr TokenHandle)
{
int dwLsassPID = -1;
int dwWinLogonPID = -1;
WTS_PROCESS_INFO[] pProcesses;
IntPtr pProcessInfo = IntPtr.Zero;
int dwProcessCount = 0;
if (WTSEnumerateProcesses((IntPtr)null, 0, 1, ref pProcessInfo, ref dwProcessCount))
{
IntPtr pMemory = pProcessInfo;
pProcesses = new WTS_PROCESS_INFO[dwProcessCount];
for (int i = 0; i < dwProcessCount; i++)
{
pProcesses[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
pProcessInfo = (IntPtr)((long)pProcessInfo + Marshal.SizeOf(pProcesses[i]));
var processName = Marshal.PtrToStringAnsi(pProcesses[i].ProcessName);
ConvertSidToStringSid(pProcesses[i].UserSid, out string sid);
string strSid;
if (processName == null || pProcesses[i].UserSid == default || sid != "S-1-5-18")
continue;
if ((-1 == dwLsassPID) && (0 == pProcesses[i].SessionID) && (processName == "lsass.exe"))
{
dwLsassPID = pProcesses[i].ProcessID;
continue;
}
if ((-1 == dwWinLogonPID) && (dwSessionID == pProcesses[i].SessionID) && (processName == "winlogon.exe"))
{
dwWinLogonPID = pProcesses[i].ProcessID;
continue;
}
}
WTSFreeMemory(pMemory);
}
bool Result = false;
IntPtr SystemProcessHandle = IntPtr.Zero;
try
{
SystemProcessHandle = Process.GetProcessById(dwLsassPID).Handle;
} catch
{
SystemProcessHandle = Process.GetProcessById(dwWinLogonPID).Handle;
}
IntPtr SystemTokenHandle = IntPtr.Zero;
if (OpenProcessToken(SystemProcessHandle, TOKEN_DUPLICATE, out SystemTokenHandle))
{
Result = DuplicateTokenEx(SystemTokenHandle, (uint)DesiredAccess, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out TokenHandle);
CloseHandle(SystemTokenHandle);
}
CloseHandle(SystemProcessHandle);
// return Result;
return;
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
uint processAccess,
bool bInheritHandle,
uint processId
);
public const UInt32 TOKEN_DUPLICATE = 0x0002;
[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
[DllImport("kernel32.dll", SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("wtsapi32.dll", SetLastError=true)]
static extern int WTSEnumerateSessions(
System.IntPtr hServer,
int Reserved,
int Version,
ref System.IntPtr ppSessionInfo,
ref int pCount);
[StructLayout(LayoutKind.Sequential)]
private struct WTS_SESSION_INFO
{
public Int32 SessionID;
[MarshalAs(UnmanagedType.LPStr)]
public String pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
[DllImport("wtsapi32.dll")]
static extern void WTSFreeMemory(IntPtr pMemory);
[DllImport("wtsapi32.dll", SetLastError=true)]
static extern bool WTSEnumerateProcesses(
IntPtr serverHandle, // Handle to a terminal server.
Int32 reserved, // must be 0
Int32 version, // must be 1
ref IntPtr ppProcessInfo, // pointer to array of WTS_PROCESS_INFO
ref Int32 pCount // pointer to number of processes
);
struct WTS_PROCESS_INFO
{
public int SessionID;
public int ProcessID;
//This is a pointer to string...
public IntPtr ProcessName;
public IntPtr UserSid;
}
[DllImport("ntdll.dll", SetLastError = true)]
static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
[DllImport("advapi32.dll")]
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
public static void GetOwnershipPrivilege()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeTakeOwnershipPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, true, out throwaway);
}
public static void GetAssignPrivilege()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeAssignPrimaryTokenPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, true, out throwaway);
}
public static void GetQuotaPrivilege()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeIncreaseQuotaPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, true, out throwaway);
}
public static void GetShutdownPrivilege()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeShutdownPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, true, out throwaway);
}
public static void RunAsUser(Action action)
{
var token = NSudo.GetUserToken();
Task.Run((Action)Delegate.Combine((Action)(() => { NSudo.GetUserPrivilege(token); }),
action)).Wait();
Marshal.FreeHGlobal(token);
}
private static async Task RunAsUserAsync(Action action)
{
var token = NSudo.GetUserToken();
await Task.Run((Action)Delegate.Combine((Action)(() => { NSudo.GetUserPrivilege(token); }),
action));
Marshal.FreeHGlobal(token);
}
}
}

+ 141
- 0
src/Program.cs View File

@ -0,0 +1,141 @@
using System;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Security.Principal;
using Ameliorated.ConsoleUtils;
using Microsoft.Win32;
using amecs.Actions;
using Menu = Ameliorated.ConsoleUtils.Menu;
namespace amecs
{
internal class Program
{
private const string Ver = "2.1";
public static ConsoleTUI.Frame Frame;
[STAThread]
public static void Main(string[] args)
{
ConsoleTUI.Initialize("Central AME Script");
try
{
NSudo.GetSystemPrivilege();
if (!WindowsIdentity.GetCurrent().IsSystem)
throw new Exception("Identity did not change.");
NSudo.RunAsUser(() =>
{
Globals.Username = WindowsIdentity.GetCurrent().Name.Split('\\').Last();
Globals.UserDomain = WindowsIdentity.GetCurrent().Name.Split('\\').FirstOrDefault();
Globals.UserSID = WindowsIdentity.GetCurrent().User.ToString();
});
try
{
Globals.UserFolder = Registry.Users.OpenSubKey(Globals.UserSID + "\\Volatile Environment").GetValue("USERPROFILE").ToString();
} catch (Exception e)
{
Console.WriteLine(Globals.Username);
ConsoleTUI.ShowErrorBox($"Could not fetch user folder information from user with SID '{Globals.UserSID}': " + e, "Central AME Script");
Environment.Exit(1);
}
PrincipalContext context = new PrincipalContext(ContextType.Machine);
PrincipalSearcher userPrincipalSearcher = new PrincipalSearcher(new UserPrincipal(context));
Globals.User = userPrincipalSearcher.FindAll().FirstOrDefault(x => (x is UserPrincipal) && x.Sid.Value == Globals.UserSID) as UserPrincipal;
PrincipalSearcher groupPrincipalSearcher = new PrincipalSearcher(new GroupPrincipal(context));
Globals.Administrators = groupPrincipalSearcher.FindAll().FirstOrDefault(x => (x is GroupPrincipal) && x.Sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid)) as GroupPrincipal;
} catch (Exception e)
{
ConsoleTUI.ShowErrorBox("Could not acquire System privileges: " + e, "Central AME Script");
Environment.Exit(1);
}
Frame = new ConsoleTUI.Frame($"| Central AME Script v{Ver} |", false);
Frame.Open();
while (true)
{
Globals.UserElevated = Globals.User.IsMemberOf(Globals.Administrators);
Frame.Clear();
bool usernameRequirement = new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System",
ValueName = "dontdisplaylastusername",
Data = 1,
}.IsEqual();
bool autoLogonEnabled = new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon",
ValueName = "DefaultUsername",
Data = Globals.Username,
}.IsEqual() &&
new Reg.Value()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon",
ValueName = "AutoAdminLogon",
Data = "1",
}.IsEqual();
bool netInstalled = new Reg.Key()
{
KeyName = @"HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5",
Operation = RegistryOperation.Add
}.IsEqual();
var mainMenu = new Ameliorated.ConsoleUtils.Menu()
{
Choices =
{
new Menu.MenuItem("Change Username or Password", new Func<bool>(UserPass.ShowMenu)),
new Menu.MenuItem("Change Lockscreen Image", new Func<bool>(Lockscreen.ChangeImage)),
new Menu.MenuItem("Change Profile Image", new Func<bool>(Profile.ChangeImage)),
Globals.UserElevated ?
new Menu.MenuItem( "De-elevate User", new Func<bool>(Elevation.DeElevate)) :
new Menu.MenuItem("Elevate User to Administrator", new Func<bool>(Elevation.Elevate)),
usernameRequirement ?
new Menu.MenuItem( "Disable Username Login Requirement", new Func<bool>(UsernameRequirement.Disable)) :
new Menu.MenuItem("Enable Username Login Requirement", new Func<bool>(UsernameRequirement.Enable)),
autoLogonEnabled ?
new Menu.MenuItem( "Disable AutoLogon", new Func<bool>(AutoLogon.Disable)) :
new Menu.MenuItem("Enable AutoLogon", new Func<bool>(AutoLogon.Enable)),
new Menu.MenuItem("Manage Language Settings", new Func<bool>(Languages.ShowMenu)),
new Menu.MenuItem("Manage Users", new Func<bool>(Users.ShowMenu)),
!netInstalled ?
new Menu.MenuItem("Install .NET 3.5", new Func<bool>(_NET.Install)) :
new Menu.MenuItem("Install .NET 3.5", new Func<bool>(_NET.Install)) {SecondaryText = "[Installed]", SecondaryTextForeground = ConsoleColor.Yellow, PrimaryTextForeground = ConsoleColor.DarkGray},
Menu.MenuItem.Blank,
new Menu.MenuItem("Uninstall AME", new Func<bool>(Deameliorate.DeAme)),
new Menu.MenuItem("Extra", new Func<bool>(Extra.Extra.ShowMenu)),
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit))
},
SelectionForeground = ConsoleColor.Green
};
Func<bool> result;
try
{
mainMenu.Write();
result = (Func<bool>)mainMenu.Load();
} catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
return;
}
try
{
result.Invoke();
} catch (Exception e)
{
ConsoleTUI.ShowErrorBox("Error while running an action: " + e.ToString(), null);
}
}
}
}
}

+ 35
- 0
src/Properties/AssemblyInfo.cs View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Central AME Script")]
[assembly: AssemblyDescription("Tool for automating a large assortment of AME related actions.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("amecs")]
[assembly: AssemblyCopyright("MIT License")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("BD020697-9E9B-4A46-8804-BC47F0FC2806")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.1")]
[assembly: AssemblyFileVersion("2.1")]

+ 375
- 0
src/Registry.cs View File

@ -0,0 +1,375 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Win32;
namespace amecs
{
public enum RegistryOperation
{
Delete = 0,
Add = 1
}
public class Reg
{
public class Key
{
public string KeyName { get; set; }
//public Scope Scope { get; set; } = Scope.AllUsers;
public RegistryOperation Operation { get; set; } = RegistryOperation.Delete;
private List<RegistryKey> GetRoots()
{
var hive = KeyName.Split('\\').GetValue(0).ToString().ToUpper();
var list = new List<RegistryKey>();
list.Add(hive switch
{
"HKCU" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
"HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
"HKLM" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
"HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
"HKCR" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
"HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
"HKU" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
"HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
_ => throw new ArgumentException($"Key '{KeyName}' does not specify a valid registry hive.")
});
return list;
}
public string GetSubKey() => KeyName.Substring(KeyName.IndexOf('\\') + 1);
public bool IsEqual()
{
try
{
var roots = GetRoots();
foreach (var _root in roots)
{
var root = _root;
var subKey = GetSubKey();
var openedSubKey = root.OpenSubKey(subKey);
if (Operation == RegistryOperation.Delete && openedSubKey != null)
{
return false;
}
if (Operation == RegistryOperation.Add && openedSubKey == null)
{
return false;
}
}
} catch (Exception e)
{
return false;
}
return true;
}
public bool Apply()
{
var roots = GetRoots();
foreach (var _root in roots)
{
var root = _root;
var subKey = GetSubKey();
var openedSubKey = root.OpenSubKey(subKey);
if (openedSubKey != null) openedSubKey.Close();
if (Operation == RegistryOperation.Add && openedSubKey == null)
{
root.CreateSubKey(subKey)?.Close();
}
if (Operation == RegistryOperation.Delete)
{
root.DeleteSubKeyTree(subKey, false);
}
root.Close();
}
return true;
}
}
public enum RegistryValueOperation
{
Delete = 0,
Add = 1,
// This indicates to skip the action if the specified value does not already exist
Set = 2
}
public enum RegistryValueType
{
REG_SZ = RegistryValueKind.String,
REG_MULTI_SZ = RegistryValueKind.MultiString,
REG_EXPAND_SZ = RegistryValueKind.ExpandString,
REG_DWORD = RegistryValueKind.DWord,
REG_QWORD = RegistryValueKind.QWord,
REG_BINARY = RegistryValueKind.Binary,
REG_NONE = RegistryValueKind.None,
REG_UNKNOWN = RegistryValueKind.Unknown
}
public class Value
{
public string KeyName { get; set; }
public string ValueName { get; set; } = "";
public object? Data { get; set; }
public RegistryValueType Type { get; set; }
//public Scope Scope { get; set; } = Scope.AllUsers;
public RegistryValueOperation Operation { get; set; } = RegistryValueOperation.Add;
private List<RegistryKey> GetRoots()
{
var hive = KeyName.Split('\\').GetValue(0).ToString().ToUpper();
var list = new List<RegistryKey>();
list.Add(hive switch
{
"HKCU" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
"HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
"HKLM" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
"HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
"HKCR" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
"HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
"HKU" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
"HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
_ => throw new ArgumentException($"Key '{KeyName}' does not specify a valid registry hive.")
});
return list;
}
public string GetSubKey() => KeyName.Substring(KeyName.IndexOf('\\') + 1);
public object? GetCurrentValue(RegistryKey root)
{
var subkey = GetSubKey();
return Registry.GetValue(root.Name + "\\" + subkey, ValueName, null);
}
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public bool IsEqual()
{
try
{
var roots = GetRoots();
foreach (var _root in roots)
{
var root = _root;
var subKey = GetSubKey();
var openedSubKey = root.OpenSubKey(subKey);
if (openedSubKey == null && (Operation == RegistryValueOperation.Set || Operation == RegistryValueOperation.Delete))
continue;
if (openedSubKey == null) return false;
var value = openedSubKey.GetValue(ValueName);
if (value == null)
{
if (Operation == RegistryValueOperation.Set || Operation == RegistryValueOperation.Delete)
continue;
return false;
}
if (Operation == RegistryValueOperation.Delete) return false;
if (Data == null) return false;
bool matches;
try
{
matches = Type switch
{
RegistryValueType.REG_SZ =>
Data.ToString() == value.ToString(),
RegistryValueType.REG_EXPAND_SZ =>
// RegistryValueOptions.DoNotExpandEnvironmentNames above did not seem to work.
Environment.ExpandEnvironmentVariables(Data.ToString()) == value.ToString(),
RegistryValueType.REG_MULTI_SZ =>
Data.ToString() == "" ? ((string[])value).SequenceEqual(new string[] { }) : ((string[])value).SequenceEqual(Data.ToString().Split(new string[] { "\\0" }, StringSplitOptions.None)),
RegistryValueType.REG_DWORD =>
unchecked((int)Convert.ToUInt32(Data)) == (int)value,
RegistryValueType.REG_QWORD =>
Convert.ToUInt64(Data) == (ulong)value,
RegistryValueType.REG_BINARY =>
((byte[])value).SequenceEqual(StringToByteArray(Data.ToString())),
RegistryValueType.REG_NONE =>
((byte[])value).SequenceEqual(new byte[0]),
RegistryValueType.REG_UNKNOWN =>
Data.ToString() == value.ToString(),
_ => throw new ArgumentException("Impossible.")
};
} catch (InvalidCastException)
{
matches = false;
}
if (!matches) return false;
}
} catch (Exception e)
{
return false;
}
return true;
}
public bool Apply()
{
var roots = GetRoots();
foreach (var _root in roots)
{
var root = _root;
var subKey = GetSubKey();
if (GetCurrentValue(root) == Data) continue;
var opened = root.OpenSubKey(subKey);
if (opened == null && Operation == RegistryValueOperation.Set) continue;
if (opened == null && Operation == RegistryValueOperation.Add) root.CreateSubKey(subKey)?.Close();
if (opened != null) opened.Close();
if (Operation == RegistryValueOperation.Delete)
{
var key = root.OpenSubKey(subKey, true);
key?.DeleteValue(ValueName);
key?.Close();
root.Close();
continue;
}
if (Type == RegistryValueType.REG_BINARY)
{
var data = StringToByteArray(Data.ToString());
Registry.SetValue(root.Name + "\\" + subKey, ValueName, data, (RegistryValueKind)Type);
}
else if (Type == RegistryValueType.REG_DWORD)
{
// DWORD values using the highest bit set fail without this, for example '2962489444'.
// See https://stackoverflow.com/questions/6608400/how-to-put-a-dword-in-the-registry-with-the-highest-bit-set;
var value = unchecked((int)Convert.ToUInt32(Data));
Registry.SetValue(root.Name + "\\" + subKey, ValueName, value, (RegistryValueKind)Type);
}
else if (Type == RegistryValueType.REG_QWORD)
{
Registry.SetValue(root.Name + "\\" + subKey, ValueName, Convert.ToUInt64(Data), (RegistryValueKind)Type);
}
else if (Type == RegistryValueType.REG_NONE)
{
byte[] none = new byte[0];
Registry.SetValue(root.Name + "\\" + subKey, ValueName, none, (RegistryValueKind)Type);
}
else if (Type == RegistryValueType.REG_MULTI_SZ)
{
string[] data;
if (Data.ToString() == "") data = new string[] { };
else data = Data.ToString().Split(new string[] { "\\0" }, StringSplitOptions.None);
Registry.SetValue(root.Name + "\\" + subKey, ValueName, data, (RegistryValueKind)Type);
}
else
{
Registry.SetValue(root.Name + "\\" + subKey, ValueName, Data, (RegistryValueKind)Type);
}
root.Close();
}
return true;
}
}
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey);
[DllImport("ntdll.dll", SetLastError = true)]
static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
[DllImport("advapi32.dll")]
static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid);
[DllImport("advapi32.dll")]
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
public static void LoadDefaultUserHive()
{
var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
IntPtr parentHandle = parentKey.Handle.DangerousGetHandle();
AcquirePrivileges();
RegLoadKey(parentHandle, "DefaultUserHive", Environment.ExpandEnvironmentVariables(@"%SYSTEMDRIVE%\Users\Default\NTUSER.dat"));
parentKey.Close();
}
public static void UnloadDefaultUserHive()
{
var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
AcquirePrivileges();
RegUnLoadKey(parentKey.Handle.DangerousGetHandle(), "DefaultUserHive");
parentKey.Close();
}
public static void AcquirePrivileges()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, true, out throwaway);
LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, true, true, out throwaway);
}
public static void ReturnPrivileges()
{
ulong luid = 0;
bool throwaway;
LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
RtlAdjustPrivilege((int)luid, false, true, out throwaway);
LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
RtlAdjustPrivilege((int)luid, false, true, out throwaway);
}
}
}

+ 263
- 0
src/amecs.cs View File

@ -0,0 +1,263 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Ameliorated.ConsoleUtils;
namespace amecs
{
public class amecs
{
public static bool RunBasicAction(string status, string result, Action action, bool logoff = false, bool restart = false)
{
ConsoleTUI.OpenFrame.WriteCentered(status);
try
{
using (new ConsoleUtils.LoadingIndicator(true))
{
action.Invoke();
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " });
return false;
}
Console.WriteLine();
if (logoff)
{
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
TextForeground = ConsoleColor.Yellow,
Text = "Logoff to apply changes? (Y/N): "
}) == 0) amecs.RestartWindows(true);
return true;
}
if (restart)
{
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
TextForeground = ConsoleColor.Yellow,
Text = "Restart to apply changes? (Y/N): "
}) == 0) amecs.RestartWindows(false);
return true;
}
ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
public static bool RunBasicAction(string status, string result, Action<int> action, ChoicePrompt prompt = null, bool logoff = false, bool restart = false)
{
int choice = -1;
if (prompt != null)
{
var choiceRes = prompt.Start();
if (!choiceRes.HasValue)
return true;
choice = choiceRes.Value;
}
ConsoleTUI.OpenFrame.WriteCentered(status);
try
{
using (new ConsoleUtils.LoadingIndicator(true))
{
action.Invoke(choice);
}
} catch (Exception e)
{
Console.WriteLine();
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " });
return false;
}
Console.WriteLine();
if (logoff)
{
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
TextForeground = ConsoleColor.Yellow,
Text = "Logoff to apply changes? (Y/N): "
}) == 0) amecs.RestartWindows(true);
return true;
}
if (restart)
{
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt()
{
TextForeground = ConsoleColor.Yellow,
Text = "Restart to apply changes? (Y/N): "
}) == 0) amecs.RestartWindows(false);
return true;
}
ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "});
return true;
}
[Flags]
enum ExitWindows : uint
{
// ONE of the following five:
LogOff = 0x00,
ShutDown = 0x01,
Reboot = 0x02,
PowerOff = 0x08,
RestartApps = 0x40,
// plus AT MOST ONE of the following two:
Force = 0x04,
ForceIfHung = 0x10,
}
[Flags]
enum ShutdownReason : uint
{
MajorApplication = 0x00040000,
MajorHardware = 0x00010000,
MajorLegacyApi = 0x00070000,
MajorOperatingSystem = 0x00020000,
MajorOther = 0x00000000,
MajorPower = 0x00060000,
MajorSoftware = 0x00030000,
MajorSystem = 0x00050000,
MinorBlueScreen = 0x0000000F,
MinorCordUnplugged = 0x0000000b,
MinorDisk = 0x00000007,
MinorEnvironment = 0x0000000c,
MinorHardwareDriver = 0x0000000d,
MinorHotfix = 0x00000011,
MinorHung = 0x00000005,
MinorInstallation = 0x00000002,
MinorMaintenance = 0x00000001,
MinorMMC = 0x00000019,
MinorNetworkConnectivity = 0x00000014,
MinorNetworkCard = 0x00000009,
MinorOther = 0x00000000,
MinorOtherDriver = 0x0000000e,
MinorPowerSupply = 0x0000000a,
MinorProcessor = 0x00000008,
MinorReconfig = 0x00000004,
MinorSecurity = 0x00000013,
MinorSecurityFix = 0x00000012,
MinorSecurityFixUninstall = 0x00000018,
MinorServicePack = 0x00000010,
MinorServicePackUninstall = 0x00000016,
MinorTermSrv = 0x00000020,
MinorUnstable = 0x00000006,
MinorUpgrade = 0x00000003,
MinorWMI = 0x00000015,
FlagUserDefined = 0x40000000,
FlagPlanned = 0x80000000
}
[DllImport("user32.dll")]
static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool InitiateSystemShutdownEx(
string lpMachineName,
string lpMessage,
uint dwTimeout,
bool bForceAppsClosed,
bool bRebootAfterShutdown,
ShutdownReason dwReason);
public static void RestartWindows(bool logoff, bool cmd = false)
{
if (cmd)
{
var psi = new ProcessStartInfo("shutdown","/r /t 0");
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
Process.Start(psi);
Environment.Exit(0);
}
if (!logoff)
{
NSudo.GetShutdownPrivilege();
InitiateSystemShutdownEx(null, null, 0, false, true, ShutdownReason.MinorInstallation);
} else
ExitWindowsEx((uint)ExitWindows.LogOff | (uint)ExitWindows.ForceIfHung, (uint)ShutdownReason.MinorInstallation);
Environment.Exit(0);
}
public static object ShowDefaultMenu(List<Menu.MenuItem> list)
{
list.AddRange(new [] {
Menu.MenuItem.BlankStatic,
new Menu.MenuItem("Next Page", null) { IsNextButton = true },
new Menu.MenuItem("Previous Page", null) { IsPreviousButton = true },
new Menu.MenuItem("Return to Menu", new Func<bool>(() => true)) { IsStatic = true },
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)) { IsStatic = true },
});
var mainMenu = new Menu()
{
Choices = list,
SelectionForeground = ConsoleColor.Green
};
mainMenu.Write();
return mainMenu.Load();
}
[DllImport("wininet.dll", SetLastError = true)]
public static extern bool InternetCheckConnection(string lpszUrl, int dwFlags, int dwReserved);
[DllImport("wininet.dll", SetLastError=true)]
private extern static bool InternetGetConnectedState(out int lpdwFlags, int dwReserved);
public static bool IsInternetAvailable()
{
try
{
try
{
if (!InternetCheckConnection("http://archlinux.org", 1, 0))
{
if (!InternetCheckConnection("http://google.com", 1, 0))
return false;
}
return true;
}
catch
{
var request = (HttpWebRequest)WebRequest.Create("http://google.com");
request.KeepAlive = false;
request.Timeout = 5000;
using (var response = (HttpWebResponse)request.GetResponse())
return true;
}
}
catch
{
return false;
}
}
}
}

+ 266
- 0
src/amecs.csproj View File

@ -0,0 +1,266 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>amecs.ico</ApplicationIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BD020697-9E9B-4A46-8804-BC47F0FC2806}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>amecs</RootNamespace>
<AssemblyName>amecs</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<LangVersion>8</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>embedded</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32bit>false</Prefer32bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>embedded</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>RELEASE;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32bit>false</Prefer32bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath>
</Reference>
<Reference Include="JetBrains.Annotations, Version=4242.42.42.42, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
<HintPath>packages\JetBrains.Annotations.2023.3.0\lib\net20\JetBrains.Annotations.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Dism, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5bba90053b345501, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Dism.3.1.0\lib\net40\Microsoft.Dism.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.AppContext, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll</HintPath>
</Reference>
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.CodeDom, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.CodeDom.8.0.0\lib\net462\System.CodeDom.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Configuration" />
<Reference Include="System.Console, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Console.4.3.1\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.OracleClient" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Tracing, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll</HintPath>
</Reference>
<Reference Include="System.DirectoryServices" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Drawing" />
<Reference Include="System.Drawing.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Drawing.Primitives.4.3.0\lib\net45\System.Drawing.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath>
</Reference>
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.AccessControl, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.FileSystem.AccessControl.5.0.0\lib\net461\System.IO.FileSystem.AccessControl.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Linq, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Linq.4.3.0\lib\net463\System.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Expressions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Reflection, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
</Reference>
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Extensions, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
</Reference>
<Reference Include="System.Security" />
<Reference Include="System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
</Reference>
<Reference Include="System.Security.Permissions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Permissions.8.0.0\lib\net462\System.Security.Permissions.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Text.RegularExpressions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Text.RegularExpressions.4.3.1\lib\net463\System.Text.RegularExpressions.dll</HintPath>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Actions\.NET.cs" />
<Compile Include="Actions\AutoLogon.cs" />
<Compile Include="Actions\Deameliorate.cs" />
<Compile Include="Actions\Elevation.cs" />
<Compile Include="Actions\Languages.cs" />
<Compile Include="Actions\Lockscreen.cs" />
<Compile Include="Actions\Profile.cs" />
<Compile Include="Actions\UsernameRequirement.cs" />
<Compile Include="Actions\UserPass.cs" />
<Compile Include="Actions\Users.cs" />
<Compile Include="amecs.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\ConsoleTUI.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\Frame.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\FrameWriteMethods.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\Menu.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\MouseInterface.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\Prompt.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ConsoleUtils.cs" />
<Compile Include="Ameliorated.ConsoleUtils\Extensions.cs" />
<Compile Include="Ameliorated.ConsoleUtils\ParentProcess.cs" />
<Compile Include="Ameliorated.ConsoleUtils\Payload.cs" />
<Compile Include="Extra\Extra.cs" />
<Compile Include="Extra\NVCP.cs" />
<Compile Include="Extra\WSH.cs" />
<Compile Include="Globals.cs" />
<Compile Include="Misc\FolderPicker.cs" />
<Compile Include="Misc\SelectWindowsImage.cs" />
<Compile Include="NSudo.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Registry.cs" />
</ItemGroup>
<ItemGroup>
<None Include="amecs.ico" />
<None Include="amecs.png" />
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Menus" />
<Folder Include="NSudo" />
</ItemGroup>
<ItemGroup>
<Content Include="app.manifest" />
</ItemGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary">
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" />
<Error Condition="!Exists('packages\Fody.6.8.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.8.0\build\Fody.targets'))" />
<Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
</Target>
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" />
<Import Project="packages\Fody.6.8.0\build\Fody.targets" Condition="Exists('packages\Fody.6.8.0\build\Fody.targets')" />
<Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

BIN
src/amecs.ico View File

Before After

BIN
src/amecs.png View File

Before After
Width: 696  |  Height: 696  |  Size: 421 KiB

+ 16
- 0
src/amecs.sln View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "amecs", "amecs.csproj", "{BD020697-9E9B-4A46-8804-BC47F0FC2806}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

BIN
src/amecs_old.ico View File

Before After

+ 17
- 0
src/app.manifest View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Support Windows 10 and above - needed for certain functions to return
correct Windows version. https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#supportedOS -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

+ 66
- 0
src/packages.config View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="5.7.0" targetFramework="net472" developmentDependency="true" />
<package id="Fody" version="6.8.0" targetFramework="net472" developmentDependency="true" />
<package id="JetBrains.Annotations" version="2023.3.0" targetFramework="net472" />
<package id="Microsoft.Dism" version="3.1.0" targetFramework="net472" />
<package id="Microsoft.NETCore.Platforms" version="7.0.4" targetFramework="net472" />
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" />
<package id="NETStandard.Library" version="2.0.3" targetFramework="net472" />
<package id="System.AppContext" version="4.3.0" targetFramework="net472" />
<package id="System.CodeDom" version="8.0.0" targetFramework="net472" />
<package id="System.Console" version="4.3.1" targetFramework="net472" />
<package id="System.Diagnostics.DiagnosticSource" version="8.0.0" targetFramework="net472" />
<package id="System.DirectoryServices" version="8.0.0" targetFramework="net472" />
<package id="System.DirectoryServices.AccountManagement" version="8.0.0" targetFramework="net472" />
<package id="System.Management" version="8.0.0" targetFramework="net472" />
<package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
<package id="System.Runtime.Extensions" version="4.3.1" targetFramework="net472" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" />
<package id="System.Security.Permissions" version="8.0.0" targetFramework="net472" />
<package id="System.Text.RegularExpressions" version="4.3.1" targetFramework="net472" />
<package id="System.Xml.ReaderWriter" version="4.3.1" targetFramework="net472" />
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
<package id="System.Net.Primitives" version="4.3.1" targetFramework="net472" />
<package id="System.Runtime" version="4.3.1" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Collections" version="4.3.0" targetFramework="net472" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net472" />
<package id="System.Drawing.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Globalization" version="4.3.0" targetFramework="net472" />
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net472" />
<package id="System.IO" version="4.3.0" targetFramework="net472" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net472" />
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net472" />
<package id="System.IO.FileSystem.AccessControl" version="5.0.0" targetFramework="net472" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Linq" version="4.3.0" targetFramework="net472" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net472" />
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.ObjectModel" version="4.3.0" targetFramework="net472" />
<package id="System.Reflection" version="4.3.0" targetFramework="net472" />
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net472" />
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
<package id="System.Security.AccessControl" version="6.0.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net472" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net472" />
<package id="System.Threading" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net472" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" />
</packages>

Loading…
Cancel
Save