| Filter and highlight code snippets by category: | |
|---|---|
| Filter: | |
| Highlight: | |
Write-Host 'PowerShell Version' $PsVersionTable.PSVersion
[System.Environment]::CommandLine # single string including powershell executable and script name
[System.Environment]::GetCommandLineArgs( ) # array of strings including powershell executable and script name
$Args # array of strings, script arguments only
some-command | Out-Null # slow
some-command > $null # fast and easier to understand for shell afficionados
[void] some-command # fastest, but works only if output is object, not if written to screen with Write-Host
$dummy = some-command( ) # alternative; your IDE may complain about unused variable $dummy
some-command -ErrorAction SilentlyContinue
some-command 2> $null # for shell afficionados
some-command -ErrorAction SilentlyContinue | Out-Null # slow
some-command > $null 2>&1 # fast and easier to understand for shell afficionados
[void] some-command -ErrorAction SilentlyContinue # fast, but won't work if output is written to screen with Write-Host
# Windows version (as in VER command)[Environment]::OSVersion
# or, using WMI:Get-CimInstance -Class Win32_OperatingSystem
# Windows edition (requires elevated privileges):Get-WindowsEdition –Online# friendly name (as in WinVer command):$winver = ( Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" )
"{0} {1}" -f $winver.ProductName, $winver.DisplayVersion
[environment]::GetEnvironmentVariables( )
"Current directory : {0}" -f $( Get-Location ).Path
"Current drive root : {0}" -f $( Get-Location ).Drive.Root
"Current drive free space : {0:F0} GB" -f $( ( Get-Location ).Drive.Free / 1GB )
# Inspired by "#PSTip Working with Special Folders" by Shay Levy# https://powershellmagazine.com/2013/10/30/pstip-working-with-special-folders/# option 1: display results in GridView$specialfolders = [ordered]@{ } # create a Dictionary object
[Enum]::GetNames( 'System.Environment+SpecialFolder' ) | Sort-Object | ForEach-Object {
$specialfolders.Add( $_, [Environment]::GetFolderPath( $_ ) ) # add each key/value pair to the Dictionary
}$specialfolders | Out-GridView -Title 'Special Folders' -PassThru # show results in GridView
# option 2: display results in the console itself:$columnwidth = 'Special Folder Name'.Length
[Enum]::GetNames( 'System.Environment+SpecialFolder' ) | ForEach-Object {
$columnwidth = [Math]::Max( $columnwidth, $_.Length )
}( "{0,-$columnwidth} {1}" -f 'Special Folder Name', 'Location' )
( "{0,-$columnwidth} {1}" -f '===================', '========' )
# [Enum]::GetNames( 'System.Environment+SpecialFolder' ) or [Enum]::GetNames( [System.Environment+SpecialFolder] )[Enum]::GetNames( 'System.Environment+SpecialFolder' ) | ForEach-Object {
( "{0,-$columnwidth} {1}" -f $_, [Environment]::GetFolderPath( $_ ) )
} | Sort-Object
And this is what the result of Out-GridView will look like:
# Source: "Shell folders: the best-kept Windows time saving secret" by Mike Williams# https://www.techradar.com/news/computing/pc/shell-folders-the-best-kept-windows-time-saving-secret-464668$registrypath = 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\FolderDescriptions'
$shellfolders = $( Get-ChildItem -Path $registrypath | Get-ItemProperty | Select-Object -Property Name,ParsingName -ErrorAction Ignore | Sort-Object { $_.Name } )
$shellfolders | Format-List
# or in GridView:$shellfolders | Out-GridView -Title 'Shell Folders' -PassThru
# or a fancy presentation in the console itself, the hard way:[Console]::BackgroundColor = [ConsoleColor]::White
[Console]::ForegroundColor = [ConsoleColor]::Black
Clear-Host# gather the information$registrypath = 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\FolderDescriptions'
$shellfolders = $( Get-ChildItem -Path $registrypath | Get-ItemProperty | Select-Object -Property Name,ParsingName -ErrorAction Ignore | Sort-Object { $_.Name } )
# calculate required column widths$consolewidth = [Console]::WindowWidth
$colwidthName = $( $shellfolders.Name | Measure-Object -Property Length -Maximum ).Maximum
$remaining = $consolewidth - $colwidthName -4
# write a header"{0,-$colwidthName} {1,-$remaining}" -f 'Name', 'ParsingName'
[Console]::BackgroundColor = [ConsoleColor]::Gray
# underline the header"{0,-$colwidthName} {1,-$remaining}" -f ( '=' * 'Name'.Length ), ( '=' * 'ParsingName'.Length )
[Console]::BackgroundColor = [ConsoleColor]::White
# present the gathered information$shellfolders | ForEach-Object {
"{0,-$colwidthName} {1,-$remaining}" -f $_.Name, $_.ParsingName
# alternate background color for easier readingif ( [Console]::BackgroundColor -eq [ConsoleColor]::White ) {
[Console]::BackgroundColor = [ConsoleColor]::Gray
} else {
[Console]::BackgroundColor = [ConsoleColor]::White
}}[Console]::BackgroundColor = [ConsoleColor]::White
""[Console]::ResetColor( )
And this is what the result of Out-GridView will look like:
And this is what the result of the "fancy" code will look like in the console:
$directory = $( [Environment]::GetFolderPath( 'MyDocuments' ) ) # or specify any other directory
$dirsize = $( Get-ChildItem -Path $directory -Recurse | Measure-Object -Property Length -Sum )
"Directory `"{0}`" contains {1} files with a total size of {2:F2} GB" -f $directory, $dirsize.Count, ( $dirsize.Sum / 1GB )
# Specify $file1 and $file2$identical = ( ( Get-FileHash -Algorithm MD5 -Path $file1 ).Hash -eq ( Get-FileHash -Algorithm MD5 -Path $file2 ).Hash )
$def = @"
public enum RecycleFlags : UInt32{ RecycleNoConfirmation = 0x00000001, RecycleNoProgressUI = 0x00000002, RecycleNoSound = 0x00000004}[DllImport( "Shell32.dll", CharSet = CharSet.Unicode )]
public static extern UInt32 SHEmptyRecycleBin( IntPtr hwnd, string pszRootPath, RecycleFlags dwFlags );"@
if ( -not ( [System.Management.Automation.PSTypeName]'NativeMethods.Shell32Dll' ).Type ) {
Add-Type -Namespace NativeMethods -Name Shell32Dll -MemberDefinition $def -ReferencedAssemblies System.Runtime.InteropServices
}$flags = [NativeMethods.Shell32Dll+RecycleFlags]::RecycleNoConfirmation
$flags += [NativeMethods.Shell32Dll+RecycleFlags]::RecycleNoProgressUI
$flags += [NativeMethods.Shell32Dll+RecycleFlags]::RecycleNoSound
[void][NativeMethods.Shell32Dll]::SHEmptyRecycleBin( [IntPtr]::Zero, 'D:', $flags ) # repeat this command for each drive
Add-Type -AssemblyName System.Windows.Forms
( [System.Windows.Forms.Screen]::AllScreens | where-Object { $_.Primary } ).WorkingArea.Width # current value for primary monitor
# or:[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width # current value for primary monitor
# or:[System.Windows.Forms.SystemInformation]::PrimaryMonitorMaximizedWindowSize.Width # maximum available width on primary monitor
# or:( Get-CimInstance -ClassName Win32_DesktopMonitor ).ScreenWidth # maximum value for primary monitor
# or:( Get-CimInstance -ClassName Win32_VideoController ).CurrentHorizontalResolution # current value for single video card and monitor
$wmiclass = "Win32_DesktopMonitor"
$wminamespace = "root/CIMV2"
$wmiquery = "MonitorManufacturer IS NOT NULL AND NOT MonitorType='Default Monitor'" # exclude disconnected monitors
$monitors = Get-CimInstance -ClassName $wmiclass -Namespace $wminamespace -Filter $wmiquery
$count = ( $monitors | Measure-Object ).Count
if ( $count -eq 0 ) {
Write-Host "`nNo" -ForegroundColor Red -NoNewline
Write-Host " monitor detected"
} elseif ( $count -eq 1 ) {
Write-Host "`n1" -ForegroundColor Green -NoNewline
Write-Host " monitor detected:"
} else {
Write-Host "`n$count" -ForegroundColor Green -NoNewline
Write-Host " monitors detected:"
}# List monitor manufacturers and typesforeach ( $monitor in $monitors ) {
Write-Host "`t" -NoNewline
Write-Host ( "{0} {1}" -f $monitor.MonitorManufacturer, $monitor.MonitorType ).Trim( )
}
Add-Type -AssemblyName System.Windows.Forms
$monitorcount = [System.Windows.Forms.SystemInformation]::MonitorCount
$monitorsequal = [System.Windows.Forms.SystemInformation]::MonitorsSameDisplayFormat
if ( $monitorcount -eq 1 ) {
Write-Host "single monitor"
} else {
Write-Host ( "{0} monitors " -f $monitorcount ) -NoNewline
if ( $monitorsequal ) {
Write-Host "of equal resolution"
} else {
Write-Host "with different resolutions"
}}
[console]::ForegroundColor = 'Yellow'
[console]::BackgroundColor = 'Blue'
Clear-Host$linelength = [console]::WindowWidth
"`n Line length (console width) = $linelength characters`n"Write-Host ( "{0,-$linelength}" -f ' A full length black and white line' ) -ForegroundColor Black -BackgroundColor White
Write-Host "`n A single " -NoNewline
Write-Host "m" -NoNewline -BackgroundColor Black -ForegroundColor Magenta
Write-Host "u" -NoNewline -BackgroundColor Black -ForegroundColor Red
Write-Host "l" -NoNewline -BackgroundColor Black -ForegroundColor DarkYellow
Write-Host "t" -NoNewline -BackgroundColor Black -ForegroundColor Yellow
Write-Host "i" -NoNewline -BackgroundColor Black -ForegroundColor Green
Write-Host "-" -NoNewline -BackgroundColor Black -ForegroundColor Blue
Write-Host "c" -NoNewline -BackgroundColor Black -ForegroundColor White
Write-Host "o" -NoNewline -BackgroundColor Black -ForegroundColor Magenta
Write-Host "l" -NoNewline -BackgroundColor Black -ForegroundColor Red
Write-Host "o" -NoNewline -BackgroundColor Black -ForegroundColor DarkYellow
Write-Host "r" -NoNewline -BackgroundColor Black -ForegroundColor Yellow
Write-Host "e" -NoNewline -BackgroundColor Black -ForegroundColor Green
Write-Host "d" -NoNewline -BackgroundColor Black -ForegroundColor Blue
Write-Host " word`n`n"
Write-Host ' List and show all console colors'
Write-Host ' --------------------------------'
[Enum]::GetNames( 'System.ConsoleColor' ) | ForEach-Object {
Write-Host ( " [{0,2}]`t{1,-26}" -f [int][ConsoleColor]$_, $_ ) -ForegroundColor $_ -BackgroundColor ( ( [int][ConsoleColor]$_ + 2 ) % 16 )
}
And this is what the result of the previous code will look like:
# More detailed information can be found at# https://ss64.com/ps/syntax-f-operator.htmlWrite-Host 'Dec Hex'
Write-Host '=== ==='
0..128 | ForEach-Object {
# {argument[,padding][:type and digits]} # {0} is first argument; # {0,4} align/pad first argument to at least 4 positions # {0,3:D2} align first argument at least 3 positions, use at least 2 decimal digits # {0,2:X2} align first argument at least 2 positions, use at least 2 upper case hexadecimal digitsWrite-Host ( '{0,3:D2} = 0x{0,2:X2}' -f ( $_ * 8 ) )
}
And this is what the result of the previous code will look like:
And this is what the result of the previous code will look like:
$now = $( Get-Date ) # or [DateTime]::Now
$calendarWeekRule = 2 # first 4-day week, see https://docs.microsoft.com/en-us/dotnet/api/system.globalization.calendarweekrule
$firstDayOfWeek = 1 # Monday, see https://docs.microsoft.com/en-us/dotnet/api/system.dayofweek
[System.Globalization.DateTimeFormatInfo]::CurrentInfo.Calendar.GetWeekOfYear( $now, $calendarWeekRule, $firstDayOfWeek )
$nextmonth = ( Get-Date -Day 1 ).AddMonths( 1 ).Date
$today = ( Get-Date ).Date
"{0} days left this month (including today)" -f ( $nextmonth - $today ).Days
$year = ( Get-Date ).Year
$leapyear = [DateTime]::IsLeapYear( $year )
# or by checking the number of days in a year, tip from Joe Caverly:$leapyear = ( ( [DateTime] "$year-12-31" ).DayOfYear -eq 366 )
# ditto, but without requiring variable $year:$leapyear = ( ( Get-Date -Month 12 -Day 31 ).DayOfYear -eq 366 )
# or by checking if February has 29 days:$leapyear = ( [DateTime]::DaysInMonth( $year, 2 ) -eq 29 )
# ditto, but without requiring variable $year:$leapyear = ( ( Get-Date -Month 3 -Day 1 ).AddDays( -1 ).Day -eq 29 )
# or, the hard way:[bool]$leapyear = ( [bool]!( $year % 4 ) -and [bool]( $year % 100 ) ) -or [bool]!( $year % 400 )
[System.Globalization.CultureInfo]::CurrentCulture.DateTimeFormat.DayNames # weekday names in current language
[System.Globalization.CultureInfo]::CurrentCulture.DateTimeFormat.MonthNames # month names in current language
[System.Globalization.CultureInfo]::GetCultureInfo( 'nl' ).DateTimeFormat.DayNames # weekday names in Dutch (NL)
[System.Globalization.CultureInfo]::GetCultureInfo( 'nl' ).DateTimeFormat.MonthNames # months names in Dutch (NL)
[System.Globalization.CultureInfo]::GetCultureInfo( 'de' ).DateTimeFormat.DayNames # weekday names in German (DE)
[System.Globalization.CultureInfo]::GetCultureInfo( 'de' ).DateTimeFormat.MonthNames # months names in German (DE)
[System.Globalization.CultureInfo]::GetCultureInfo( 'fr' ).DateTimeFormat.DayNames # weekday names in French (FR)
[System.Globalization.CultureInfo]::GetCultureInfo( 'fr' ).DateTimeFormat.MonthNames # months names in French (FR)
[System.Globalization.CultureInfo]::GetCultureInfo( 'pt' ).DateTimeFormat.DayNames[0] # 'domingo' = Sunday in Portuguese (PT)
[System.Globalization.CultureInfo]::GetCultureInfo( 'es' ).DateTimeFormat.MonthNames[2] # 'marzo' = March in Spanish (ES)
# List all cultures/languages:[System.Globalization.CultureInfo]::GetCultures( [System.Globalization.CultureTypes]::AllCultures )
$today = ( Get-Date )
$year = $today.Year
if ( ( $today.Month -eq 12 ) -and ( $today.Day -ge 25 ) ) {
$year += 1 # add 1 year if we are past Christmas this year
}$christmas = ( Get-Date "$year-12-25" )
$wait = ( New-TimeSpan -Start $today -End $christmas )
Write-Host ( "Please be patient for another {0} day(s)" -f $wait.Days )
# Easter is at first Sunday after the first full moon at or after the Spring equinox (21 March)# Calculation explained: https://www.timeanddate.com/calendar/determining-easter-date.htmlSet-Variable -Name ReferenceFullMoon -Option Constant -Value $( Get-Date -Date '2022-01-17 23:48' ) -ErrorAction Ignore
Set-Variable -Name MoonCycleDays -Option Constant -Value 29.53 -ErrorAction Ignore
if ( $args.Length -eq 1 ) {
$year = $args[0] # enclose year in quotes if less than 100, and always use 4 digits, e.g. '0033'
} else {
$year = $( Get-Date ).Year # or specify any other year on the command line
}# For Easter calculations, the Spring equinox is always assumed to be at 21 March$springequinox = $( Get-Date -Date "$year-03-21" ) # 21 March
# Calculate full moon cycles to first full moon after Spring equinox of specified year$fullcycles = [Math]::Ceiling( ( New-TimeSpan -Start $ReferenceFullMoon -End $springequinox ).Days / $MoonCycleDays )
# Date of first full moon after Spring equinox of specified year$fullmoonafterequinox = $ReferenceFullMoon.AddDays( $fullcycles * $MoonCycleDays )
# First Sunday following first full moon at or after Spring equinox of specified year$eastersunday = $fullmoonafterequinox.AddDays( 7 - [int]$fullmoonafterequinox.DayOfWeek ).Date
# Display the resultif ( ( New-TimeSpan -Start ( Get-Date ).Date -End $eastersunday ).Days -lt 0 ) {
"Easter {0} was at {1}" -f $year, $eastersunday.ToLongDateString( )
} else {
"Easter {0} will be at {1}" -f $year, $eastersunday.ToLongDateString( )
}
# Code to convert today's (Gregorian) date to Julian date by David Yaw: https://stackoverflow.com/a/5254812$juliandate = ( Get-Date ).Date.ToOADate( ) + 2415018.5
# or (see https://en.wikipedia.org/wiki/Julian_day#Variants for details):$juliandate = ( Get-Date ).Date.Ticks / 864000000000 + 1721425.5
# Convert Julian date back to Gregorian date:$gregoriandate = [DateTime]::FromOADate( $juliandate - 2415018.5 )
# or:$gregoriandate = $( Get-Date -Date '0001-01-01' ).AddTicks( ( $juliandate - 1721425.5 ) * 864000000000 )
# Demo: convert between Gregorian and Julian dates:$todaygregorian = $( Get-Date ).Date
"Gregorian date for today : {0}" -f $todaygregorian.ToString( 'yyyy-MM-dd' )
$juliandate = $todaygregorian.ToOADate( ) + 2415018.5 # or: $todaygregorian.Ticks / 864000000000 + 1721425.5
"Converted to Julian date : $juliandate"$gregoriandate = [DateTime]::FromOADate( $juliandate - 2415018.5 ) # or: $( Get-Date -Date 0001-01-01 ).AddTicks( ( $juliandate - 1721425.5 ) * 864000000000 )
"Converted back to Gregorian : {0}" -f $gregoriandate.ToString( 'yyyy-MM-dd' )
And this is what the result of the previous demo code will look like in a PowerShell console:
Gregorian date for today : 2026-09-01 Converted to Julian date : 2461284.5 Converted back to Gregorian : 2026-09-01
Add-Type -AssemblyName System.Net
$unescapedtext = '4 > 3'
$escapedtext = [System.Net.WebUtility]::HtmlEncode( $unescapedtext );
$escapedtext
$tempfile = New-TemporaryFile
some-command | Get-Unique
# Retrieve line 25 of file 'some_text_file.txt'( Get-Content 'some_text_file.txt' -TotalCount 25 )[-1]
# Alternative way to retrieve line 25 of file 'some_text_file.txt'( Get-Content 'some_text_file.txt' )[24]
# Retrieve first 15 lines of file 'some_text_file.txt'Get-Content 'some_text_file.txt' -TotalCount 15
# Get lines 20..25 of file 'some_text_file.txt'( Get-Content 'some_text_file.txt' -TotalCount 25 )[-5..-1]
# Retrieve last 5 lines of file 'some_text_file.txt'Get-Content 'some_text_file.txt' -Tail 5
# Alternative way to retrieve last 5 lines of file 'some_text_file.txt'( Get-Content 'some_text_file.txt' )[-5..-1]
# . . . . . . . . . files to archive . . . . . . . . . ZIP file . . . . . best compression . . add to existing ZIP fileCompress-Archive -Path 'd:\folder' -DestinationPath 'd:\zipfile.zip' -CompressionLevel Optimal -Update
# Extract ZIP file into a subfolder with the ZIP file's name; use -DestiantionPath to specify an alternative destinationExpand-Archive -Path 'd:\zipfile.zip' -Force
Set-Clipboard -Value 'new clipboard text' # overwrite
# or:Set-Clipboard -Value 'more clipboard text' -Append # append
Get-Clipboard# or the hard way:Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Clipboard]::GetText( [System.Windows.Forms.TextDataFormat]::UnicodeText )
Add-Type -AssemblyName System.Windows.Forms
$filelist = @( Get-ChildItem -Path 'd:\folder\filenames*.*' ) # array of file names
[System.Windows.Forms.Clipboard]::SetFileDropList( $filelist )
# This script uses SendKeys to paste files from the clipboard into an Explorer window.# This is ABSOLUTELY NOT a recommended procedure, as it is extremely error-prone.$def = @"
[DllImport( "user32.dll" )]
[return: MarshalAs( UnmanagedType.Bool )]public static extern bool SetForegroundWindow( IntPtr hWnd );"@ # C# code to set foreground window
Add-Type -Namespace NativeMethods -Name User32Dll -MemberDefinition $def -ReferencedAssemblies System.Runtime.InteropServices
Add-Type -AssemblyName System.Windows.Forms
Start-Process -FilePath 'explorer.exe' -ArgumentList "$Env:Temp" # open TEMP directory in Explorer
Start-Sleep -Milliseconds 500 # wait half a second
[IntPtr]$handle = $( Get-Process -Name 'explorer' | Where-Object { $_.MainWindowTitle -eq "$Env:Temp" } )[0].MainWindowHandle
[NativeMethods.User32Dll]::SetForegroundWindow( $handle ) # make Explorer the foreground window
Start-Sleep -Milliseconds 500 # wait half a second
[System.Windows.Forms.SendKeys]::SendWait( "+{INSERT}" ) # send Shift-Ins keystroke to paste files into TEMP directory
# Multiple characters, case sensitive string, terminated with Enter# =================================================================$input = Read-Host -Prompt "Enter your name"
# or:Write-Host "Enter your name " -NoNewLine
$input = $Host.UI.ReadLine( )
# Single charater (note that ReadKey accepts ALL keys including function keys F2..F12, Enter and Esc)# ===================================================================================================# Case sensitive, hide input $true$key = [System.Console]::ReadKey( $true ).KeyChar
# Upper case character or special key's caption (e.g. 'Enter'), hide input $true$key = [System.Console]::ReadKey( $true ).Key
# Limited range of characters accepted (case sensitive if letters)$input = ''
$range = '[1-5]' # regular expression
do {
Write-Host 'Choose a number from 1 to 5: ' -NoNewline
$input = [System.Console]::ReadKey( $false ).KeyChar
# Clear the line to either prompt again or show the accepted resultWrite-Host ( "`b `b" * $Host.UI.RawUI.CursorPosition.X ) -NoNewline
} until ( $input -match $range )
Write-Host "You chose $input"
# Limited range of strings, type the string of choice (not case sensitive) or press Enter for the default# =======================================================================================================$title = 'Printer Selection'
$message = 'Pick one of the following printers:'
$options = ( Get-Printer ).Name
$defaultprinter = ( Get-CimInstance -ClassName Win32_Printer -Filter "Default=TRUE" ).Name
$defaultchoice = $options.IndexOf( $defaultprinter )
$selected = $host.UI.PromptForChoice( $title , $message, $options, $defaultchoice )
$options[$selected]
And this is what the result of the previous PromptForChoice code will look like in a PowerShell console:
And this is what the result of the previous PromptForChoice code will look like in PowerShell ISE:
Check out Dirk's A nicer PromptForChoice for the PowerShell Console Host article for a more consistent looking alternative to PromptForChoice.
# More details on https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator$currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent( ) )
if ( -not ( $currentPrincipal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ) ) )
{Write-Error "This script must be executed in admin mode." -ErrorAction Stop
}# or:if ( -not ( [Security.Principal.WindowsIdentity]::GetCurrent( ).Groups -contains 'S-1-5-32-544' ) ) # S-1-5-32-544 is the local Administrators group
{Write-Error "This script must be executed in admin mode." -ErrorAction Stop
}# or:#Requires -RunAsAdministrator# The "#Requires" statement above will make the script abort with error message if not run as administrator# See https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires for details
if ( [Security.Principal.WindowsIdentity]::GetCurrent( ).Groups -contains 'S-1-5-32-544' )
{Write-Error "This script must NOT be executed by members of the Administrators group." -ErrorAction Stop
}
$progpath = ( Get-Command ( [System.Environment]::GetCommandLineArgs( ) )[0] ).Definition
if ( $PSVersionTable.PSVersion.Major -gt 5 ) {
# PowerShell 7 console states pwsh.dll as its executable, we'll use pwsh.exe instead$progpath = $progpath -replace 'pwsh\.dll$', 'pwsh.exe'
}if ( $args.Length -eq 0 ) {
Start-Process -FilePath $progpath -Verb RunAs
} else {
Start-Process -ArgumentList $args -FilePath $progpath -Verb RunAs
}
Write-Host $sometext
Write-Host ( "-" * $sometext.Length ) # single underline
Write-Host ( "=" * $sometext.Length ) # double underline
( Get-Command $file ).Definition # $file is the file to be found, e.g. "powershell.exe"
[environment]::GetLogicalDrives( )
# or:( Get-PSDrive -Name ? ).Name
# or:( Get-Location ).Provider.Drives.Name
# or:( Get-PSDrive -PSProvider FileSystem ).Name
# or the hard way:( Get-PSDrive | Where-Object { $_.Name -match '^[A-Z]$' } ).Name
# or local drives only (excluding network drives):( Get-Volume ).DriveLetter
$drive = ( Get-Volume | Where-Object { $_.DriveType -eq 'Fixed' } | Sort-Object { $_.SizeRemaining } | Select-Object -Last 1 )
Write-Host ( "Drive with most free space {0}:" -f $drive.DriveLetter )
Write-Host ( "Total size of drive {0}: {1:F0} GB" -f $drive.DriveLetter, ( $drive.Size / 1GB ) )
Write-Host ( "Free space on drive {0}: {1:F0} GB" -f $drive.DriveLetter, ( $drive.SizeRemaining / 1GB ) )
Write-Host ( "Percentage of free space {0:F0}%" -f ( 100 * $drive.SizeRemaining / $drive.Size ) )
# Standard beep:[Console]::Beep( )
# Custom beep:[Console]::Beep( $frequency, $milliseconds ) # frequency 37..32767 Hz
# Melody demo:@( 392, 330, 349, 247, 32767, 330, 349, 392, 330 ) | ForEach-Object { [Console]::Beep( $_, 500 ) } # use 32767 for pauses
Start-Sleep -Seconds 10 # wait 10 seconds
Start-Sleep 10 # wait 10 seconds
Start-Sleep -Seconds 2.7 # wait 3 seconds, rounded to integer
Start-Sleep -MilliSeconds 500 # wait half a second
$columns = 8 # Number of columns, use any power of 2 to make the table fit on screen
0..( $columns - 1 ) | ForEach-Object {
if ( $_ -eq 0 ) {
Write-Host "Decimal`tASCII" -NoNewline
} else {
Write-Host "`t`tDecimal`tASCII" -NoNewline
}}Write-Host0..( $columns - 1 ) | ForEach-Object {
if ( $_ -eq 0 ) {
Write-Host "=======`t=====" -NoNewline
} else {
Write-Host "`t`t=======`t=====" -NoNewline
}}Write-Host0..( ( 256 / $columns ) - 1 ) | ForEach-Object {
$startvalue = $columns * $_
0..( $columns - 1 ) | ForEach-Object {
$charvalue = $startvalue + $_
if ( $_ -eq 0 ) {
Write-Host ( "{0,7}`t{1,5}" -f $charvalue,[char]$charvalue ) -NoNewline
} else {
Write-Host ( "`t`t{0,7}`t{1,5}" -f $charvalue,[char]$charvalue ) -NoNewline
} } Write-Host}
And this is what the result of the previous code will look like, depending on your codepage:
$computerinfo = ( Get-ComputerInfo )
if ( $computerinfo.CsPartOfDomain ) {
Write-Host( "Domain: {0}" -f $computerinfo.CsDomain )
} else {
Write-Host( "Workgroup: {0}" -f $computerinfo.CsWorkgroup )
}
# Source: https://morgantechspace.com/2015/06/powershell-find-machine-name-from-ip-address.html# Replace 127.0.0.1 with any other IP address[System.Net.Dns]::GetHostByAddress('127.0.0.1').HostName
# Source: https://morgantechspace.com/2015/06/powershell-find-machine-name-from-ip-address.html# Replace $Env:ComputerName with any other computer name[System.Net.Dns]::GetHostByName( $Env:ComputerName ).AddressList[0].IPAddressToString
# or:[System.Net.Dns]::Resolve( $env:ComputerName ).AddressList[0].IPAddressToString
# wanip.php contains only this code: <?php print $_SERVER['REMOTE_ADDR']; ?>Write-Host 'My IP address is:' ( Invoke-WebRequest -Uri https://www.robvanderwoude.com/wanip.php ).Content
And this is what you will get:
My IP address is: 152.55.176.99
Add-Type -AssemblyName System.Windows.Forms
$capslock = [System.Windows.Forms.Control]::IsKeyLocked( [System.Windows.Forms.Keys]::CapsLock )
$numlock = [System.Windows.Forms.Control]::IsKeyLocked( [System.Windows.Forms.Keys]::NumLock )
$scrolllock = [System.Windows.Forms.Control]::IsKeyLocked( [System.Windows.Forms.Keys]::Scroll )
$Insert = [System.Windows.Forms.Control]::IsKeyLocked( [System.Windows.Forms.Keys]::Insert )
# or shorter, for CapsLock and NumLock only:$capslock = [console]::CapsLock
$numlock = [console]::NumberLock
# Note that Get-ComputerInfo may take a while getting "all" available data[int]( ( Get-ComputerInfo ).CsTotalPhysicalMemory / 1GB )
# or, faster:[int]( ( Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum ).Sum / 1GB )
# or:$shell = New-Object -ComObject Shell.Application
[int] ( $shell.GetSystemInformation( 'PhysicalMemoryInstalled' ) / 1GB )
$windowtitle = $Host.UI.RawUI.WindowTitle
# or:$windowtitle = [console]::Title
$Host.UI.RawUI.WindowTitle = 'Test new window title'
# or:[console]::Title = 'Test new window title'
# By window title (won't work on minimized windows):$wshShell = New-Object -ComObject WScript.Shell
Start-Process -FilePath 'cmd.exe' -ArgumentList '/k title Test WScript.Shell.AppActivate' # open a test window
pause # just to make sure the freshly opened window loses focus# AppActivate sets focus to a window with matching title# WARNING: unlike in VBScript, in PowerShell WScript.Shell.AppActivate will always return false[void]$wshShell.AppActivate( 'Test WScript.Shell.AppActivate' )
# or:Add-Type -AssemblyName Microsoft.VisualBasic
Start-Process -FilePath 'cmd.exe' -ArgumentList '/k title Test Microsoft.VisualBasic.AppActivate' # open a test window
pause # just to make sure the freshly opened window loses focus[Microsoft.VisualBasic.Interaction]::AppActivate( 'Test Microsoft.VisualBasic.AppActivate' )
# or by process name:$def = @"
[DllImport( "user32.dll" )]
[return: MarshalAs( UnmanagedType.Bool )]public static extern bool SetForegroundWindow( IntPtr hWnd );"@
Add-Type -Namespace NativeMethods -Name User32Dll -MemberDefinition $def -ReferencedAssemblies System.Runtime.InteropServices
[NativeMethods.User32Dll]::SetForegroundWindow( ( Get-Process -Name 'cmd' | Select-Object -First 1 ).MainWindowHandle )
# Hide console window by Anthony on StackOverflow.com# http://stackoverflow.com/a/15079092$def = @'
public static void ShowConsoleWindow( int state ){ var handle = GetConsoleWindow( ); ShowWindow( handle, state );}[DllImport( "kernel32.dll" )]static extern IntPtr GetConsoleWindow( );[DllImport( "user32.dll" )]static extern bool ShowWindow( IntPtr hWnd, int nCmdShow );'@
$hideconsole = Add-Type -MemberDefinition $def -Name Hide -Namespace HideConsole -ReferencedAssemblies System.Runtime.InteropServices -PassThru
$hideconsole::ShowConsoleWindow( 0 ) # 0 to hide the console
Start-Sleep -Seconds 3 # Wait 3 seconds before restoring the window again
$hideconsole::ShowConsoleWindow( 5 ) # 5 to restore the console
Check out my Show-Console cmdlet.
Start-Process -FilePath yourprog.exe -WindowStyle Hidden
# Source: https://superuser.com/a/1250038$wshShell = New-Object -ComObject WScript.Shell
Start-Process -FilePath 'cmd.exe' -ArgumentList '/k title Test WScript.Shell.SendKeys'
pause # just to make sure the freshly opened window loses focus# AppActivate sets focus to a window with matching title, so it can receive keystrokes sent by SendKeys.# WARNING: unlike in VBScript, in PowerShell AppActivate will always return false.[void]$wshShell.AppActivate( 'Test WScript.Shell.SendKeys' )
Start-Sleep -Seconds 1
$wshShell.SendKeys( 'exit' )
Start-Sleep -Seconds 1
$wshShell.SendKeys( '{ENTER}' )
# or:Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
Start-Process -FilePath 'cmd.exe' -ArgumentList '/k title Test Microsoft.VisualBasic.SendKeys'
pause # just to make sure the freshly opened window loses focus[Microsoft.VisualBasic.Interaction]::AppActivate( 'Test Microsoft.VisualBasic.SendKeys' )
Start-Sleep -Seconds 1
[System.Windows.Forms.SendKeys]::SendWait( 'exit' )
Start-Sleep -Seconds 1
[System.Windows.Forms.SendKeys]::SendWait( '{ENTER}' )
Check out this list of special characters for SendKeys
$process = 'rundll32.exe'
Get-CimInstance -ClassName Win32_Process -Filter "Name='$process'" | ForEach-Object { $_.CommandLine }
$months = "9","12","3","7","5","6","4","8","1","10","11","2"
Write-Host "`nSort as strings:"
$months | Sort-Object # returns 1,10,11,12,2,3,4,5,6,7,8,9
Write-Host"`nSort as numbers:"
$months | Sort-Object { [int]$_ } # returns 1,2,3,4,5,6,7,8,9,10,11,12
if ( $PSVersionTable.PSVersion.Major -gt 4 ) {
# PowerShell 3 and later$instances = Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root/Microsoft/Windows/Storage
} else {
# PowerShell 5 and older$instances = Get-WMIObject -Query "SELECT * FROM MSFT_PhysicalDisk" -Namespace "root/Microsoft/Windows/Storage"
}foreach ( $item in $instances ) {
Write-Host ( "Model : {0}" -f $item.Model )
Write-Host ( "Size : {0} GB" -f [int]( $item.Size / 1GB ) )
# or: Write-Host ( "Size : {0:F0} GB" -f ( $item.Size / 1GB ) )Write-Host ( "BusType : {0}" -f $item.BusType )
Write-Host}
$hash = Get-FileHash -Path d:\folder\file.ext -Algorithm SHA256 #MD5, SHA1, SHA256, SHA384 or SHA512
Get-CimInstance -Namespace root\SecurityCenter2 -Class AntiVirusProduct | Select-Object -Property displayname,timestamp
$originaltext = "Original unencoded text"
"Original text : {0}" -f $originaltext
$encodedtext = [System.Convert]::ToBase64String( [System.Text.Encoding]::Unicode.GetBytes( $originaltext ) )
"Encoded text : {0}" -f $encodedtext
$decodedtext = [System.Text.Encoding]::Unicode.GetString( [System.Convert]::FromBase64String( $encodedtext ) )
"Decoded text : {0}" -f $decodedtext
Add-Type -AssemblyName System.Drawing
$inputfile = 'd:\folder\image.jpg'
$outputfile = $inputfile -replace '\.jpe?g$', '.png'
# Valid ImageFormat values can be found with the command# [System.Drawing.Imaging.ImageFormat].DeclaredProperties.Name# or at https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imageformat$outputformat = [System.Drawing.Imaging.ImageFormat]::Png
$bitmap = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $inputfile
$bitmap.Save( $outputfile, $outputformat )
Add-Type -AssemblyName System.Drawing
$inputfile = 'd:\folder\testimage.tif'
$outputfile = $inputfile -replace '\.[^\.\\]+$', '.resized50percent.jpg'
$scalepercentage = 50
# Valid ImageFormat values can be found with the command# [System.Drawing.Imaging.ImageFormat].DeclaredProperties.Name# or at https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imageformat$outputformat = [System.Drawing.Imaging.ImageFormat]::Jpeg
$bitmap = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $inputfile
"Bitmap size BEFORE {0}x{1}" -f $bitmap.Width, $bitmap.Height
$newwidth = [int]( $bitmap.Width * $scalepercentage / 100 )
$newheight = [int]( $bitmap.Height * $scalepercentage / 100 )
$resizedimage = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $newwidth,$newheight
[System.Drawing.Graphics]$graphic = [System.Drawing.Graphics]::FromImage( $resizedimage )
$graphic.DrawImage( $bitmap, 0, 0, $newwidth, $newheight )
$graphic.Dispose( )
$resizedimage.Save( $outputfile, $outputformat )
"Bitmap size AFTER {0}x{1}" -f $resizedimage.Width, $resizedimage.Height
Add-Type -AssemblyName System.Drawing
$inputfile = 'd:\folder\testimage.tif'
$outputfile = $inputfile -replace '\.[^\.\\]+$', '.rotated90degrees.jpg'
# Valid ImageFormat values can be found with the command# [System.Drawing.Imaging.ImageFormat].DeclaredProperties.Name# or at https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imageformat$outputformat = [System.Drawing.Imaging.ImageFormat]::Jpeg
$bitmap = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $inputfile
# valid RotateFlipType values can be found with the command# [enum]::GetNames( [System.Drawing.RotateFlipType] )# or at https://docs.microsoft.com/en-us/dotnet/api/system.drawing.rotatefliptype$bitmap.RotateFlip( [System.Drawing.RotateFlipType]::Rotate90FlipNone )
$bitmap.Save( $outputfile, $outputformat ) # Note: output file size may be considerably larger than expected
# This script requires EAN-13 font made available by Fontpalace.com:# http://www.fontpalace.com/font-download/EAN-13/# You can modify this script to generate any text in images, in which case you probably won't need the EAN-13 fontAdd-Type -AssemblyName System.Drawing
# specify EAN-13 font$font = New-Object -TypeName System.Drawing.Font( 'EAN-13', 48 )
# test if EAN-13 font is installedif ( $font.Name -ne 'EAN-13' ) {
$errormessage = "`n `n`tThis script requires the `"EAN-13`" font made available by Fontpalace.com:"
$errormessage += "`n`thttp://www.fontpalace.com/font-download/EAN-13/`n `n"
Write-Error $errormessage -ErrorAction 'Stop'
}$text = $( Get-Date -Format 'yyyyMMddHHmmss' ).Substring( 0, 13 ) # or any other 13-digit number
# You can list all available text colors with the command: [System.Drawing.Brushes].DeclaredProperties.Name$textcolor = [System.Drawing.Brushes]::Black
# You can list all available background colors with the command: [enum]::GetNames( [System.Drawing.KnownColor] )$backgroundcolor = [System.Drawing.Color]::White
$outputfile = ( "D:\barcode{0}.jpg" -f $text )
# You can list available output formats with the command: [System.Drawing.Imaging.ImageFormat].DeclaredFields.Name$outputformat = [System.Drawing.Imaging.ImageFormat]::Jpeg
$bitmap = New-Object -TypeName System.Drawing.Bitmap -ArgumentList 1,1
$graphic = [System.Drawing.Graphics]::FromImage( $bitmap );
$stringsize = $graphic.MeasureString( $text, $font ) # calculate required image size
$bitmap = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $bitmap,$stringsize.Width,$stringsize.Height
$graphic = [System.Drawing.Graphics]::FromImage( $bitmap )
$graphic.Clear( $backgroundcolor )
$graphic.DrawString( $text, $font, $textcolor, 0, 0 )
$font.Dispose( )
$graphic.Flush( )
$graphic.Dispose( )
$bitmap.Save( $outputfile, $outputformat )
# Open the image we just createdStart-Process -FilePath $outputfile
And this is what the result of the previous code will look like:
# Based on C# code by Ali Hamdar (http://alihamdar.com/)# http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/79efecc4-fa6d-4078-afe4-bb1379bb968b$outputfile = 'D:\test.jpg'
$imagetype = 'jpeg' # bmp, emf, gif, jpeg, png, tiff, wmf
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Default values for full screen$width = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width
$height = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height
$top = 0
$left = 0
[System.Drawing.Bitmap]$printscreen = New-Object System.Drawing.Bitmap( $width, $height )
[System.Drawing.Graphics]$graphics = [System.Drawing.Graphics]::FromImage( $printscreen )
$graphics.CopyFromScreen( $top, $left, 0, 0, $printscreen.Size )
$printscreen.Save( $outputfile, $imagetype ) # will overwrite existing file without prompt for confirmation
Start-Process -FilePath $outputfile # open the screenshot we just saved
# Windows 10:# Source: https://gist.github.com/winhelponline/4dc635770d5b123f6c1a719326037880$TIC = ( Get-ItemProperty 'HKCU:\Control Panel\Desktop' TranscodedImageCache -ErrorAction Stop ).TranscodedImageCache
[System.Text.Encoding]::Unicode.GetString( $TIC ) -replace '(.+)([A-Z]:[0-9a-zA-Z\\])+','$2'
# Windows 7 with PowerShell 5:# Source: https://quickbytesstuff.blogspot.com/2015/11/powershell-check-wallpaper-location.html( Get-WmiObject -Class 'Win32_Desktop' ).Wallpaper
$hasmouse = [System.Windows.Forms.SystemInformation]::MousePresent
if ( $hasmouse )
{Write-Host "At least " -NoNewline
Write-Host "1" -ForegroundColor Green -NoNewline
Write-Host " mouse available"
}else{Write-Host "No" -ForegroundColor Red -NoNewline
Write-Host " mouse available"
}
Add-Type -AssemblyName System.Windows.Forms
Write-Host 'Primary mouse button: ' -NoNewline
if ( [System.Windows.Forms.SystemInformation]::MouseButtonsSwapped ) {
Write-Host 'right'
} else {
Write-Host 'left'
}# Open mouse button settings (Windows 8..11)Start-Process "ms-settings:mousetouchpad"
# Using WMI, relies on a description which is not the most reliable way:"Touch enabled: {0}" -f ( ( Get-CimInstance -ClassName Win32_PnPEntity | Where-Object { $_.Description -match 'touch' } ).Count -gt 0 )
# or using P/Invoke:$code = @'
[DllImport( "user32.dll" )]public static extern int GetSystemMetrics( int smIndex );'@
Add-Type -Namespace NativeMethods -Name User32Dll -MemberDefinition $code -ReferencedAssemblies System.Runtime.InteropServices
"Touch enabled: {0}" -f ( [NativeMethods.User32Dll]::GetSystemMetrics( 95 ) -gt 0 )
[boolean] ( @( Get-CimInstance -ClassName Win32_PnPEntity -Filter 'PNPClass="Bluetooth"' ).Count -gt 0 )
# Use WMI:Get-CimInstance -ClassName Win32_Printer -Filter "Default=TRUE"
# or read its name from the registry:( Get-ItemProperty -Path 'HKCU:Software\Microsoft\Windows NT\CurrentVersion\Windows' ).Device.Split( ',' )[0]
# or use System.Drawing.Printing:Add-Type -AssemblyName System.Drawing
$printer = New-Object -TypeName System.Drawing.Printing.PrinterSettings
Get-Printer | ForEach-Object {
$printer.PrinterName = $_.Name
if ( $printer.IsDefaultPrinter ) {
"Default printer: {0}" -f $_.Name
}}# or shorter:Add-Type -AssemblyName System.Drawing
"Default printer: {0}" -f ( New-Object -TypeName System.Drawing.Printing.PrinterSettings | Where-Object { $_.IsDefaultPrinter } ).PrinterName
Add-Type -AssemblyName System.Drawing
$printersettings = New-Object -TypeName System.Drawing.Printing.PrinterSettings
Get-Printer | ForEach-Object {
$printersettings.PrinterName = $_.Name
$printersettings.CanDuplex}# or, using WMI (may fail on non-English systems):Get-CimInstance -ClassName Win32_Printer `
| Select-Object -Property CapabilityDescriptions,Name `
| Where-Object { $_.CapabilityDescriptions -match 'Duplex' }
# or, if duplex printing requires a duplex unit:Get-Printer | ForEach-Object {
$printername = $_.Name
Get-PrinterProperty -PrinterName $printername `
| Where-Object { $_.PropertyName -eq 'Config:DuplexUnit' -and $_.Value -eq 'Installed' } `
| ForEach-Object { "Printer `"$printername`" has a duplex unit installed" }
}
$regKey = "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\"
$LegacyDefaultPrinterMode = ( Get-ItemProperty $regKey ).LegacyDefaultPrinterMode
if ( $LegacyDefaultPrinterMode -eq 1 ) {
Write-Host 'You manage your default printer yourself'
} else {
Write-Host 'You let Windows manage your default printer for you'
}
$regKey = "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\"
Set-ItemProperty -Path $regKey -Name 'LegacyDefaultPrinterMode' -Value 1
# Plain text files:Get-Content -Path 'd:\folder\mytextfile.txt' | Out-Printer # print to default printer
Get-Content -Path 'd:\folder\mytextfile.txt' | Out-Printer -Name 'Microsoft Print to PDF' # print to alternative printer
Start-Process -FilePath 'd:\folder\mytextfile.txt' -Verb Print # print to default printer
# Other file types with associated print command:Start-Process -FilePath 'd:\folder\mypdffile.pdf' -Verb Print # print to default printer
# StartComponentCleanup job cleans up WinSxS directory; admin privileges required$task = Start-ScheduledTask -TaskPath '\Microsoft\Windows\Servicing\' -TaskName 'StartComponentCleanup' -AsJob
Start-Sleep -Seconds 1 # wait 1 second
$task.Progress # then check its progress
# assuming that floppy drives will only have driveletter A: and B: which may in rare cases not be true:Get-Volume | Where-Object { $_.DriveType -eq 'Removable' -and $_.DriveLetter -lt 'C' }
# WMI is more reliable and returns more information:Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 2 And MediaType > 1 And MediaType != 11 And MediaType !=12"
# slightly simpler code, but MUCH slower if there are network drives:Get-CimInstance -ClassName Win32_LogicalDisk -Filter "MediaType > 1 And MediaType != 11 And MediaType !=12"
$wia = New-Object -ComObject WIA.DeviceManager
( $wia.DeviceInfos.Count -gt 0 )
$wia = New-Object -ComObject WIA.DeviceManager
$wia.DeviceInfos | ForEach-Object {
$scanner = $_.Connect( )
$scanner.Properties | Select-Object -Property Name,Value
}
# Based on code by Vadim Kantorov: https://stackoverflow.com/a/28422467# WIA FormatID constants: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/wiaaut/-wiaaut-consts-formatidSet-Variable wiaFormatBMP -Option Constant -Value '{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}'
Set-Variable wiaFormatPNG -Option Constant -Value '{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}'
Set-Variable wiaFormatGIF -Option Constant -Value '{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}'
Set-Variable wiaFormatJPEG -Option Constant -Value '{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}'
Set-Variable wiaFormatTIFF -Option Constant -Value '{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}'
$deviceManager = new-object -COMObject WIA.DeviceManager
$device = $deviceManager.DeviceInfos.Item( 1 ).Connect( )
$device.Items | ForEach-Object {
$image = $_.Transfer( $wiaFormatPNG )
}# Just in case the scanner doesn't support saving in PNG format:if ( $image.FormatID -ne $wiaFormatPNG ) {
$imageProcess = New-Object -COMObject WIA.ImageProcess
$imageProcess.Filters.Add( $imageProcess.FilterInfos.Item( "Convert" ).FilterID )
$imageProcess.Filters.Item( 1 ).Properties.Item( "FormatID" ).Value = $wiaFormatPNG
$image = $imageProcess.Apply( $image )
}$image.SaveFile( "D:\test.png" )
# The first script block is the "cleanest" way, as it will NOT throw an error if no CD is found:# Get all optical drives . . . . . . . . . . . . . . . . . . . with an audio CD loaded . . . . . just the first oneGet-CimInstance -ClassName Win32_CDROMDrive | Where-Object { $_.VolumeName -EQ 'Audio CD' } | Select-Object -First 1 | ForEach-Object {
# open the audio CD with the associated playerStart-Process -FilePath $_.Drive -Verb Play
}# or without WMI (note that assuming index [0] instead of using Select-Object -First 1 will throw an error if no CD is found):# . . . . . All drives . . . . . . . . . . . . . select optical drives with an audio CD loaded . . . . . drive letter of the first matching drive$driveletter = ( Get-Volume | Where-Object { $_.DriveType -eq 'CD-ROM' -and $_.FileSystemLabel -eq 'Audio CD' } ).DriveLetter[0]
Start-Process -FilePath "$driveletter`:" -Verb Play
# or the most simple one, though not 100% tamper-proof, and like the previous script block will throw an error if no CD is found:$driveletter = ( Get-Volume -FileSystemLabel 'Audio CD' ).DriveLetter[0]
Start-Process -FilePath "$driveletter`:" -Verb Play
# This script requires Windows Media Player$player = New-Object -ComObject WMPlayer.OCX
0..( $player.cdromCollection.count - 1 ) | ForEach-Object { $player.cdromCollection.Item($_).Eject( ) }
$acrobatreaderinstalled = ( [System.Type]::GetTypeFromProgID( "AcroPDF.PDF" ) -ne $null )
# for all users, requires elevated privileges:$riainstalled = $( ( Get-AppxPackage -AllUsers ).Name -match "RawImageExtension" ) -ne $null
# for current user, no elevated privileges required:$riainstalled = $( ( Get-AppxPackage ).Name -match "RawImageExtension" ) -ne $null
$accessinstalled = ( [System.Type]::GetTypeFromProgID( "Access.Application" ) -ne $null )
$excelinstalled = ( [System.Type]::GetTypeFromProgID( "Excel.Application" ) -ne $null )
$msgraphinstalled = ( [System.Type]::GetTypeFromProgID( "MSGraph.Application" ) -ne $null )
$outlookinstalled = ( [System.Type]::GetTypeFromProgID( "Outlook.Application" ) -ne $null )
$powerpointinstalled = ( [System.Type]::GetTypeFromProgID( "PowerPoint.Application" ) -ne $null )
$wordinstalled = ( [System.Type]::GetTypeFromProgID( "Word.Application" ) -ne $null )
# works for OpenOffice.org, Apache OpenOffice and LibreOffice$openofficeinstalled = ( [System.Type]::GetTypeFromProgID( "com.sun.star.ServiceManager" ) -ne $null )
$wordperfectinstalled = ( [System.Type]::GetTypeFromProgID( "WordPerfect.PerfectScript" ) -ne $null )
# Based on article by François-Xavier Cat# https://lazywinadmin.com/2014/03/powershell-read-excel-file-using-com.html$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open( $excelfile ) # $excelfile must be specified
$workbook.Sheets | ForEach-Object {
if ( ![string]::IsNullOrEmpty( $_.Range( "A1" ).Text ) ) { # skip sheets with cell A1 empty
Write-Host $_.Name # sheet name
Write-Host ( "=" * $_.Name.Length ) # underline sheet name
Write-Hostfor ( $row = 1; $row -le $_.UsedRange.Rows.Count; $row++ ) { # iterate through all rows in used range
for ( $column = 1; $column -le $_.UsedRange.Columns.Count ; $column++ ) { # iterate through all columns in used range
Write-Host ( "({0}{1})`t{2}" -f ( [char] ( $column + 64 ) ), $row, $_.Columns.Item( $column ).Rows.Item( $row ).Text ) # e.g. '(A4) content_of_cell_A4'
}Write-Host # blank line between rows
} }}[void] $workbook.Close( ) # close Excel file
[void] $objExcel.Quit( ) # should close Excel application but may not always do so
# Requires Microsoft Access Database Engine 2016 Redistributable:# https://www.microsoft.com/en-us/download/details.aspx?id=54920Set-Variable adOpenStatic -Option Constant -Value 3
$excelfile = 'd:\folder\excelfile.xlsx'
$sheet = 'Sheet1'
$range = 'A1:D14'
$connectstring = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=$excelfile;Extended Properties=`"Excel 12.0 Xml;IMEX=1;`""
$excel = New-Object -ComObject ADODB.Connection
$excel.Open( $connectstring )
$recordset = New-Object -ComObject ADODB.RecordSet
$recordset.Open( ( "Select * from [{0}`${1}]" -f $sheet, $range ), $excel, $adOpenStatic )
$recordset.MoveFirst( )
# Determine the required width of the first column$column1width = 1
0..3 | ForEach-Object { $column1width = [System.Math]::Max( $column1width, $recordset.Fields.Item( $_ ).Name.length ) }
$recordset.MoveFirst( )
while ( !$recordset.EOF ) {
0..3 | ForEach-Object { Write-Host ( "{0,-$column1width} {1}" -f $recordset.Fields.Item( $_ ).Name, $recordset.Fields.Item( $_ ).Value ) }
Write-Host$recordset.MoveNext( )
}$recordset.Close( )
$excel.Close( )
$objWord = New-Object -ComObject Word.Application
[void] $objWord.Documents.Open( "$wordfile", $false, $true ) # $wordfile must be specified
$objWord.ActiveDocument.PrintOut( )
$objWord.ActiveDocument.Close( $false )
$objWord.Quit( )
# or:Start-Process -Filepath "$wordfile" -Verb Print # $wordfile must be specified
$objWord = New-Object -ComObject Word.Application
$defaultprinter = $objWord.ActivePrinter
$objWord.ActivePrinter = "$otherprinter" # $otherprinter must be specified
[void] $objWord.Documents.Open( "$wordfile", $false, $true ) # $wordfile must be specified
$objWord.ActiveDocument.PrintOut( )
$objWord.ActiveDocument.Close( $false )
$objWord.ActivePrinter = $defaultprinter
$objWord.Quit( )
# Output format constants: https://docs.microsoft.com/office/vba/api/word.wdsaveformatSet-Variable -Name 'wdFormatPDF' -Option Constant -Value 17 -ErrorAction SilentlyContinue
Set-Variable -Name 'wdDoNotSaveChanges' -Option Constant -Value 0 -ErrorAction SilentlyContinue
$wordfile = 'D:\folder\wordfile.docx'
$pdffile = 'D:\folder\pdffile.pdf'
$pdfformat = $wdFormatPDF
$wordapp = New-Object -ComObject Word.Application
$wordapp.Documents.Open( $wordfile, $false, $true )
$wordapp.Documents.Item( $wordfile ).Activate( )
$wordapp.ActiveDocument.SaveAs( $pdffile, $pdfformat )
$wordapp.ActiveDocument.Close( $wdDoNotSaveChanges )
$wordapp.Quit( )
# Output format constants: https://docs.microsoft.com/office/vba/api/word.wdsaveformatSet-Variable -Name 'wdFormatOpenDocumentText' -Option Constant -Value 23 -ErrorAction SilentlyContinue
Set-Variable -Name 'wdDoNotSaveChanges' -Option Constant -Value 0 -ErrorAction SilentlyContinue
$wordfile = 'D:\folder\test.docx'
$odtfile = 'D:\folder\test.odt'
$odtformat = $wdFormatOpenDocumentText
$wordapp = New-Object -ComObject Word.Application
$wordapp.Documents.Open( $wordfile, $false, $true )
$wordapp.Documents.Item( $wordfile ).Activate( )
$wordapp.ActiveDocument.SaveAs( $odtfile, $odtformat )
$wordapp.ActiveDocument.Close( $wdDoNotSaveChanges )
$wordapp.Quit( ) # if you are sure no other documents are opened in Word
# Based on code by Ijacek:# https://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=33643# and many experiments, and many searches on:# https://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide$inputDoc = 'D:\folder\oofile.odt'
$outputPDF = 'D:\folder\oofile.pdf'
if ( Test-Path -Path $outputPDF -PathType Leaf ) {
Remove-Item -Path $outputPDF -Force
}# convert file paths to URLs$inputURL = ( "file:///{0}" -f ( $inputDoc -replace '\\', '/' ) )
$outputURL = ( "file:///{0}" -f ( $outputPDF -replace '\\', '/' ) )
# set up OpenOffice automation environment[void][System.Reflection.Assembly]::LoadWithPartialName( 'cli_basetypes' )
[void][System.Reflection.Assembly]::LoadWithPartialName( 'cli_cppuhelper' )
[void][System.Reflection.Assembly]::LoadWithPartialName( 'cli_oootypes' )
[void][System.Reflection.Assembly]::LoadWithPartialName( 'cli_ure' )
[void][System.Reflection.Assembly]::LoadWithPartialName( 'cli_uretypes' )
$localContext = [uno.util.Bootstrap]::bootstrap( )
$multiComponentFactory = [unoidl.com.sun.star.uno.XComponentContext].getMethod( 'getServiceManager' ).invoke( $localContext, @( ) )
$desktop = [unoidl.com.sun.star.lang.XMultiComponentFactory].getMethod( 'createInstanceWithContext' ).invoke( $multiComponentFactory, @( 'com.sun.star.frame.Desktop', $localContext ) )
# set file open property Hidden$openHidden = New-Object unoidl.com.sun.star.beans.PropertyValue
$openHidden.Name = "Hidden"
$openHidden.Value = $true
$openProperties = [unoidl.com.sun.star.beans.PropertyValue[]] @( [unoidl.com.sun.star.beans.PropertyValue] $openHidden )
# open OpenOffice document$writer = [unoidl.com.sun.star.frame.XComponentLoader].getMethod( 'loadComponentFromURL' ).invoke( $desktop, @( $inputURL, '_default', 0, $openProperties ) )
# set save as property to PDF$saveAsPDF = New-Object unoidl.com.sun.star.beans.PropertyValue
$saveAsPDF.Name = 'FilterName'
$saveAsPDF.Value = 'writer_pdf_Export'
$storeProperties = [unoidl.com.sun.star.beans.PropertyValue[]] @( [unoidl.com.sun.star.beans.PropertyValue] $saveAsPDF )
# save document as PDF[unoidl.com.sun.star.frame.XStorable].getMethod( 'storeToURL' ).invoke( $writer, @( $outputURL, $storeProperties ) )
# close documents and program[void][unoidl.com.sun.star.frame.XDesktop].GetMethod( 'terminate' ).Invoke( $desktop, $null )
# open the newly created PDF file, if it exists$success = Test-Path -Path $outputPDF -PathType Leaf
if ( $success ) {
Start-Process -FilePath $outputPDF
}# return True if PDF was succesfully created$success
$docxfile = 'D:\folder\wordfile.docx'
if ( -not ( Test-Path $docxfile -PathType Leaf ) ) {
Write-Error ( "`n`tFile not found: `"{0}`"`n`n" -f $docxfile ) -ErrorAction 'Stop'
}$docxext = [System.IO.Path]::GetExtension( $docxfile )
if ( $docxext -ne '.docx' ) {
Write-Error "`n`tThis script reads the text content from .DOCX files only`n`n" -ErrorAction 'Stop'
}Copy-Item -Path $docxfile -Destination "$Env:Temp\~readdocx.zip" -Force # Copy Word file to Temp directory, renaming it to ZIP on the fly
Expand-Archive -Path "$Env:Temp\~readdocx.zip" -DestinationPath "$Env:Temp\~readdocx" -Force # extract the temporary ZIP file
Remove-Item -Path "$Env:Temp\~readdocx.zip" -Force # remove the temporary ZIP file
$docxcontent = $( Get-Content -Path "$Env:Temp\~readdocx\word\document.xml" -Encoding UTF8 ) # read the file document.xml from the extracted ZIP
Remove-Item -Path "$Env:Temp\~readdocx" -Recurse -Force # remove the extracted files
$plaintext = ( $docxcontent -replace '<[^>]+.', '' ) # remove all tags from the XML's content
$plaintext # show the result
# Not as reliable as the code to extract plain text from .DOCX but it usually seems to work$docfile = 'D:\folder\wordfile.doc'
if ( -not ( Test-Path $docfile -PathType Leaf ) ) {
Write-Error ( "`n`tFile not found: `"{0}`"`n`n" -f $docfile ) -ErrorAction 'Stop'
}$docext = [System.IO.Path]::GetExtension( $docfile )
if ( $docext -ne '.doc' ) {
Write-Error "`n`tThis script reads the text content from .DOC files only`n`n" -ErrorAction 'Stop'
}$regex = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList '[^\000\015\367\377]{20,}'
# Assuming the document contained enough text to beat the embedded control strings in length$plaintext = $( $regex.Matches( $( Get-Content -Path $docfile ) ) | Sort-Object { $_.Length } | Select-Object -Last 1 ).Value
$plaintext
$odtfile = 'D:\folder\openofficetextfile.odt'
if ( -not ( Test-Path $odtfile -PathType Leaf ) ) {
Write-Error ( "`n`tFile not found: `"{0}`"`n`n" -f $odtfile ) -ErrorAction 'Stop'
}$odtext = [System.IO.Path]::GetExtension( $odtfile )
if ( $odtext -ne '.odt' ) {
Write-Error "`n`tThis script reads the text content from .ODT files only`n`n" -ErrorAction 'Stop'
}# Copy OpenOffice file to Temp directory, renaming it to ZIP on the flyCopy-Item -Path $odtfile -Destination "$Env:Temp\~readodt.zip" -Force
# extract the temporary ZIP fileExpand-Archive -Path "$Env:Temp\~readodt.zip" -DestinationPath "$Env:Temp\~readodt" -Force
# remove the temporary ZIP fileRemove-Item -Path "$Env:Temp\~readodt.zip" -Force
# read the file content.xml from the extracted ZIP$odtcontent = $( Get-Content -Path "$Env:Temp\~readodt\content.xml" -Encoding UTF8 )
# remove the extracted filesRemove-Item -Path "$Env:Temp\~readodt" -Recurse -Force
# insert linefeeds after paragraphs, headers and list-items$plaintext = ( $odtcontent -replace '</text:(h|list-item|p)>', "`n`n" )
# remove all tags from the XML's content$plaintext = ( $plaintext -replace '<[^>]+.', '' )
# remove excess linefeeds$plaintext = ( $plaintext -replace "`n{3,}", "`n`n" )
# show the result$plaintext
# Based on C# code to use hidden RichTextBox to convert RTF to plain text by Wendy Zang# https://social.msdn.microsoft.com/Forums/vstudio/en-US/6e56af9b-d7d3-49f3-9ec4-80edde3fe54b/reading-modifying-rtf-files?forum=csharpgeneral#a64345e9-cfcb-43be-ab18-c08fae02cb2aAdd-Type -AssemblyName System.Windows.Forms
$rtffile = 'D:\folder\rtfdocument.rtf'
$rtftext = Get-Content -Path $rtffile
$rtbox = New-Object -TypeName System.Windows.Forms.RichTextBox
$rtbox.Rtf = $rtftext
$plaintext = $rtbox.Text
$plaintext
# "progname" is (part of) the name of the program to be removed.# Forget the wildcards if you use the full program name.# Use doublequotes if progname contains spaces or special characters.Get-AppxPackage -AllUsers -Name *progname* | Remove-AppPackage
# Reboot immediately:Restart-Computer -Force
# or:Invoke-CimMethod -Query "SELECT * FROM Win32_OperatingSystem WHERE Primary=TRUE" -MethodName 'Reboot'
# Shutdown immediately:Stop-Computer -Force
# or:Invoke-CimMethod -Query "SELECT * FROM Win32_OperatingSystem WHERE Primary=TRUE" -MethodName 'Shutdown'
# Kill all running processes immediately, resulting in a BSOD, NOT recommended:Stop-Process -ProcessName *
$shell = New-Object -ComObject Shell.Application
$shell.MinimizeAll( ) # restore with $shell.UndoMinimizeALL( )
# or:$shell.ToggleDesktop( ) # restore by running same command a second time (not very reliable)
# or:# Source: Complete List of Windows 10 CLSID Key (GUID) Shortcuts by Shawn Brink# https://www.tenforums.com/tutorials/3123-clsid-key-guid-shortcuts-list-windows-10-a.htmlStart-Process -FilePath explorer.exe -ArgumentList 'shell:::{3080F90D-D7AD-11D9-BD98-0000947B0257}'
# or even shorter:Start-Process -FilePath 'shell:::{3080F90D-D7AD-11D9-BD98-0000947B0257}'
$shell = New-Object -ComObject Shell.Application
$shell.CascadeWindows( )
Start-Sleep -Seconds 5
$shell.TileHorizontally( )
Start-Sleep -Seconds 5
$shell.TileVertically( )
$shell = New-Object -ComObject Shell.Application
$shell.WindowSwitcher( )
Start-Process -FilePath 'd:\'
# or:Start-Process -FilePath 'explorer.exe' -ArgumentList 'd:\'
# or:$shell = New-Object -ComObject Shell.Application
$shell.Explore( 'd:\' )
# Unless you disabled it, you will still be prompted for confirmationStart-Process -FilePath 'shell:RecycleBinFolder' -Verb Empty
# or:Start-Process -FilePath 'shell:::{645FF040-5081-101B-9F08-00AA002F954E}' -Verb Empty
And this is what the result of the previous code will look like:
# All volumes . . . . . . . . . . . optical drives only . . . . no disk loaded . . . . . . . . . . . . . . . . . . . . . open drive . . . . . . . . . . show only the dialogGet-Volume | Where-Object { $_.DriveType -eq 'CD-ROM' -and -not $_.FileSystem } | ForEach-Object { Start-Process -FilePath ( "{0}:" -f $_.DriveLetter ) -WindowStyle Hidden }
# or:# All CD-ROM drives . . . . . . . . . . . . . . . . . no disk loaded . . . . . . . . . . . . . . . . . . . . . . open drive . . . show only the dialogGet-CimInstance -ClassName Win32_CDROMDrive -Filter "MediaLoaded=FALSE" | ForEach-Object { Start-Process -FilePath $_.Drive -WindowStyle Hidden }
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::UseWaitCursor = $true
Write-Host 'Move the mouse pointer please'
Start-Sleep -Seconds 5
[System.Windows.Forms.Application]::UseWaitCursor = $false
Write-Host 'Now move the mouse pointer again, please'
# Open Windows Update settings; more URIs for specific settings can be found at# https://docs.microsoft.com/en-us/windows/uwp/launch-resume/launch-settings-app#ms-settings-uri-scheme-referenceStart-Process "ms-settings:windowsupdate"
Show-ControlPanelItem -Name 'Device Manager' # No longer works in PowerShell 7
# or, for all PowerShell versions:# Source: Complete List of Windows 10 CLSID Key (GUID) Shortcuts by Shawn Brink# https://www.tenforums.com/tutorials/3123-clsid-key-guid-shortcuts-list-windows-10-a.htmlStart-Process -FilePath 'explorer.exe' -ArgumentList 'shell:::{74246bfc-4c96-11d0-abef-0020af6b0b7a}'
# or shorter:Start-Process -FilePath 'shell:::{74246bfc-4c96-11d0-abef-0020af6b0b7a}'
Start-Process -FilePath rundll32.exe -ArgumentList 'shell32.dll,Control_RunDLL mmsys.cpl'
And this is what the result of the previous code will look like: