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 reading
if ( [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 types
foreach ( $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.html
Write-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 digits
Write-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.html
Set-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 result
if ( ( 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 : 2024-12-22 Converted to Julian date : 2460666.5 Converted back to Gregorian : 2024-12-22
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 file
Compress-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 destination
Expand-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 result
Write-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-Host
0..( $columns - 1 ) | ForEach-Object {
if ( $_ -eq 0 ) {
Write-Host "=======`t=====" -NoNewline
} else {
Write-Host "`t`t=======`t=====" -NoNewline
}
}
Write-Host
0..( ( 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: 3.144.40.90
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 font
Add-Type -AssemblyName System.Drawing
# specify EAN-13 font
$font = New-Object -TypeName System.Drawing.Font( 'EAN-13', 48 )
# test if EAN-13 font is installed
if ( $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 created
Start-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-formatid
Set-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 one
Get-CimInstance -ClassName Win32_CDROMDrive | Where-Object { $_.VolumeName -EQ 'Audio CD' } | Select-Object -First 1 | ForEach-Object {
# open the audio CD with the associated player
Start-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-Host
for ( $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=54920
Set-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.wdsaveformat
Set-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.wdsaveformat
Set-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 fly
Copy-Item -Path $odtfile -Destination "$Env:Temp\~readodt.zip" -Force
# extract the temporary ZIP file
Expand-Archive -Path "$Env:Temp\~readodt.zip" -DestinationPath "$Env:Temp\~readodt" -Force
# remove the temporary ZIP file
Remove-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 files
Remove-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-c08fae02cb2a
Add-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
# 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.html
Start-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 confirmation
Start-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 dialog
Get-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 dialog
Get-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-reference
Start-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.html
Start-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:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'PowerShell GUI Demo'
$form.Size = '400,240'
$label1 = New-Object System.Windows.Forms.Label
$label1.Text = 'Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial Arial'
$label1.Font = New-Object System.Drawing.Font( 'Arial', 10 ) # This is the "official" way to specify a font
$label1.Size = New-Object System.Drawing.Size( 200, 40 ) # This is the "official" way to specify a size
$label1.Location = New-Object System.Drawing.Point( 10, 25 ) # This is the "official" way to specify a location
$form.Controls.Add( $label1 )
$label2 = New-Object System.Windows.Forms.Label
$label2.Text = 'Courier Courier Courier Courier Courier Courier Courier Courier Courier Courier Courier Courier Courier'
$label2.Font = 'Courier New,10' # This is an alternative way to specify a font
$label2.Size = '200, 40' # This is an alternative way to specify a size
$label2.Location = '10, 75' # This is an alternative way to specify a location
$form.Controls.Add( $label2 )
$buttonOK = New-Object System.Windows.Forms.Button
$buttonOK.Text = 'OK'
$buttonOK.DialogResult = 'OK' # This should usually not be required
$buttonOK.Location = '10, 150'
$form.Controls.Add( $buttonOK )
$buttonCancel = New-Object System.Windows.Forms.Button
$buttonCancel.Text = 'Cancel'
$buttonCancel.Location = '120, 150'
$form.Controls.Add( $buttonCancel )
$form.AcceptButton = $buttonOK # This should usually suffice to make the dialog return OK when OK is clicked
$form.CancelButton = $buttonCancel
# Without [void] PowerShell will write the ShowDialog result (caption of the button clicked) to screen
[void] $form.ShowDialog( )
# This is another way to get the form's ShowDialog result
Write-Host $form.DialogResult
And this is what the result of the previous code will look like:
# Using IE poses many challenges, use of System.Windows.Forms is preferred.
# This script is derived from a VBScript version, and simplified; for details see:
# https://www.robvanderwoude.com/vbstech_ui_password.php#InternetExplorer
$password = ''
$screen = Get-CimInstance -ClassName Win32_DesktopMonitor # used to center dialog on screen
$html = @"
<div style="text-align: center;">
<p>Please enter your password:</p>
<p><input type="password" size="20" name="Password" id="Password" onkeyup="if(event.keyCode==13){document.all.OKButton.click();}" /></p>
<p><input type="hidden" id="OK" name="OK" value="0" />
<input type="submit" value=" OK " id="OKButton" onclick="document.all.OK.value=1;" /></p>
</div>
"@
# open IE
$ie = New-Object -ComObject 'InternetExplorer.Application'
$ie.Navigate2( 'about:blank' )
$ie.AddressBar = $false
$ie.Resizable = $false
$ie.StatusBar = $false
$ie.ToolBar = $false
$ie.Width = 320
$ie.Height = 180
$ie.Document.Title = 'Please enter password:'
$ie.Document.body.innerHTML = $html
# center dialog on screen
$ie.Left = [int]( ( $screen.ScreenWidth - $ie.Width ) / 2 )
$ie.Top = [int]( ( $screen.ScreenHeight - $ie.Height ) / 2 )
$ie.Visible = $true
$oldErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
# wait until OK is clicked or Enter is pressed
do {
Start-Sleep -Milliseconds 200
} while ( ( $ie.Document.all | Where-Object -Property 'Name' -EQ 'OK' ).Value -eq 0 )
$password = ( $ie.Document.all | Where-Object -Property 'IHTMLElement_id' -EQ 'Password' ).IHTMLInputTextElement_value
# close IE
$ie.Quit( )
$ErrorActionPreference = $oldErrorActionPreference
$password
And this is what the result of the previous code will look like:
# https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-provide-a-progress-dialog-box-for-file-operations
Add-Type -AssemblyName Microsoft.VisualBasic
$sourcePath = "$Env:windir\winSxS"
$destinationPath = "$Env:Temp\test"
$options = [Microsoft.VisualBasic.FileIO.UIOption]::AllDialogs
[Microsoft.VisualBasic.FileIO.FileSystem]::CopyDirectory( $sourcePath, $destinationPath, $options )
# Uncomment the next line to remove the files we copied for this demo
#Remove-Item "$env:Temp\test\" -Force
And this is what the result of the previous code will look like:
# source: "Creating a GUI Using Out-GridView in PowerShell" by Boe Prox
# https://mcpmag.com/articles/2016/02/17/creating-a-gui-using-out-gridview.aspx
@( 'MyDesktop', 'MyLaptop', 'YourDesktop', 'Yourlaptop' ) | Out-GridView -PassThru -Title 'Select your favorite computer'
And this is what the result of the previous code 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 | Out-GridView -Title 'Shell Folders' -PassThru | ForEach-Object { Start-Process -FilePath $( "shell:{0}" -f $_.Name ) }
And this is what the result of previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object -TypeName System.Windows.Forms.Form
$form.Text = 'Select your favorite computer'
$form.Size = '400, 200'
$list = @( 'My Desktop'; 'My Laptop'; 'Your Desktop'; 'Your Laptop' )
$Script:selectedvalue = 'My Laptop'
$dropdown = New-Object -TypeName System.Windows.Forms.ComboBox
$dropdown.Items.AddRange( $list )
$dropdown.SelectedIndex = 1
$dropdown.Width = '200'
$dropdown.Location = New-Object System.Drawing.Point( [int]( ( $form.Width - $dropdown.Width ) / 2 ), 25 )
$form.Controls.Add( $dropdown )
$buttonOK_Click = {
$Script:selectedvalue = $dropdown.Text
$form.DialogResult = 'OK'
$form.Close( )
}
$buttonOK = New-Object System.Windows.Forms.Button
$buttonOK.Text = 'OK'
$buttonOK.Location = New-Object System.Drawing.Point( [int]( ( $form.Width / 2 ) - 5 - $buttonOK.Width ), 100 )
$buttonOK.Add_Click( $buttonOK_Click )
$form.Controls.Add( $buttonOK )
$form.AcceptButton = $buttonOK # pressing Enter assumes OK
$buttonCancel_Click = {
$form.DialogResult = 'Cancel'
$form.Close( )
}
$buttonCancel = New-Object System.Windows.Forms.Button
$buttonCancel.Text = 'Cancel'
$buttonCancel.Location = New-Object System.Drawing.Point( [int]( ( $form.Width / 2 ) + 5 ), 100 )
$buttonCancel.Add_Click( $buttonCancel_Click )
$form.Controls.Add( $buttonCancel )
$form.CancelButton = $buttonCancel # pressing Esc assumes Cancel
$result = $form.ShowDialog( )
if ( $result -eq 'OK' ) {
$Script:selectedvalue
}
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
# message is mandatory; title, button and icon are optional
# message with OK only
[void] [System.Windows.Forms.MessageBox]::Show( "Message", "Title", "OK", "Information" )
# answer required
$answer = [System.Windows.Forms.MessageBox]::Show( "Dou you want to continue erasing all files?", "Please Confirm", "YesNoCancel", "Warning" )
And this is what the result of the previous code will look like:
Add-Type -AssemblyName Microsoft.VisualBasic
$name = [Microsoft.VisualBasic.Interaction]::InputBox( 'Please enter your name', 'Name', $Env:UserName )
And this is what the result of the previous code will look like:
$cred = Get-Credential $UserName # UserName is optional
$newUsername = $cred.GetNetworkCredential( ).UserName
$password = $cred.GetNetworkCredential( ).Password
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
$initialDirectory = [Environment]::GetFolderPath( 'MyDocuments' )
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = $initialDirectory
$OpenFileDialog.Filter = 'Batch files (*.bat;*.cmd)|*.bat;*.cmd'
$OpenFileDialog.Multiselect = $false
$response = $OpenFileDialog.ShowDialog( ) # $response will be OK or Cancel
if ( $response -eq 'OK' ) { Write-Host 'Selected file:' $OpenFileDialog.FileName }
And this is what the result of the previous code will look like:
$shell = New-Object -ComObject Shell.Application
$selectedfolder = $shell.BrowseForFolder( 0, 'Select a folder', 16, $shell.NameSpace( 17 ).Self.Path ).Self.Path
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
$printdialog = New-Object System.Windows.Forms.PrintDialog
$printdialog.AllowCurrentPage = $false
$printdialog.AllowPrintToFile = $false
$printdialog.AllowSelection = $false
$printdialog.AllowSomePages = $false
$printdialog.ShowNetwork = $false
$response = $printdialog.ShowDialog( ) # $response will be OK or Cancel
if ( $response -eq 'OK' ) { Write-Host 'Selected printer:' $printdialog.PrinterSettings.PrinterName }
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object -TypeName System.Windows.Forms.Form
$form.Text = 'Select a printer'
$form.Size = '400, 200'
$list = @( ( Get-Printer ).Name )
$Script:selectedvalue = ''
$dropdown = New-Object -TypeName System.Windows.Forms.ComboBox
$dropdown.Items.AddRange( $list )
$dropdown.SelectedIndex = 0
$dropdown.Width = '200'
$dropdown.Location = New-Object System.Drawing.Point( [int]( ( $form.Width - $dropdown.Width ) / 2 ), 25 )
$form.Controls.Add( $dropdown )
$buttonOK_Click = {
$Script:selectedvalue = $dropdown.Text
$form.DialogResult = 'OK'
$form.Close( )
}
$buttonOK = New-Object System.Windows.Forms.Button
$buttonOK.Text = 'OK'
$buttonOK.Location = New-Object System.Drawing.Point( [int]( ( $form.Width / 2 ) - 5 - $buttonOK.Width ), 100 )
$buttonOK.Add_Click( $buttonOK_Click )
$form.Controls.Add( $buttonOK )
$form.AcceptButton = $buttonOK # pressing Enter assumes OK
$buttonCancel_Click = {
$form.DialogResult = 'Cancel'
$form.Close( )
}
$buttonCancel = New-Object System.Windows.Forms.Button
$buttonCancel.Text = 'Cancel'
$buttonCancel.Location = New-Object System.Drawing.Point( [int]( ( $form.Width / 2 ) + 5 ), 100 )
$buttonCancel.Add_Click( $buttonCancel_Click )
$form.Controls.Add( $buttonCancel )
$form.CancelButton = $buttonCancel # pressing Esc assumes Cancel
$result = $form.ShowDialog( )
if ( $result -eq 'OK' ) {
$Script:selectedvalue
}
And this is what the result of the previous code will look like:
$shell = New-Object -ComObject Shell.Application
$shell.FindPrinter( )
And this is what the result of the previous code will look like:
# See the ShellSpecialFolderConstants enumeration for details:
# https://docs.microsoft.com/en-us/windows/win32/api/shldisp/ne-shldisp-shellspecialfolderconstants
$shell = New-Object -ComObject Shell.Application
$shell.Open( 4 )
# or:
# 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
Start-Process -FilePath shell:PrintersFolder
# See the ShellSpecialFolderConstants enumeration for details:
# https://docs.microsoft.com/en-us/windows/win32/api/shldisp/ne-shldisp-shellspecialfolderconstants
$shell = New-Object -ComObject Shell.Application
$shell.Open( 18 )
Use this list of special folders constants to open other special folders using the Shell.Application
COM object.
Instead of an integer special folder constant, you may also specify an "ordinary" folder path as string.
# 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
Start-Process -FilePath shell:NetworkPlacesFolder
# or:
Start-Process -FilePath shell:::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}
# 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
Start-Process shell:ChangeRemoveProgramsFolder
# or:
Start-Process shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}\0\::{7b81be6a-ce2b-4676-a29e-eb907a5126c5}
$shell = New-Object -ComObject Shell.Application
$shell.FindComputer( )
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
$selectedfont = $null
$fontdialog = New-Object System.Windows.Forms.FontDialog
if ( $fontdialog.ShowDialog( ) -eq 'OK' ) {
$selectedfont = $fontdialog.Font
}
$selectedfont
And this is what the result of the previous code 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
Start-Process -FilePath shell:Fonts
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$Script:selecteddate = ( Get-Date ).Date # default if canceled
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size( 360, 200 )
$form.Text = 'Pick a date within 1 month'
$datepicker = New-Object System.Windows.Forms.DateTimePicker
$datepicker.MinDate = ( Get-Date ) # no past dates allowed
$datepicker.MaxDate = ( Get-Date ).AddMonths( 1 ) # allow dates within 1 month only
$datepicker.Location = New-Object System.Drawing.Point( [int]( ( $form.Width - $datepicker.Width ) / 2 ), 40 )
$form.Controls.Add( $datepicker )
$buttonOK_Click = {
$Script:selecteddate = $datepicker.Value.Date
$form.DialogResult = 'OK'
$form.Close( )
}
$buttonOK = New-Object System.Windows.Forms.Button
$buttonOK.Text = 'OK'
$buttonOK.Location = New-Object System.Drawing.Point( [int]( $form.Width / 2 ) - 5 - $buttonOK.Width, 100 )
$buttonOK.Add_Click( $buttonOK_Click )
$form.Controls.Add( $buttonOK )
$form.AcceptButton = $buttonOK # pressing Enter assumes OK
$buttonCancel_Click = {
$form.DialogResult = 'Cancel'
$form.Close( )
}
$buttonCancel = New-Object System.Windows.Forms.Button
$buttonCancel.Text = 'Cancel'
$buttonCancel.Location = New-Object System.Drawing.Point( [int]( $form.Width / 2 ) + 5, 100 )
$buttonCancel.Add_Click( $buttonCancel_Click )
$form.Controls.Add( $buttonCancel )
$form.CancelButton = $buttonCancel # pressing Esc assumes Cancel
$result = $form.ShowDialog( )
if ( $result -eq 'OK' ) {
Write-Host ( "Selected date: {0}" -f $Script:selecteddate.ToString( 'yyyy-MM-dd' ) )
}
And this is what the result of the previous code will look like:
$startdate = $( Get-Date ).Date # or pick any other start date
$enddate = $startdate.AddMonths( 1 ) # or pick any other end date
$title = 'Select a date within a month from now' # adjust the title for the chosen date range
# First convert dates to integers so we can define a range, next convert back to dates, next select
# to show date only, then format the date, and finally show as list in GridView to select a value
$selecteddate = $( $startdate.ToOADate( )..$enddate.ToOADate( ) `
| ForEach-Object { [DateTime]::FromOADate( $_ ) } `
| Select-Object Date `
| ForEach-Object { $_.Date.ToString( 'yyyy-MM-dd' ) } `
| Out-GridView -Title $title -PassThru )
"Selected date: $selecteddate"
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
$colorDialog = New-Object System.Windows.Forms.ColorDialog
$colorDialog.SolidColorOnly = $true
if ( $colorDialog.ShowDialog( ) -eq 'OK' ) {
# if the selected color doesn't have a name, the hexadecimal RGB value will be returned
Write-Host ( "Selected color: {0}" -f $colorDialog.Color.Name )
}
And this is what the result of the previous code will look like:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Base64 encoded icon
$b64convicon = "AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAA"
$b64convicon += "AAAAAAAAAAAAAAAAAAAEAgQAhIKEAPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$b64convicon += "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$b64convicon += "AAAAAAAAAAAAAAAAAAAAEiEAAAICAAEgAgEAAgEgAgAAAgARACECAAAAACAAAgIA"
$b64convicon += "AAEAIAACAgAAAgEQACEBIAIAAgABIAASIQACAAIAAAAAAAAAAAAAAAAAAAAAAAAA"
$b64convicon += "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$b64convicon += "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$form = New-Object System.Windows.Forms.Form
# Use Base64 encoded icon in code, by Kenny Baldwin
# https://foxdeploy.com/2013/10/23/creating-a-gui-natively-for-your-powershell-tools-using-net-methods/#comments
$form.Icon = ( [System.Drawing.Icon]( New-Object System.Drawing.Icon( ( New-Object System.IO.MemoryStream( ( $$ = [System.Convert]::FromBase64String( $b64convicon ) ), 0, $$.Length ) ) ) ) )
$form.ShowDialog( )
And this is what the result of the previous code will look like (note the icon):
# System Tray ToolTip Balloon by Don Jones
# http://blog.sapien.com/current/2007/4/27/creating-a-balloon-tip-notification-in-powershell.html
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Base64 encoded icon
$b64convicon = 'AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAA'
$b64convicon += 'AAAAAAAAAAAAAAAAAAAEAgQAhIKEAPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
$b64convicon += 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
$b64convicon += 'AAAAAAAAAAAAAAAAAAAAEiEAAAICAAEgAgEAAgEgAgAAAgARACECAAAAACAAAgIA'
$b64convicon += 'AAEAIAACAgAAAgEQACEBIAIAAgABIAASIQACAAIAAAAAAAAAAAAAAAAAAAAAAAAA'
$b64convicon += 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
$b64convicon += 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
# Use Base64 encoded icon in code, by Kenny Baldwin
# https://foxdeploy.com/2013/10/23/creating-a-gui-natively-for-your-powershell-tools-using-net-methods/#comments
$icon = [System.Drawing.Icon]( New-Object System.Drawing.Icon( ( New-Object System.IO.MemoryStream( ( $$ = [System.Convert]::FromBase64String( $b64convicon ) ), 0, $$.Length ) ) ) )
$notify = new-object system.windows.forms.notifyicon
$notify.icon = $icon
$notify.visible = $true
# show the balloon for 10 seconds (will not show in Windows 10)
$notify.showballoontip( 10, "Reminder", "It's scripting time", [system.windows.forms.tooltipicon]::Info )
# Uncomment the next command line to remove the icon, or type it manually, or
# close the balloon and hover the mouse pointer over the system tray icon.
# $notify.Visible = $false
And this is what the result of the previous code will look like (we just inserted the icon):
$shell = New-Object -ComObject Shell.Application
$shell.FileRun( )
And this is what the result of the previous code will look like:
$shell = New-Object -ComObject Shell.Application
$shell.ShutdownWindows( )
# or as a one-liner:
( New-Object -ComObject Shell.Application ).ShutdownWindows( )
And this is what the result of the previous code will look like:
page last modified: 2024-03-11; loaded in 0.3415 seconds