WindowsUtils is a PowerShell module designed to make easier the administration of Windows computers.
The module consists in a library written in C++/CLI which contains the main functions, and the .NET wrapper.
To get information on how to use it, use Get-Help Cmdlet-Name -Full.
- WindowsUtils
- Installation
- Cmdlets
- Invoke-RemoteMessage
- Get-RemoteMessageOptions
- Get-ComputerSession
- Send-Click
- Get-ResourceMessageTable
- Get-ErrorString (gerrmess)
- Get-LastWin32Error
- Get-ObjectHandle (gethandle)
- Get-MsiProperties
- Disconnect-Session (disconnect)
- Remove-Service
- Get-ServiceSecurity
- New-ServiceAccessRule
- New-ServiceAuditRule
- Set-ServiceSecurity
- Get-InstalledDotnet (getdotnet)
- Expand-Cabinet
- Start-Tcping (tcping)
- Start-ProcessAsUser (runas)
- Get-NetworkFile (psfile, getnetfile)
- Close-NetworkFile (closenetfile)
- New-Cabinet
- Test-Port (testport)
- Get-ProcessModule (listdlls)
- Suspend-Process (suspend)
- Resume-Process (resume)
- Get-ErrorInformation (err)
- Get-MsiSummaryInfo
- Get-MsiTableInfo
- Get-MsiTableData
- Invoke-MsiQuery (imsisql)
- Changelog
- Support
This module is available on the PowerShell Gallery.
To install it, you can use PowerShellGet.
Install-Module -Name 'WindowsUtils'
Import-Module -Name 'WindowsUtils'
If you clone the repository, build WindowsUtils.csproj, and the module will be found at .\bin\WindowsUtils.
To import it in a PowerShell session, use Import-Module on the module manifest or folder.
Import-Module -Name '.\bin\WindowsUtils'
Import-Module -Name '.\bin\WindowsUtils\WindowsUtils.psd1'
This Cmdlet is the Windows Terminal Services equivalent of the MessageBox function.
It allows you to send messages on the local, or remote computers. On all or selected interactive sessions.
Invoke-RemoteMessage -Title 'Awesome message!' -Message 'Hello dude.' -SessionId 1 -Style 'MB_OKCANCEL','MB_ICONINFORMATION' -Timeout 30 -Wait
This Cmdlet returns all options available to be used with the parameter Style, from Invoke-RemoteMessage.
These options are named like the ones from the MessageBox function.
Get-RemoteMessageOptions | Format-Table * -Autosize
This Cmdlet allows you to list sessions on the local and remote computers.
Get-ComputerSession -ComputerName 'MYQUANTUMCOMPUTER.contoso.com' -ActiveOnly -IncludeSystemSession
Sends a click on the current desktop.
Send-Click
This Cmdlet was designed to retrieve messages stored in a message table, in a file.
These files are usually libraries used by the system, and other applications, for error handling, status and many others.
It is specially useful to build automations for Microsof Endpoint Configuration Manager, based on Status Messages.
Get-ResourceMessageTable -Path 'C:\Windows\System32\kernel32.dll'
This Cmdlet retrieves the message for a 'Win32', 'NTSTATUS', 'FDI' and 'FCI' errors Trivia: These errors are stored in message tables, inside system DLLs, which you can list with the previous Cmdlet.
Get-ErrorString -ErrorCode 5
Access is denied.
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error() | Get-FormattedError
This Cmdlet returns the last 'Win32' error thrown by the system.
Does the same as the GetLastWin32Error() method, from System.Runtime.InteropServices.Marshal, but brings the error message instead of the code.
Get-LastWin32Error
My favorite one, and the one I had most fun building.
This Cmdlet was designed to mimic the famous Handle, from Sysinternals.
It shows which process holds a handle to a file or directory. This information can be used when you need to modify or delete a file locked by a process.
You can close handles to objects using -CloseHandle.
Get-ObjectHandle -Path 'C:\Windows\System32\kernel32.dll', 'C:\Windows\System32\ntdll.dll'
Get-ObjectHandle -Path "$env:TEMP\*.tmp"
Get-ObjectHandle -Path "${env:ProgramFiles(x86)}\7-zip\7-zip.dll" -CloseHandle
Get-ObjectHandle -Path "${env:ProgramFiles(x86)}\7-zip\7-zip.dll" -CloseHandle -Force
Get-ChildItem -Path 'C:\Windows\System32' -Filter '*.dll' | Get-ObjectHandle
gethandle -ProcessId 666
Get-Process -Id 666 | gethandle -All
PS C:\Windows\System32>_ Get-ObjectHandle csrss*
Another favorite of mine, this Cmdlet get's information about MSI files, from the installer database.
This can also be achieved using the WindowsInstaller.Installer object, and in fact, it uses the same object, but called directly via WINAPI.
Get-MsiProperties -Path 'C:\Users\You\Downloads\PowerShell-Installer.msi'
This Cmdlet disconnects interactive sessions on the local, or remote computers.
It disconnects based on the SessionId, which can be obtained with Get-ComputerSession.
Disconnect-Session -ComputerName 'MYQUANTUMCOMPUTER.contoso.com' -SessionId 3 -Wait
This Cmdlet deletes a service installed in the current or remote computer. You can choose to stop the service, and its dependents to make sure the service is deleted as soon as possible. To remove a service is ultimately to mark it to deletion. The removal might not be instantaneous.
# Removes the service 'MyCoolService'.
Remove-Service -Name 'MyCoolService'
# Stops the service, and its dependents, and remove it. 'Force' skips confirmation.
Remove-Service -Name 'MyCoolService' -Stop -Force
This Cmdlet gets the security attributes for a service. These include the DACL, and optionally the SACL.
It was designed to be familiar with the '*-Acl' Cmdlet series, like Get-Acl
. In fact, the objects where
created based on the same objects.
Get-ServiceSecurity wuauserv | Format-List *
Name : wuauserv
AccessToString : NT AUTHORITY\Authenticated Users Allow Start, GenericRead
NT AUTHORITY\SYSTEM Allow AllAccess
BUILTIN\Administrators Allow AllAccess
AuditToString :
Access : {WindowsUtils.AccessControl.ServiceAccessRule, WindowsUtils.AccessControl.ServiceAccessRule, WindowsUtils.AccessControl.ServiceAccessRule}
Audit : {}
AccessRightType : WindowsUtils.Services.ServiceRights
AccessRuleType : WindowsUtils.AccessControl.ServiceAccessRule
AuditRuleType : WindowsUtils.AccessControl.ServiceAuditRule
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Sddl : O:SYG:SYD:(A;;CCLCSWRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)
AreAccessRulesProtected : False
AreAuditRulesProtected : False
AreAccessRulesCanonical : True
AreAuditRulesCanonical : True
Get-ServiceSecurity wuauserv -Audit | Format-List *
Name : wuauserv
AccessToString : NT AUTHORITY\Authenticated Users Allow Start, GenericRead
NT AUTHORITY\SYSTEM Allow AllAccess
BUILTIN\Administrators Allow AllAccess
AuditToString : Everyone Failure ChangeConfig, Start, Stop, PauseContinue, Delete, GenericRead, WriteDac, WriteOwner
Access : {WindowsUtils.AccessControl.ServiceAccessRule, WindowsUtils.AccessControl.ServiceAccessRule, WindowsUtils.AccessControl.ServiceAccessRule}
Audit : {WindowsUtils.AccessControl.ServiceAuditRule}
AccessRightType : WindowsUtils.Services.ServiceRights
AccessRuleType : WindowsUtils.AccessControl.ServiceAccessRule
AuditRuleType : WindowsUtils.AccessControl.ServiceAuditRule
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Sddl : O:SYG:SYD:(A;;CCLCSWRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)S:(AU;FA;CCDCLCSWRPWPDTLOSDRCWDWO;;;WD)
AreAccessRulesProtected : False
AreAuditRulesProtected : False
AreAccessRulesCanonical : True
AreAuditRulesCanonical : True
This Cmdlet creates a service access rule (DACL) used to change service security.
You can use the new access rule with Set-ServiceSecurity
.
New-ServiceAccessRule -Identity 'NT AUTHORITY\SYSTEM' -Rights 'ChangeConfig' -Type 'Allow' -InheritanceFlags 'ObjectInherit' -PropagationFlags 'InheritOnly'
ServiceRights : ChangeConfig
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited : False
InheritanceFlags : ObjectInherit
PropagationFlags : InheritOnly
This Cmdlet creates a service audit rule (SACL) used to change service security.
You can use the new audit rule with Set-ServiceSecurity
.
New-ServiceAuditRule -Identity 'NT AUTHORITY\SYSTEM' -Rights 'EnumerateDependents' -Flags 'Failure'
ServiceRights : EnumerateDependents
AuditFlags : Failure
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
This Cmdlet changes service security. It was designed to work like the Set-Acl
Cmdlet.
You typically use this Cmdlet with the other service security commands.
$serviceSecurity = Get-ServiceSecurity -Name test_service
$newRule = New-ServiceAccessRule -Identity 'CONTOSO\User' -Rights 'EnumerateDependents' -Type 'Allow'
$serviceSecurity.AddAccessRule($newRule)
Set-ServiceSecurity -Name test_service -SecurityObject $serviceSecurity
This Cmdlet returns all .NET versions installed in the computer. Additionally, you can return the installed patches for .NET.
Get-InstalledDotnet
Version Edition ComputerName
------- ------- ------------
4.8.9032 FullFramework MYCOMPUTERNAME
Get-InstalledDotnet -InlcudeUpdate | Select-Object -ExpandProperty InstalledUpdates
Version InstalledUpdates ComputerName
------- ---------------- ------------
Microsoft .NET Framework 4 Client Profile {KB2468871, KB2468871v2, KB2478063, KB2533523…} MYCOMPUTERNAME
Microsoft .NET Framework 4 Extended {KB2468871, KB2468871v2, KB2478063, KB2533523…} MYCOMPUTERNAME
This Cmdlet extracts files from a cabinet file. This Cmdlet is provider-aware.
# Extracts files from 'Cabinet.cab' to the 'Destination' folder.
Expand-Cabinet -Path "$env:SystemDrive\Path\To\Cabinet.cab" -Destination "$env:SystemDrive\Path\To\Destination"
# Extract files from all cabinet files from 'C:\CabinetSource' that matches 'MultipleCab*'.
Get-ChildItem -Path 'C:\CabinetSource\MultipleCab*' | Expand-Cabinet -Destination 'C:\Path\To\Destination'
This Cmdlet attempts to measure network statistics while connecting to a destination using TCP. It works similarly as well-known tools like 'ping.exe', or 'tcping.exe'. The parameters contain aliases that mimic the parameter in those applications.
Start-Tcping -Destination learn.microsoft.com -Port 443 -IncludeJitter
Destination Port Status Times
----------- ---- ------ -----
learn.microsoft.com 443 Open Rtt: 7.14
learn.microsoft.com 443 Open Rtt: 8.50, Jitter: 1.36
learn.microsoft.com 443 Open Rtt: 9.50, Jitter: 1.68
learn.microsoft.com 443 Open Rtt: 7.59, Jitter: 0.79
Sent : 4
Succeeded : 4
Failed : 0
FailedPercent : 0.00%
MinTimes : Rtt: 7.59, Jitter: 0.79
AvgTimes : Rtt: 8.18, Jitter: 1.28
MaxTimes : Rtt: 9.50, Jitter: 1.68
tcping learn.microsoft.com, google.com -Port 80, 443 -s
Destination Port Status Times
----------- ---- ------ -----
learn.microsoft.com 80 Open Rtt: 8.32
learn.microsoft.com 443 Open Rtt: 19.91
google.com 80 Open Rtt: 9.57
google.com 443 Open Rtt: 7.01
This Cmdlet logs in a user and starts a process with it.
This is my terrible attempt to reverse engineer 'runas.exe'.
It works by typing the credentials in the go, like 'runas.exe', or using
a PSCredential
.
Start-ProcessAsUser CONTOSO\francisco.nabas powershell
Of course we have an alias for it.
runas -CommandLine powershell -Credential (Get-Credential)
This Cmdlet lists all files opened through the network on the current or remote computer.
It was designed to mimic psfile.exe
from Sysinternals.
Get-NetworkFile -ComputerName CISCOSRVP01P
Id Path LockCount UserName Permissions
-- ---- --------- -------- -----------
8 C:\ 0 francisco.nabas Read
14 C:\Program Files 0 francisco.nabas Read
18 C:\Program Files\Microsoft Analysis Services 0 francisco.nabas Read
24 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
25 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
28 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
29 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
40 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
43 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
56 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
59 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
60 \srvsvc 0 francisco.nabas Read, Write, ChangeAttribute
psfile CISCOSRVP01P -IncludeConnectionName | Select-object * -First 1
ComputerName : CISCOSRVP01P
SessionName : 10.21.13.152
UserName : francisco.nabas
LockCount : 0
Permissions : Read
Path : C:\
Id : 8
psfile CISCOSRVP01P -BasePath 'C:\Program Files\Microsoft Analysis Services'
Id Path LockCount UserName Permissions
-- ---- --------- -------- -----------
18 C:\Program Files\Microsoft Analysis Services 0 francisco.nabas Read
24 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
25 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
28 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
29 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
40 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
43 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
59 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
getnetfile CISCOSRVP01P -UserConnectionFilter 'francisco.nabas'
Id Path LockCount UserName Permissions
-- ---- --------- -------- -----------
8 C:\ 0 francisco.nabas Read
14 C:\Program Files 0 francisco.nabas Read
18 C:\Program Files\Microsoft Analysis Services 0 francisco.nabas Read
24 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
25 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
28 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
29 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
40 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
43 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
59 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
64 \srvsvc 0 francisco.nabas Read, Write, ChangeAttribute
This Cmdlet closes files opened through the network on the local or remote computer.
It was designed to work in conjunction with Get-NetworkFile
.
It is also based on psfile.exe
, from Sysinternals.
Get-NetworkFile -ComputerName CISCOSRVP01P
Id Path LockCount UserName Permissions
-- ---- --------- -------- -----------
24 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
25 C:\Program Files\Microsoft Analysis Services\AS OLEDB 0 francisco.nabas Read
28 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
29 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
59 C:\Program Files\Microsoft Analysis Services\AS OLEDB\140 0 francisco.nabas Read
140 C:\Windows\SYSVOL\sysvol\nabas.com\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine 0 CISCOCS01P$ Read
141 C:\Windows\SYSVOL\sysvol\nabas.com\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Microsoft 0 CISCOCS01P$ Read
142 C:\Windows\SYSVOL\sysvol\nabas.com\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Microsoft\Windows NT 0 CISCOCS01P$ Read
143 C:\Windows\SYSVOL\sysvol\nabas.com\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Machine\Microsoft\Windows NT\SecEdit 0 CISCOCS01P$ Read
147 \srvsvc
Close-NetworkFile -ComputerName CISCOSRVP01P -FileId 24
getnetfile CISCOSRVP01P | ? UserName -eq 'francisco.nabas' | closenetfile -Force
This Cmdlet creates a new cabinet based on a source path. It must be a valid path to a file or folder. If the path is a folder, it will search for files recursively, and compress them. Cabinet files only accept files up to 2Gb of length, and the maximum size for a cabinet is also 2Gb.
New-Cabinet -Path 'C:\Path\To\Files' -Destination 'C:\Path\To\Destination'
You can also limit the size of the cabinet, in kilobytes. If the files surpass this limit they will span over multiple files
New-Cabinet -Path 'C:\Path\To\Files' -Destination 'C:\Path\To\Destination' -MaxCabSize 20000
This Cmdlet tests if a TCP or UDP port is open in a given destination.
Attention! Due to the nature of UDP packets, Test-Port
might return false positive if a timeout occur when testing against public domains, like 'google.com'.
UPD testing is better used with LAN servers.
Test-Port -ComputerName 'google.com' -TcpPort 80
testport 'SUPERSERVER.contoso.com' 443
testport 'SUPERSERVER1.contoso.com', 'SUPERSERVER2.contoso.com' -TcpPort 80, 443, 1433 -UdpPort 67, 68, 69, 4011
This Cmdlet lists modules loaded into processes. You can list modules for one or more processes, or all of them. You can also include module file version information (with a performance penalty).
Get-ProcessModule -Name 'explorer'
listdlls -ProcessId 666, 667 -IncludeVersionInfo
listdlls
This Cmdlet suspends a running process.
Suspend-Process -Name 'notepad'
suspend -Id 666
This Cmdlet resumes a suspended process. It does nothing on running processes.
Resume-Process -Name 'notepad'
resume -Id 666
This Cmdlet mimics 'Err.exe'. In fact, the error database is extracted from it.
Get-ErrorInformation -ErrorCode 0xC0000008
err 0x80070057
ErrorCode HexCode IsHResult SymbolicName Description
--------- ------- --------- ------------ -----------
-2147024809 0x80070057 True XNS_INTERNAL_ERROR
-2147024809 0x80070057 False COR_E_ARGUMENT An argument does not meet the contract of the method.
-2147024809 0x80070057 False DDERR_INVALIDPARAMS
-2147024809 0x80070057 False DIERR_INVALIDPARAM
-2147024809 0x80070057 False DSERR_INVALIDPARAM
-2147024809 0x80070057 True NMERR_FRAME_HAS_NO_CAPTURE
-2147024809 0x80070057 False STIERR_INVALID_PARAM
-2147024809 0x80070057 False DRM_E_INVALIDARG
-2147024809 0x80070057 True ERROR_INVALID_PARAMETER The parameter is incorrect.
-2147024809 0x80070057 False E_INVALIDARG One or more arguments are invalid
-2147024809 0x80070057 True LDAP_FILTER_ERROR
This Cmdlet gets the summary information from a Windows Installer. Summary data contains information about the author, languages, platforms, creation time, UAC compliance and more.
Get-MsiSummaryInfo -Path 'C:\Path\To\Installer.msi'
This Cmdlet gets table information from a Windows Installer's database. You can list information about a single table, multiple tables, or all tables in the database. Contains the table name and column information, like type, position, if it's key, nullable, etc.
Get-MsiTableInfo -Path 'C:\Path\To\Installer.msi' -Table 'Feature', 'Registry'
Get-MsiTableInfo 'C:\Path\To\Installer.msi'
This Cmdlet gets the data from a table in a Windows Installer's Database. This works for built-in, and custom tables.
Get-MsiTableData -Path 'C:\Path\To\Installer.msi' -Table 'Feature', 'Registry'
Get-MsiTableData 'C:\Path\To\Installer.msi' 'Feature'
Get-MsiTableInfo -Path 'C:\Path\To\Installer.msi' -Table 'Feature', 'Registry' | Get-MsiTableData
This Cmdlet executes a query in a Windows Installer MSI database.
ATTENTION! The SQL language used in the installer database is quite finicky. Be sure to check the notes, and related links for more information.
You can reach that information with Get-Help Invoke-MsiQuery -Full
.
Invoke-MsiQuery -Path 'C:\SuperInstaller.msi' -Query 'SELECT * FROM Registry' | Format-Table -AutoSize
Invoke-MsiQuery 'C:\SuperInstaller.msi' "INSERT INTO Registry (Registry, Root, ``Key``, Name, Value, Component_) VALUES ('NeatNewKey', 0, 'SOFTWARE\NeatKey', 'NeatKey', 'KeyValue', 'KeyComponent')"
$parameter = [WindowsUtils.Installer.InstallerCommandParameter]::new('String', 'ProductCode')
imsisql 'C:\SuperInstaller.msi' 'Select * From Property Where Property = ?' -Parameters $parameter
$parameter = [WindowsUtils.Installer.InstallerCommandParameter]::new('File', 'C:\Path\To\InstallerIcon.ico')
imsisql 'C:\SuperInstaller.msi' "INSERT INTO Icon (Name, Data) VALUES ('IconName', ?)" -Parameters $parameter
Versioning information can be found on the Changelog file.
Changelogging began at version 1.3.0, because I didn't keep track before that.
No way you made it down here LOL.
If you have an idea, or a solution you'd like to have in PowerShell, Windows-related, regardless of how absurd it might sound, let me know. I'd love to try it.
This is a module from a Sysadmin to Sysadmins, if you know how to program using C++/CLI and C#, and want to contribute, fork it!