PS: Software Commands

11 minute read

Description:

This section is for Powershell itself and any software on the OS.

To See how Powershell developers coded an internal function (Out-File in this example):

$command = Get-Command Out-File -CommandType Cmdlet
$metadata = New-Object System.Management.Automation.CommandMetaData($command)
$proxyCode = [System.Management.Automation.ProxyCommand]::Create($metadata)
$proxyCode

NOTE: Almost all command prompt commands work just as well in Powershell. Search the “batch” label to see examples of them.

To Launch PS As Admin:

Start-Process powershell.exe -verb runas

To Launch ISE As Admin:

Start-Process powershell_ise -verb runas

To Start An EXE As Admin:

cmd /c “runas /profile /user:server\administrator “C:\Program Files (x86)\Google\Drive\googledrivesync.exe””

To Make A Shortcut Run As Admin

$fullpath = 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\Event Viewer.lnk'
$fileBytes = [System.IO.File]::ReadAllBytes($fullpath)
$fileBytes[0x15] = $fileBytes[0x15] -bor 0x20
[System.IO.File]::WriteAllBytes($fullpath, $fileBytes)

To Start A Program Normally:

C:\Windows\System32\calc.exe
# or
cmd /c “start C:\Windows\System32\calc.exe”
# or 
& C:\Windows\System32\calc.exe

To Bulk Install Programs (Change the path of the executables relative to scripts running path)

Write-Output "Installing PDF" 
If (!(Test-Path "C:\Program Files (x86)\PDF"))
{
    Set-Location -Path "$PSScriptRoot\..\Private\Bin\pdf"
    Invoke-Item -Path "$PSScriptRoot\..\Private\Bin\pdf\setup.exe"
    cmd /c "pause"
}
Else
{
    Write-Output "PDF already installed, moving on" 
}

To Get OS Version

# To get the Server OS Version:

$Counter = 0
[string]$OsName = Get-Ciminstance -ClassName Win32_OperatingSystem -Property Caption | Select-Object -ExpandProperty Caption

Switch -Regex ($osName)
{
    '7'
    {
        Log $osName; $Counter = 1; Break 
    }
    # Had to put R2 first because if it matches 2008, it would just break and not keep the correct counter. Nested elseif's could be another option.
    '2008 R2'
    {
        Log $osName; $Counter = 3; Break 
    }
    '2008'
    {
        Log $osName; $Counter = 2; Break 
    }
    '2012 R2'
    {
        Log $osName; $Counter = 5; Break 
    }
    '2012'
    {
        Log $osName; $Counter = 4; Break 
    }
    '10'
    {
        Log $osName; $Counter = 6; Break 
    }
    '2016'
    {
        Log $osName; $Counter = 7; Break 
    }
}

# Then, if older than 2012r2, you can run this:

If ($Counter -le 4)
{
    # Do something in older versions of Powershell (Versions 2, 3)
}
Else
{
    # Do something in newer versions of Powershell (4+)
}

To Interact With COM Objects (Outlook in this example)

# New Outlook object
$ol = new-object -comobject "Outlook.Application";

# MAPI namespace
$mapi = $ol.getnamespace("mapi");

$folder =  $mapi.Folders.Item('name@gmail.com').Folders.Item('Inbox')

# Get the items in the folder
$contents = $folder.Items

# Sort the items in the folder by the metadata, in this case ReceivedTime
$contents.Sort("ReceivedTime")

# Get the first item in the sorting; in this case, you will get the oldest item in your inbox.
$item = $contents.GetFirst()
echo $item

# If instead you wanted to get the newest item, you could do the same thing but do $item = $contents.GetLast()

To Make Sure A Script Is Running As Admin, And If Not – Restart As Admin With All Parameters Passed:

If (-Not ([Security.Principal.Windowsprincipal][Security.Principal.Windowsidentity]::Getcurrent()).Isinrole([Security.Principal.Windowsbuiltinrole] “Administrator”))
{
$Arguments = “& ‘” + $Myinvocation.Mycommand.Definition + “‘”
Start-Process Powershell -Verb Runas -Argumentlist $Arguments
Break
}

To Clear The Credential Manager:

cmd /c “cmdkey /list” | ForEach-Object {if ($_ -like “*Target:*)
{
cmdkey /del:($_ -replace ” “, “” -replace “Target:”, “”)
}}

To Stop A Process If It Is Running:

$process = Get-Process -Name “powershell.exe” -ErrorAction SilentlyContinue
If ($process -eq $null)
{
Write-Log “$($process.name) is not running, continuing…” -Logfile $Logfile
}
Else
{
Stop-Process $process
Write-Log “$($process.name) is running, closing” -Logfile $Logfile
}

To Restart A Computer Into Advanced Startup Mode:

cmd /c “shutdown /o /r /t 02”

To Add An Environmental Variable:

$X = “C:\_Gwill\Google\Scripts\_Other-Langs\Python\Python27”
$Env:Path+= “;” + $X + “;”
[Environment]::Setenvironmentvariable(“Path”,$Env:Path, [System.Environmentvariabletarget]::User)
Write-Output “Path Updated Permanently!!”

To Enable System Restore and Create A Checkpoint:

Enable-ComputerRestore -Drive $env:systemdrive -Verbose
Checkpoint-Computer -Description “Default Config” -RestorePointType “MODIFY_SETTINGS” -Verbose

To Set UAC Setting To Third Bar Down (Notify When Apps Make Changes… Don’t Dim):

$registryPath = “HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System”
$Name = “ConsentPromptBehaviorAdmin”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

$registryPath = “HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System”
$Name = “EnableInstallerDetection”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

$registryPath = “HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System”
$Name = “PromptOnSecureDesktop”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

$registryPath = “HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System”
$Name = “FilterAdministratorToken”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

To Set A Daily Task (Daily/2AM):

$taskName = “ExampleDailyChocolateyUpgrade”
$taskAction = New-ScheduledTaskAction –Execute C:\programdata\chocolatey\choco.exe -Argument “upgrade all -y”
$taskTrigger = New-ScheduledTaskTrigger -At 2am -Daily
$taskUser = “System”
Register-ScheduledTask –TaskName $taskName -Action $taskAction –Trigger $taskTrigger -User $taskUser

To Set Power Settings To “Never Sleep”:

cmd /c “powercfg -change -monitor-timeout-ac 0”
cmd /c “powercfg -change -monitor-timeout-dc 0”
cmd /c “powercfg -change -standby-timeout-ac 0”
cmd /c “powercfg -change -standby-timeout-dc 0”
cmd /c “powercfg -change -disk-timeout-ac 0”
cmd /c “powercfg -change -disk-timeout-dc 0”
cmd /c “powercfg -change -hibernate-timeout-ac 0”
cmd /c “powercfg -change -hibernate-timeout-dc 0”

To Allow Pings, RDP, WMI, and File and Printer Sharing Through Firewall:

Import-Module NetSecurity
Enable-NetFirewallRule -DisplayGroup “Remote Desktop”
New-NetFirewallRule -Name Allow_RDP -DisplayName “Allow Ping” -Description “Packet Internet Groper ICMPv4” -Protocol ICMPv4 -IcmpType Any -Enabled True -Profile Any -Action Allow
New-NetFirewallRule -Name Allow_Ping -DisplayName “Allow Ping” -Description “Packet Internet Groper ICMPv4” -Protocol ICMPv4 -IcmpType Any -Enabled True -Direction Outbound -Profile Any -Action Allow
Set-NetFirewallRule -DisplayGroup “Windows Management Instrumentation (WMI)” -Profile Any
Set-NetFirewallRule -DisplayGroup “Network Discovery” -Profile Any
Set-NetFirewallRule -DisplayGroup “File and Printer Sharing” -Profile Any
Set-NetFirewallRule -DisplayGroup “Windows Firewall Remote Management” -Profile Any
Set-NetFirewallRule -DisplayGroup “Core Networking” -Profile Any

To Create Custom Firewall Rules

$Params = @{
    'DisplayName' = "AllowRDP"
    'Description' = "Allow Remote Desktop"
    'Profile' = "Any"
    'Direction' = "Inbound"
    'LocalPort' = "3389"
    'Protocol' = "TCP"
    'Action' = "Allow"
    'Enabled' = "True"
}
New-NetFirewallRule @Params | Out-Null

To Disable Firewall

Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
# or
netsh advfirewall set allprofiles state off

To Enable Remote Desktop With Network Level Authentication:

$registryPath = “HKLM:\System\CurrentControlSet\Control\Terminal Server”
$Name = “fDenyTSConnections”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

$registryPath = “HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp”
$Name = “UserAuthentication”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

To Disable Remote Assistance:

$registryPath = “HKLM:\System\CurrentControlSet\Control\Remote Assistance”
$Name = “fAllowToGetHelp”
$value = “0”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

To Disable Windows Update Automatic Restart:

$registryPath = “HKLM:\Software\Microsoft\WindowsUpdate\UX\Settings”
$Name = “UxOption”
$value = “1”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

To Export/Import Start Menu Layouts:

Export-StartLayout –path c:\_gwill\startmenu.xml
Import-StartLayout -LayoutPath c:\software\startmenu.xml -MountPath c:

To Disable Windows Defender:

# Get information about Server roles and features that are available or installed
Get-WindowsFeature
# Turn-off real-time protection
Set-MpPreference -DisableRealtimeMonitoring $true
# Check real-time protection status
Get-MpPreference | FL *RealtimeMonitoring
# Turn-on real-time protection
Set-MpPreference -DisableRealtimeMonitoring $false
# Install Windows Defender GUI (no restart required)
Install-WindowsFeature Windows-Defender-GUI
# Uninstall Windows Defender and its GUI (restart required)
Remove-WindowsFeature Windows-Defender, Windows-Defender-GUI

Another way to disable Windows defender:

$registryPath = “HKLM:\System\CurrentControlSet\Services\SecurityHealthService”
$name = “Start”
$value = “4”
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null
Restart-Computer

To Enable PS Remoting:

Enable-Psremoting -Force
# Make sure to hit "a" yes to all on the prompts

To Update Help (One of the First Tasks To Do):

Update-Help

To Create A Text File of A Command’s Help:

Get-Help (Commandname) -Full >(Commandname Or Whatever).Txt

To Get A Pop-Up Window In Finding Help:

Get-Help Invoke-Item -ShowWindow

To Run A “What-If” Analysis For A Command. You Can Also Use “-confirmation” For A Pop-Up Confirmation Prompt:

Restart-Computer -WhatIf
#or
Restart-Computer -Confirm

To Find the Properties/Method of A Command. Pipe To Get-Member or “gm”:

Get-Process | Gm

To Start A Transcript Of All Commands and Their Output For A PS Session:

Start-Transcript (Pathname)

To Change The Background of the PS GUI:

(Get-Host).Ui.Rawui.Backgroundcolor = "Red"

To Check The Execution Policy and Change It To Remote Signed:

# Must Run-As Admin

# Gets Current Execution Policy
Get-Executionpolicy
Set-Executionpolicy Remotesigned

To Get The Version of PS Running:

$PSVersionTable

To Open Your Current Directory In Windows Explorer Using Invoke-Item:

ii .

To See If A Command Has An Alias:

Get-Alias -Definition (Commandname)

To Create Your Own Alias:

New-Alias -Name (Shortname) -Val (Realcommandname) -Desc (Not Mandatory But You Can Add A Description)

To Search Help On SS64.com From PS:

Function Get-Help2
{
param([string]$command)
$lcommand = $command.ToLower()
Start-process -filepath “http://ss64.com/ps/$lcommand.html”
}

To AutoLoad Scripts (Usually Placed In PS Profile):

$autodir=”C:\Scripts\_Autoload”
Get-ChildItem${autodir}\*.ps1” | ForEach-Object {.$_}
Write-Output “Scripts in ” + $autodir + ” loaded”

To Add All Clients To Trusted Hosts

Set-Item wsman:\localhost\Client\TrustedHosts -value *

To Learn Begin, Process, End:

Function Test-BPEPowershell
{
Begin
{
$i = 0
Write-Host “Setting `$i in Begin to $i}
Process
{
$i++
Write-Host “Setting `$i in Begin to $i}
End
{
Write-Host “Setting `$i in Begin to $i}
}
‘1’, ‘2’, ‘3’ |Test-BPEPowershell

To Learn “-WhatIf”:

Function Restart-Computers
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    param(
        [string[]]$ComputersToRestart
    )

    ForEach ($Computer in $ComputersToRestart)
    {
        # If the user uses the -Whatif parameter, this will show: 
        # What if: Performing the operation "Rebooting the server" on target "Server01", but won't actually do it.
        If ($pscmdlet.ShouldProcess("$Computer", "Rebooting the server"))
        {
            # Put code here for code you want to run if the user DOESN'T USE the -WhatIf parameter
            Write-Output "Restarting computer $Computer"
            Restart-Computer $Computer 
        }
    }
}
Restart-Computers -ComputersToRestart "Server01", "Server02" -WhatIf

To Create A Collection Of Objects In A Single Variable:

[System.Management.Automation.Scriptblock]$Scriptblock = {
$Lastboottime = (Get-Ciminstance -Classname Win32_Operatingsystem | Select-Object -Property Lastbootuptime).Lastbootuptime
Return [Datetime]$Lastboottime
}

Process
{
Foreach ($Computer In $Computername)
{
$Lastboottime = Invoke-Command -Scriptblock $Scriptblock
}
$table = [Pscustomobject] @{
Computername = $Computer
Lastboottime = $Lastboottime
}

Info we need:
For Each $computer in $computername – builds the computer name table
$lastboottime = main information we want to get from each computer
$table = Variable that will hold the values for each computer processed

More Advanced:

To Make Your Computer Talk Using MS Speech:

Add-Type -AssemblyName System.speech
$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer
$speak.Speak('Ohhh Baby Ohh Yeah Do Me Harder')

To Make Sure Your Script Runs As Administrator:

If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
[Security.Principal.WindowsBuiltInRole] “Administrator”))
{
Write-Warning “You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!”
Break
}

Disable Screensaver:

Set-ItemProperty -Path ‘HKCU:SoftwarePoliciesMicrosoftWindowsControl PanelDesktop’ -Name ScreenSaveTimeOut -Value 0
Set-ItemProperty -Path ‘HKCU:SoftwarePoliciesMicrosoftWindowsControl PanelDesktop’ -Name ScreenSaveActive -Value 0
Set-ItemProperty -Path ‘HKCU:SoftwarePoliciesMicrosoftWindowsControl PanelDesktop’ -Name ScreenSaverIsSecure -Value 0

Enable Task Manager (post virus cleanup):

Set-ItemProperty -Path ‘HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\System’ -Name DisableTaskMgr -Value 0

Disable Windows 7 Automatic Driver Installation:

Set-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DriverSearching -Name SearchOrderConfig -Value 0

To Add A GUI To Server 2012 Core: to uninstall type “uninstall” at the beginning

Install-WindowsFeature -ComputerName Server-Gui-Mgmt-Infra, Server-Gui-Shell -Restart

To Get All Scheduled Tasks and Export Them To CSV:

schtasks /query /v /fo csv | out-file tasks.csv

To Create A Pop-Up Window:

$wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
$wshell.popup("Text",0,"Message",48+4)
#or
(new-object -ComObject wscript.shell).Popup("Text",3,"Message") 
# Change the 3 to however long you want to message to appear. 0 will leave it up until user intervention.

To Change The Hostname:

# From Elevated CMD:
$computerName = Get-WmiObject Win32_ComputerSystem
$newName = Read-Host -Prompt "Please enter new hostname:"
$computerName.Rename($newName)
# For PSv3+:
Rename-Computer "newName"
Restart-Computer -Force

To Get Logged On User:

Get-WmiObject Win32_LogonSession -ComputerName localhost -Filter 'LogonType=2 OR LogonType=10' |
Foreach-Object { $_.GetRelated('Win32_UserAccount') } |
Select-Object Caption -Unique

To Get Last Reboot Time:

$RebootTime = [System.DateTime]::ParseExact((Get-WmiObject Win32_OperatingSystem -ComputerName localhost| foreach{$_.LastBootUpTime}).split('.')[0],'yyyyMMddHHmmss',$null)
$RebootTime

To Run Remote .BAT file Using PS Remoting:

copy c:\test.bat \\test\c$\test.bat
invoke-command -script {c:\test.bat} -computer test

To have a service start automatically:

$A = get-service Wuauserv
if ($A.Status -eq "Stopped") {$A.start()} elseIf ($A.status -eq "Running") {Write-Output -Verbose $A.name "is running"}

To unblock scripts you download:

gci C:\path\to\scripts -recurse | unblock-file -Verbose

To Save To SQL Database

<#
Saving data to SQL Server - versus Excel or some other contraption - is easy.

Assume that you have SQL Server Express installed locally. You've created in it a database called MYDB, and in that a table called MYTABLE. 
The table has ColumnA and ColumnB, which are both strings (VARCHAR) fields. And the database file is in c:\myfiles\mydb.mdf. 
This is all easy to set up in a GUI if you download SQL Server Express "with tools" edition. And it's free!

$cola = "Data to go into ColumnA"
$colb = "Data to go into ColumnB"

$connection_string = "Server=.\SQLExpress;AttachDbFilename=C:\Myfiles\mydb.mdf;Database=mydb;Trusted_Connection=Yes;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connection_string
$connection.Open()
$command = New-Object System.Data.SqlClient.SqlCommand
$command.Connection = $connection

$sql = "INSERT INTO MYTABLE (ColumnA,ColumnB) VALUES('$cola','$colb')"
$command.CommandText = $sql
$command.ExecuteNonQuery()

$connection.close()
You can insert lots of values by just looping through the three lines that define the SQL statement and execute it:

$cola = @('Value1','Value2','Value3')
$colb = @('Stuff1','Stuff2','Stuff3')

$connection_string = "Server=.\SQLExpress;AttachDbFilename=C:\Myfiles\mydb.mdf;Database=mydb;Trusted_Connection=Yes;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connection_string
$connection.Open()
$command = New-Object System.Data.SqlClient.SqlCommand
$command.Connection = $connection

for ($i=0; $i -lt 3; $i++) {
  $sql = "INSERT INTO MYTABLE (ColumnA,ColumnB) VALUES('$($cola[$i])','$($colb[$i])')"
  $command.CommandText = $sql
  $command.ExecuteNonQuery()
}

$connection.close()
It's just as easy to run UPDATE or DELETE queries in exactly the same way. SELECT queries use ExecuteReader() instead of ExecuteNonQuery(), and return a SqlDataReader object that you can use to read column data or advance to the next row.
#>