How To Recover SQLSERVER Service from Being Unable to Start

# startSqlService.ps1

    $sqlService=get-service MSSQLSERVER -EA Ignore
    if($sqlService.Status -ne $desiredState -and $null -ne $sqlService){
        start-service 'MSSQLSERVER'
    write-warning $_
    $attempt=net start mssqlserver /T902 2>&1|FIND "already been started"
    if($attempt -match 'already been started'){
        write-host "MSSQLSERVER has been started with trace flag /T902"

PowerShell: How to Change Guest VM Names in Virtual Machine Manager

# changeGuessVmNameInVmm.ps1
# The following script prepend all VM's matching certain pattern
# This is useful to mark VM's to be deleted for ease of administration

$prefix='(decom 02-01-2020) '

$targetVms=Get-SCVirtualMachine|?{$_.Name -like "*$nameLike*"} 
foreach($targetVm in $targetVms){
        $changed=Set-SCVirtualMachine -VM $targetVm -Name $newName
        if($ -eq $newName){
            write-host "$oldName's name has been changed to $newName" -foregroundcolor Green
            write-host "$oldName's name has NOT been changed to $newName" -foregroundcolor Red
        write-warning $_        

Resume All Guest VMs in a Clustered Hyper-V Environment

# resumeAllVms.ps1
# Significance: this script is useful in a Clustered Hyper-V environment
# where storage was down for over 60 seconds, causing Hyper-V to put all guest VM's into 'paused-critical' statuses.
# During such event, the cluster would be unreachable as well. Hence, knowing node names prior to pasting this script
# would be necessary.

$computernames=@($computerlist -split "`n")|%{$_.Trim()}
foreach ($computername in $computernames){
  invoke-command $computername {
    write-host "Connected to $env:computername..."
    #Get list of all VMs on this host
    #write-host "$env:computername`:`r`n$($vmNames|out-string)"
    # Unpausing all VMs
    $pausedVms=get-vm | where state -eq 'paused'
    foreach($vm in $pausedVMs){        
        write-host $vm.Name -nonewline
        $vm|resume-vm -ea stop
        write-host ": resumed" -foregroundcolor Green
        write-warning $_

PowerShell: Command to Retrieve Windows Applications List

The following the the PoSH equivalent of appwiz.cpl in Windows:

PS> invoke-command TestWindows {Get-Package -Provider Programs -IncludeWindowsInstaller|select-object Name,Version|sort -property Name}|select -property * -ExcludeProperty runspaceid,pscomputername

Name                                                               Version
----                                                               -------
7-Zip 18.06 (x64 edition)                                
DRAC Command Line Tools                                            9.2.0
Notepad++ (64-bit x64)                                             7.5.9
NSClient++ (x64)                                                   0.5.2039
PuTTY release 0.71 (64-bit)                              

Linux Cheat Sheet

Below is a quick reference to the most useful commands and techniques for a Linux sysadmin:

List of useful commands:
netstat # shows network connections -a (all tcp/udp), -l (listening ports), -at (all tcp), -u (udp)
curl # send get command to URL: -I (retrieve header), -X POST --data "u=username&p=password" (execute post command, flag contains data), -o file.html (save to a file)
env # show environmental variables: printenv <var> (print), export <var>=<value> (change, non-persistent), vi .bashrc (set changes), source .bashrc (pull stored env configs), vi /etc/environment (make changes for all users)
whoami  #  show current username
rmdir  #  remove directory
tail  #  shows just the last 10 lines of file
man  #  display manual
rm  #  remove item	
date  #   shows current date and time
clear  #  clear terminal
touch  #  create a file
cat  #  read file
pwd  #  get current path
less  #  is the better more command
ls  #  list contents
mv  #  move or change file name
echo  #  printout to terminal
cd  #  change directory
cp  #  copy 
wc  #  word count
mkdir  #  make directory
head  #  shows first 10 lines
sort  #  sort a stream or text file
uniq  #  remove duplicates or show only uniques
diff  #  shows differences between 2 files or streams
find  #  search live (without using indexed db)
grep  #  search from file or stream
du -h  #  disk usage information in human readable format
df  #  disk free
history  #  list previous commands
ps  #  process status, use with -aux to show lots of info
top  #  show top processes
kill <pid>  #  kill a process by its pid
killall <processname>  #  kill all processes matching name
jobs  #  display current jobs
fg  #  switch background job into foreground
bg  #  switch foreground job into background
sleep  #  pause for a number of seconds
gzip  #  uses gzip with -f (force), -r (compress recursively), -d (decompress), -[1-9] (compression level)
gunzip  #  uses the smarter gunzip with -f (force), -c (view-only), -k (keep original zip after uncompressed), -r (recurse), -v (verbose), -d (decompress)
tar  #  create a tarball: cvzf (compress) vs xvzf (extract)
nano  #  text editor, most common
alias k='kubectl' # create an alias command basing on another command or script
xargs # accept output of a stream as arguments of a command. Example: echo 'one two three' | xargs mkdir
ln	# create a hard link, use -s for symlink
who	# shows all current users and sessions
su	# switch user account
sudo	# enter root context
passwd # change password of a user
chown	# change ownership of an item
chmod	# modify permissions of an item

# How to discover OS version
cat /etc/os-release

# How to get kernel version
uname -r
cat /proc/version
hostnamectl | grep Kernel

# Add a user
adduser user2 -g <groupname> # create new user and set its group membership
sudo passwd user2	# change password of user

# modify a user
sudo usermod -aG <groupname>,<group2> user2 # add user to more [non-primary] groups
sudo usermod -ag <groupname> user2 # change user's primary group
usermod -s /dev/null user2	# send user logon sessions to the black hole
usermod -d /home/user2newhome --move-home user2	# move a user's home directory
usermod -l <newusername> <oldusername>
usermod -L user2 # lock a user account
usermod -U user2 # unlock a user account
chage -l user2	# check age of user account

# Remove user
userdel -r user2

# groups management
groups <username>	# get membership of user
groupadd sales
groupmod -n sales_new sales	# change the group name
groupmod -gid GID <groupname>	# change group ID
groupdel sales_new

# commands to check logins
id <username>
pinky (replacement of finger command)

# password database
	- users: /etc/passwd
	- passwords: /etc/shadow
	- groups: /etc/group
	- group passwords: /etc/gshadow
# Edit users file
sudo vipw
# Edit shadow file
sudo vipws

# User Profiles
# System-wide
	- /etc/environment
	- /etc/bash.bashrc
	- /etc/bashrc
	- /etc/profile
# personal profiles
	- /home/username/.bashrc
	- /home/username/.profile
	- /home/username/.bash-profile

# Jobs management
ping &  # run a command and put into background
jobs  # check jobs
ping ... then [control-Z] to suspend job and put into background
bg [job number] # put background job into running status
fg [job number] # bring job into foreground
[control-Z] to halt job
nohup ping localhost &  # run jobs in the background and detach from current session
nohup ping localhost >/dev/null 2>&1 :Send standard output to /dev/null, plus sending standard errors (code 2) to same destination (which is also /dev/null).

# Search devices
# ls commands
lsblk # list block storage (hard drives, DVD-rom, usb-drive)
lscpu # show cpu info
lsdev # show devices
lspci # show all PCI devices
lsusb # show usb devices
# kernel messages

# where to find kernel & device info
/proc/  # original container for process
/sys/	# new folder to contain kernel info
/dev/	# system devices

# use cache database to look for files
sudo updatedb # update name index database prior to issuing command
locate file.txt	# use indexed database to search for files
locate sshd.service # more common to search for expected libraries

# File viewing
cat file.txt | grep searchstring
grep searchstring file.txt

# command redirects
	- STDOUT: >
	- STDIN: < or |
	- STDERR: 2>
	- /dev/null 2>&1 : STDERR redirect to STDOUT of preceeding location (blackhole)
# command to manipulate files and streams
cat textfile.txt | tee textfile_copy.txt # STDOUT and output to a file or console
echo "newfolder" | xargs mkdir # takes STDIN as arguments and then execute
echo "test" > /dev/null > 2>&1	# send stream and errors to the void
printf '4\n1\n2\n3\n'|sort	# sort the output
cut -c 1 textfile.txt	# show the 1st character in each line
paste file1.txt file2.txt > joined.txt
wc -m file1.txt # display the characters count of file
awk '{print $1}' file1.txt	# print first word of each line
echo "searchword other" | sed s/searchword/replaceword/g # search and replace

# soft-links and hard-links
ln -s file1.txt file1_shortcut.txt
ln file1_hardlink.txt file1.txt
find ~ -samefile file1.txt	# look in user directory for files with same pointer to storage location as file1.txt
ls -li # list files with inode info

# search for file in real-time
find . -name file.txt	# look in current location for file matching name
find / -name *file.txt* 2> /dev/null		# redirect errors into void to show only matching results

# secure copy using scp
scp user1@linuxbox:/home/user1/testfile.txt ~/ # Get 1 file
scp testfile.txt user1@linuxbox:/home/user1/ # Put 1 file

# Network copying using rsync
rsync -av user1@linuxbox:/home/user1 .  # get files recursively
rsync -av /home/user1/Desktop user1@linuxbox:/home/user1/Desktop # Put files

# Debian/Ubuntu runlevels
0 = halt
1 = single user mode
2 = full, multi-user mode [with GUI if installed]
3-5 unused
6 = Reboot

# Redhat/Centos runlevels
0 = halt (systemd boot target: poweroff)
1 = single user mode (rescue)
2 = multi-user, no network
3 = multi-user, with network (multi-user)
4 = unused
5 = multi-user with GUI (graphical)
6 = Reboot (reboot)

# systemd boot targets

# change runlevel
runlevel # check current runlevel
telinit 6 # reboot
vi /etc/inittab # edit default runlevels

# change boot targets
systemctl get-default # view default mode
systemctl set-default # change the boot target, effective on next reboot
systemctl isolate multi-user # switch to mode immediately

# systemd commands to control services
systemctl status kubelet
systemctl disable kubelet # change bootup status
systemctl enable kubelet
systemctl start kubelet
systemctl stop kubelet

# service commands
service httpd start
service httpd stop
service httpd status
chkconfig --list httpd # check config of service on runlevels
chkconfig httpd on # turn service on runlevels 2-5
chkconfig --level 1 httpd on # turn service on at specific runlevel

# Cron
# search for pre-made cron files
root@linuxbox:/$  cd /etc && ls -d -1 "$PWD/"**|grep cron

# format: minute hour day-of-month month day-of-week
crontab -e # edit personal crontab
# add lines to run scheduled tasks
* * * * * echo "something" # every minute
*/15 * * * * echo "something" # every 15 minutes
30 12 9-15 * 2 echo "something" # every 2nd Tuesday of each month at 12:30am

# delayed execution using at daemon
at now +1 hour # run something 1 hour from now

# printing with CUPS
web GUI is located at http://localhost:631
"Print this line" | lpr # send test to printer
lpr textfile.txt 	# print text file
lpq	# list running print jobs
lprm [jobId]	# remote a print job

# How to mount drives

# check drives

# scan for usb drives
user1@linuxbox:~$ lsusb
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 136b:2300 STEC FlashLink All-in-One Reader
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 18a5:0302 Verbatim, Ltd Flash Drive	# this is the USB drive being plugged in
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

user1@linuxbox:~$ usb-devices
T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh= 9
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev=05.04
S:  Manufacturer=Linux 5.4.0-132-generic xhci-hcd
S:  Product=xHCI Host Controller
S:  SerialNumber=0000:12:00.0
C:  #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=0mA
I:  If#=0x0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub

T:  Bus=01 Lev=01 Prnt=01 Port=07 Cnt=01 Dev#=  4 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=18a5 ProdID=0302 Rev=02.00
S:  Manufacturer=Verbatim
S:  Product=STORE N GO
S:  SerialNumber=7716151047687633054
C:  #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:  If#=0x0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage

kim@linux03:~$ lsblk
sda       8:0    0 931.5G  0 disk
└─sda1    8:1    0 931.5G  0 part
  └─md0   9:0    0   1.8T  0 raid10 /
sdb       8:16   0 931.5G  0 disk
└─sdb1    8:17   0 931.5G  0 part
  └─md0   9:0    0   1.8T  0 raid10 /
sdc       8:32   1  29.8G  0 disk
├─sdc1    8:33   1   512M  0 part   /boot/efi
└─sdc2    8:34   1  29.3G  0 part   /
sdf       8:80   0 931.5G  0 disk
└─sdf1    8:81   0 931.5G  0 part
  └─md0   9:0    0   1.8T  0 raid10 /
sdg       8:96   0 931.5G  0 disk
└─sdg1    8:97   0 931.5G  0 part
  └─md0   9:0    0   1.8T  0 raid10 /
sdh       8:112  1  14.5G  0 disk	# this is matching the expected usb drive
└─sdh1    8:113  1  14.5G  0 part

user1@linux01:/$ udevadm info /dev/sdh
P: /devices/pci0000:00/0000:00:01.2/0000:12:00.0/usb1/1-8/1-8:1.0/host10/target10:0:0/10:0:0:0/block/sdh
N: sdh
L: 0
S: disk/by-path/pci-0000:12:00.0-usb-0:8:1.0-scsi-0:0:0:0
S: disk/by-id/usb-Verbatim_STORE_N_GO_7716151047687633054-0:0
E: DEVPATH=/devices/pci0000:00/0000:00:01.2/0000:12:00.0/usb1/1-8/1-8:1.0/host10/target10:0:0/10:0:0:0/block/sdh
E: DEVNAME=/dev/sdh
E: MINOR=112
E: USEC_INITIALIZED=4395690127950
E: SCSI_MODEL_ENC=STORE\x20N\x20GO\x20\x20\x20\x20\x20\x20
E: ID_VENDOR=Verbatim
E: ID_MODEL_ENC=STORE\x20N\x20GO\x20\x20\x20\x20\x20\x20
E: ID_TYPE=disk
E: ID_SERIAL=Verbatim_STORE_N_GO_7716151047687633054-0:0
E: ID_SERIAL_SHORT=7716151047687633054
E: ID_BUS=usb
E: ID_USB_DRIVER=usb-storage
E: ID_PATH=pci-0000:12:00.0-usb-0:8:1.0-scsi-0:0:0:0
E: ID_PATH_TAG=pci-0000_12_00_0-usb-0_8_1_0-scsi-0_0_0_0
E: DEVLINKS=/dev/disk/by-path/pci-0000:12:00.0-usb-0:8:1.0-scsi-0:0:0:0 /dev/disk/by-id/usb-Verbatim_STORE_N_GO_7716151047687633054-0:0
E: TAGS=:systemd:

# Create a custom rule to mount the usb-drive
sudo su
cat << EOF > /etc/udev/rules.d/10-usb-drive.rules
KERNEL=="sdh1", SUBSYSTEM=="block", SYMLINK="usb-drive"

# rescan drives and reactive rules
udevadm trigger
ls -l /dev | grep usb

# validate the auto detection
root@linux01:/# ls -l /dev | grep usb
lrwxrwxrwx  1 root root           3 Jan 12 03:30 usb-drive -> sdh

# test writing a file into the hard-link (expect to fail)
root@linuxbox:/media# touch /dev/usb-drive/test0.txt
touch: cannot touch '/dev/usb-drive/test0.txt': Not a directory

# Mounting a device
root@linuxbox:# mkdir /media/usb-drive
root@linuxbox:# mount /dev/usb-drive /media/usb-drive
root@linuxbox:# touch /media/usb-drive/test.txt
root@linuxbox:# ls /media/usb-drive/
'System Volume Information'   test.txt

# Partition Editor
fdisk /dev/sdh
m	# display help menu

g	# create gpt partitioning table
# Example
Command (m for help): g
Created a new GPT disklabel (GUID: DB913469-586B-3F48-9B11-6B2C1A57B04E).
The old dos signature will be removed by a write command.

n	# create new partition
# Example
Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-30433246, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-30433246, default 30433246):
Created a new partition 1 of type 'Linux filesystem' and of size 14.5 GiB.

q	# exit without saving changes
w	# write changes and exit

# Setup RAID
# use fdisk to create partitions as a recommended practice prior to setting up RAID
# create array
mdadm --create /dev/md0 --level=5 --raid-devices=4 /dev/sd{h,i,j,k}1
# check array
cat /proc/mdstat
# save existing config into config file for persistency
mdadm --detail --scan > /etc/adadm/adadm.conf

# Using parted
sudo parted /dev/sdh mklabel gpt
sudo parted -a opt /dev/sdh mkpart primary ext4 0% 100%	# Create primary partition and reserve the entire disk for it

# Creating file system on partitions
# Options:
# mkfs.[ext4,btrfs,msdos,xfs,cramfs,fat,minix,vfat]
mkfs.ext4 -L usb-drive /dev/sdh1	# create an ext4 file system
lsblk -f	# shows disks along with file systems

# Logical Volume Manager
 - Volume Group
 - Logical Volume
 - Physical Volume
pvdisplay	 # shows existing PV config
lvdisplay	 # shows existing LV config
pvcreate /dev/sdh /dev/sdi
vgcreate <groupname> /dev/sdh /dev/sdi
lvcreate -L 10G -N <lvname> <groupname>
mkfs.ext4 /dev/<groupname>/<lvname>
lvextend -L+10G /dev/<groupname>/<lvname>

# Mounting drives
mkdir -p /media/usb-drive
mount /dev/sdh1 /media/usb-drive
mount -a # reload mounts

# persist mounting on reboots
vi /etc/fstab
### add this line
LABEL=usb-drive /media/usb-drive ext4 defaults 0 0
UUID=<output from: ls /dev/sdh1> /media/usb-drive ext4 defaults 0 0
# reload automounts
sudo mount -av

# Quotas
# Enable quota on certain disks
vi /etc/fstab	# ensure that usrquota or grpquota is marked as options for certain volumes (e.g. /dev/sdb1)
sudo quotacheck -au	# generate quota checks file on all partitions indexing by usernames
sudo quotaon -a # turn on quota features
sudo edquota user2 # edit quota for user

# how to scan file system

# View current thresholds for 'Maximum mount count'
tune2fs -l /dev/sdh1

# set /etc/fstab to activate scanning (triggered by combination of max mount count and pass value)
# example server config to activate scanning
/dev/sdh1 /mnt/usb-drive ext4 defaults 0 2 # the last value representing pass number greater than 0, which means it will scan if mount count threshold has been surpassed
tune2fs -c 2 /dev/sdh1 # set file scan threshold at 2
# example laptop to disable scanning
tune2fs -c 2 /dev/sdh1 # set file scan threshold at -1

# how to blacklist a device
vi /etc/modprobe.d/blacklist.conf
# insert a sample line
blacklist <device-name> 

# modules
kernel=$(uname -r)
ls /lib/modules/$kernel/kernel/drivers/net # look for network modules
modprobe hamradio # insert module using the wrapper for insmod command with dependencies autoresolve
rmmod hamradio
depmod # update currently loaded modules' system map

# networking commands
ip route # check route table

# NIC bonding
# mode 0 = balance-rr (round-robin, requires switch support) 
# mode 4 = 802.3ad (advanced switch support)
# mode 6 = balance-alb (no need switch support)

# Ubuntu/Debian
vi /etc/netplan/00-installer-config.yaml
# edit the file
  renderer: networkd
      dhcp4: false
	  dhcp4: false
	  dhcp4: false
	    - enp37s0
		- enp37s1
	  addresses: []
	    mode: balance-alb
		addresses: []
  version: 2
### save file
cat /proc/net/bonding/bond0
netplan apply

# Redhat/Centos
vi /etc/sysconfig/network-scripts/ifconfig-bond0
# edit the master bond0 file
BONDING_OPTS="mode=6 miimon=100"
# edit the slave eno{49,50,51,52} files
vi /etc/sysconfig/network-scripts/ifconfig-eth0
# edit the file

# network config files
/etc/hosts	# local dns file
/etc/resolv.conf	# shows the dns servers list
/etc/nsswitch.conf	# shows more info about name resolutions

# Redhat network config
ls /etc/sysconfig/network-scripts

# Ubuntu/Debian network config
ls /etc/netplan
vi /etc/netplan/<config.file>
sudo netplan apply # make changes effective
nmtui # GUI version

# DNS resolutions
dig @
nslookup <host>

# Manual installation using tarballs
tar -zxvf program.tar.gz
cd program/
make install OR mv program /usr/local/bin

# Manual install using dpkg
sudo dpkg -i program.deb
sudo dpkg -r program

# Install using apt
ls /ect/apt/	# check for existing sources.list
# add ssl key
wget -qO https://URL | apt-key add -
apt-key list
# automatically adding ssl key
add-apt-respostory ppa:vendorname/appname
# hold currently installed package version
apt-mark hold kubeadm kubelet kubectl
# hold currently installed package version
apt-mark unhold kubeadm kubelet kubectl

# Install using yum (Yellow Dog manager)
yum install program
yum upgrade
# edit main yum config file
vi /etc/yum.conf
# add new repos
vi /etc/yum.repos.d/newrepo.repo
# installing new repo the easy way
yum install epel-release
# install version lock
yum -y install yum-versionlock
# lock a version
yum versionlock nginx
# unlock a version
yum versionlock delete nginx
# view current locks
yum versionlock nginx

# Install using dnf (Dandified YUM)
dnf search packagename
dnf install packagename
dnf remove packagename
sudo dnf upgrade --exclude=packagename
# edit config
vi /etc/dnf/dnf.conf
# lock currently installed package
sudo dnf versionlock add package
# unlock
sudo dnf versionlock delete package

Sample bash shell scripts

# Download firmware from Internet and recursively execute bin files
mkdir -p ~/firmware/r640;
cd ~/firmware/r640;
wget -ml1;
chmod +x ;
for i in .BIN;do ./$i -q;done

How to Search for Installed Application by Name in PowerShell

One can search using the known Vendor or application Name as illustrated below:

[testwindows]: PS C:\Users\user1\Documents> Get-WmiObject -Class Win32_Product | ?{$_.Name -like '*exporter*'}

IdentifyingNumber : {EDD0CDE3-4519-4C1A-9FB4-C8C067615698}
Name              : windows_exporter
Vendor            : prometheus-community
Version           : 0.20.0
Caption           : windows_exporter

[btestwindows]: PS C:\Users\user1\Documents> Get-WmiObject -Class Win32_Product | ?{$_.Vendor -like '*prometheus*'}

IdentifyingNumber : {EDD0CDE3-4519-4C1A-9FB4-C8C067615698}
Name              : windows_exporter
Vendor            : prometheus-community
Version           : 0.20.0
Caption           : windows_exporter

PowerShell: Create Registry Keys within Windows Localhost

# createRegKey.ps1

function createRegKey{
        $keyValue=(Get-ItemProperty -Path $regHive -Name $keyName -ErrorAction Stop).$keyName
        if($keyValue -ne $value){
            New-ItemProperty -Path $regHive -Name $keyName -Value $value -Type String -Force
            write-host "$regHive $keyName already has a value of $value"
    }catch [System.Management.Automation.ItemNotFoundException],[System.Management.Automation.PSArgumentException] {
        New-Item -Path $regHive -Force
        New-ItemProperty -Path $regHive -Name $keyName -Value $value -Force
        write-host "$regHive $keyName value has been set to $value"
    }catch {
        write-warning $_
        New-ItemProperty -Path $regHive -Name $keyName -Value $value -Type String -Force
        write-host "$regHive $keyName value has been set to $value"

$regKeys|%{createRegKey $_.hive $ $_.value}

Windows: How to Map Network Drive for All Users of a Local Machine

# Mapping file share using legacy commands (more effective than newer PowerShell equivalents in certain scenarios)
net use m: /delete
Set-Content "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\mountShares.bat" $textContent

How to Set PowerShell Window and Prompt Title or Label

Have you ever wondered about changing the boring PS C:\Windows\system32> whenever a new window is opened in PowerShell? You’re in luck by finding this quick note. Here’s how you’d do it:

# Set Window title to match current machine name
$host.UI.RawUI.WindowTitle="PS $env:computername $env:username"

# Set Window prompt to match current machine name
function prompt {"PS $env:computername $env:username> "}

# Set color of label
function prompt{
Write-Host ("PS $env:computername $env:username> ") -nonewline -foregroundcolor Yellow
return " "

Use DISM To Install Windows Features

# dismInstallFeatures.ps1

$featuresToInstall = ('FileAndStorage-Services','Storage-Services','Web-Server','Web-WebServer','Web-Common-Http','Web-Default-Doc','Web-Dir-Browsing','Web-Http-Errors',

# Remove any feature that is not available to prevent dism failures. MSMQ-Container for example is only available 
# on Windows 7 but not on Windows Server 2008 R2. 
$availableFeatures = dism /online /Get-Features
$featuresToRemove = @()
$featuresToInstall | % { if (-not ($availableFeatures | Select-String ('{0}$' -f $_) -Quiet)) { $featuresToRemove += $_} }
$featuresToInstall = Compare-Object -ReferenceObject $featuresToInstall -DifferenceObject $featuresToRemove | select -ExpandProperty InputObject

$dismParameter = @('/online', '/Enable-Feature', ($featuresToInstall | % { '/FeatureName:{0}' -f $_ }), '/NoRestart', '/all')
$output = dism @dismParameter

# throw an error if dism wasn't successful
if ($global:LastExitCode -ne 0){
    throw 'Error while installing Windows Features. {0}' -f ($output | Select-String '\.log$')
# dismCheckWindowsFeature.ps1

$featuresToCheck = ('RDS-RD-Server')
$availableFeatures = dism /online /Get-Features
$featuresToRemove = @()
$featuresToInstall | % { if (-not ($availableFeatures | Select-String ('{0}$' -f $_) -Quiet)) { $featuresToRemove += $_} }
$featuresToInstall = Compare-Object -ReferenceObject $featuresToInstall -DifferenceObject $featuresToRemove | select -ExpandProperty InputObject

$dismParameter = @('/online', '/Get-Features', ($featuresToCheck | % { '/FeatureName:{0}' -f $_ }), '/NoRestart', '/all')

$output = dism @dismParameter

# throw an error if dism wasn't successful
if ($global:LastExitCode -ne 0)
    throw 'Error while installing Windows Features. {0}' -f ($output | Select-String '\.log$')

dism /online /get-Features 'RDS-RD-Server'

How To Delete Virtual Machine in Unsupported Configuration Status

Possible Errors in VMM Console:

Error (20408)
VMM could not get the specified instance Msvm_VirtualSystemSettingData.InstanceID="Microsoft:1D78A299-C989-40FC-BC5C-B54934A126B7" of class Msvm_VirtualSystemSettingData on the server NODE002. The operation failed with error HRESULT 0x80004005 The WS-Management service cannot process the request. The service cannot find the resource identified by the resource URI and selectors.

Recommended Action
Ensure the provider is running, and then try the operation again.
Error (20411)
VMM could not invoke method ImportSystemDefinition on Msvm_VirtualSystemManagementService: Hyper-V Virtual System Management Service (Name = "vmms", CreationClassName = "Msvm_VirtualSystemManagementService", SystemCreationClassName = "Msvm_ComputerSystem", SystemName = "NODE002") on the server NODE002. Failed with error HRESULT 0x80338029 The WS-Management service cannot complete the operation within the time specified in OperationTimeout.

Recommended Action
Ensure the provider is running, and then try the operation again.

Warning (10655)
Hardware changes while cloning a Hyper-V virtual machine, VMware virtual machine, or stored virtual machine are not supported and were ignored.

Recommended Action
Make any hardware changes to the virtual machine after the cloning operation is complete.
Error (809)
VMM cannot remove the virtual machine because it is in the Unsupported Cluster Configuration state.

Recommended Action
Change the virtual machine's state, and then try the operation again.


# Resolution
Get-SCVirtualMachine $vmName|Remove-SCVirtualMachine -Force

Upgrade Virtual Hardware Version in VMM

The following script will upgrade all guest virtual machines from a lower version to the desired version:

# upgradevHardwareVersion.ps1

# User inputs

function updateVmVersion($vmNames,$desiredVersion='9.0',$vmmServer=$env:computername){
    foreach($vmName in $vmNames){
                $vm=get-scvirtualmachine $vmName -vmmServer $vmmServer
                if($vm.VirtualMachineState -eq 'Running' -and [version]$previousVersion -lt [version]$desiredVersion){
                    $null=stop-scvirtualmachine -vm $vm
                    $null=Update-SCVMVersion -vm $vm
                    $vm=start-scvirtualmachine -vm $vm
                    if($vm.status -eq 'Running'){
                        write-host "$vmName has been updated from version $previousVersion to $($vm.Version) and is now back online"
                        write-host "$vmName has been updated from version $previousVersion to $($vm.Version) but it's now offline"
                        return $previousVersion
                }elseif($vm.VirtualMachineState -eq 'PowerOff' -and [version]$previousVersion -lt [version]$desiredVersion){
                    $null=Update-SCVMVersion -vm $vm
                return $vm.Version
                write-warning $_
                return $previousVersion
    return $results

# Get the report
$vmsWithLowerVersions=get-scvirtualmachine|?{[version]$_.version -lt [version]$desiredVersion}
write-host "Processing list:`r`n$($vmsWithLowerVersions|select name,version|out-string)"
$filteredList=$vmsWithLowerVersions|?{$name=$_.Name;$null -eq $($excludeKeywords|?{$name -like "*$_*"})}
write-host "Filtered list:`r`n$($filteredList|select name,version|out-string)"
$inversedList=$vmsWithLowerVersions|?{$name=$_.Name;$null -ne $($excludeKeywords|?{$name -like "*$_*"})}
write-host "Inverted list:`r`n$($inversedList|select name,version|out-string)"

# Upgrade all VMs with lower versions
updateVmVersion $vmsWithLowerVersions.Name $desiredVersion $vmmServer

Upgrade a selected list of VMs


function updateVmVersion($vmNames,$desiredVersion='9.0',$vmmServer=$env:computername){
    foreach($vmName in $vmNames){
                $vm=get-scvirtualmachine $vmName -vmmServer $vmmServer
                if($vm.VirtualMachineState -eq 'Running' -and [version]$previousVersion -lt [version]$desiredVersion){
                    $null=stop-scvirtualmachine -vm $vm
                    $null=Update-SCVMVersion -vm $vm
                    $vm=start-scvirtualmachine -vm $vm
                    if($vm.status -eq 'Running'){
                        write-host "$vmName has been updated from version $previousVersion to $($vm.Version) and is now back online"
                        write-host "$vmName has been updated from version $previousVersion to $($vm.Version) but it's now offline"
                        return $previousVersion
                }elseif($vm.VirtualMachineState -eq 'PowerOff' -and [version]$previousVersion -lt [version]$desiredVersion){
                    $null=Update-SCVMVersion -vm $vm
                return $vm.Version
                write-warning $_
                return $previousVersion
    return $results

$vmnames=@($vmsToUpgrade -split "`n")|%{$_.Trim()}
write-warning "Please confirm that we're ready to have these virtual machines rebooted:`r`n$vmnames"
updateVmVersion $vmnames $desiredVersion $vmmServer

Simple version – upgrading only VMs that are offline


$vmnames=@($vmsToUpgrade -split "`n")|%{$_.Trim()}
foreach($vmName in $vmNames){
    $vm=get-scvirtualmachine $vmName -vmmServer $vmmServer
    if($vm.VirtualMachineState -eq 'PowerOff'){
            $null=Update-SCVMVersion -vm $vm
            write-host "$vmName virtual hardward has been upgraded from version $oldVersion to $newVersion"
            write-warning $_


PowerShell: Get Available RAM Slots

# getRamSlotsAvailable.ps1


function getRamSlotsAvailable{
    write-host "Computer name: $computerName"
    $slots = Get-WmiObject -Class "win32_PhysicalMemoryArray" -namespace "root\CIMV2" -computerName $computerName
    $ramModules = Get-WmiObject -Class "win32_PhysicalMemory" -namespace "root\CIMV2" -computerName $computerName
    write-host "Total slots: $slotsSum"
    write-host "Total RAM: $([math]::round($ramSum/1GB,2)) GB"
    Foreach ($module In $ramModules) {
        write-host "Memory Installed: $($module.DeviceLocator)"
        write-host "Memory Size: $($module.Capacity/1GB) GB"
    return $slotsSum

getRamSlotsAvailable $computername

# Sample output
# PS C:\Windows\system32> getRamSlotsAvailable $computername
# Computer name: TEST-SERVER
# Total slots: 24
# Total RAM: 256 GB
# Memory Installed: DIMM_A1
# Memory Size: 16 GB
# Memory Installed: DIMM_A2
# Memory Size: 16 GB
# Memory Installed: DIMM_A3
# Memory Size: 16 GB
# Memory Installed: DIMM_A4
# Memory Size: 16 GB
# Memory Installed: DIMM_A5
# Memory Size: 16 GB
# Memory Installed: DIMM_A6
# Memory Size: 16 GB
# Memory Installed: DIMM_A7
# Memory Size: 16 GB
# Memory Installed: DIMM_A8
# Memory Size: 16 GB
# Memory Installed: DIMM_B1
# Memory Size: 16 GB
# Memory Installed: DIMM_B2
# Memory Size: 16 GB
# Memory Installed: DIMM_B3
# Memory Size: 16 GB
# Memory Installed: DIMM_B4
# Memory Size: 16 GB
# Memory Installed: DIMM_B5
# Memory Size: 16 GB
# Memory Installed: DIMM_B6
# Memory Size: 16 GB
# Memory Installed: DIMM_B7
# Memory Size: 16 GB
# Memory Installed: DIMM_B8
# Memory Size: 16 GB

Use PowerShell to Get GeoLocation of a Computer’s Public IP

Method 1:

Invoke-RestMethod -Uri (''+(Invoke-WebRequest -uri "").Content)

Method 2:

function getIPGeolocation($ipAddress) {

$request = Invoke-RestMethod -Method Get -Uri "$ipAddress"

IP = $request.query
City = $
Country = $
Isp = $request.isp

$thisPublicIP=(Invoke-WebRequest -uri "").Content
getIPGeolocation $thisPublicIP

How to Upgrade Kubernetes Ingress Nginx Deployed via Helm

# How to upgrade ingress-nginx:
helm upgrade --reuse-values ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx

# Sample output of a failure scenario:

brucelee@k8-controller:~$ helm upgrade --reuse-values ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx
Error: UPGRADE FAILED: template: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml:52:24: executing "ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml" at <.Values.controller.admissionWebhooks.patchWebhookJob.resources>: nil pointer evaluating interface {}.resources


# How to force uninstall ingress-nginx and re-install it:
helm delete ingress-nginx -n ingress-nginx
# Delete a pod stuck in terminating status
kubectl delete pod $podName --grace-period=0 --force --namespace ingress-nginx
# Pull most updated versions of applications from source
helm repo update
# Export helm's ingress-nginx yaml config file
helm show values ingress-nginx/ingress-nginx > ingress-nginx.yaml
# edit the values
vim ingress-nginx.yaml

# change these three (3) values

  hostNetwork: true # change this value to true

    enabled: true # set this value to true

  kind: DaemonSet # modify this from Deployment to DaemonSet
# Reinstall ingress-nginx using the edited yaml file:
helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --values ingress-nginx.yaml
# Check results:
k -n ingress-nginx get all

How To Add or Remove a Path in Windows Environmental Paths

There are 2 functions to Add and Remove, at your convenience:

# addEnvironmentalPath.ps1


function addEnvironmentalPath($pathToAdd){
    $registryEnvironment='Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment'
    $pathToAdd=if($pathToAdd -match '\\$'){$pathToAdd -replace '.$'}else{$pathToAdd}
        $originalPaths=(Get-ItemProperty -Path $registryEnvironment -Name PATH).path
        $pathsArray=$originalPaths -split ';'|?{$_.trim() -ne ''}|%{if($_ -match '\\$'){$_ -replace '.$'}else{$_}}|Sort-Object -Unique
        if($pathToAdd -in $pathsArray){
            write-host "$pathToAdd is already included in the environmental paths: '$originalPaths'"
            return $true
            $newPaths=$newPathsArray -join ';'
            Set-ItemProperty -Path $registryEnvironment -Name PATH -Value $newPaths
            $newRegistryEnvironment=(Get-ItemProperty -Path $registryEnvironment -Name PATH).Path
            write-host "Environmental paths have been changed:`r`nFrom: $originalPaths`r`nTo: $newPaths"
            return $true
        write-warning $_
        return $false

function removeEnvironmentalPath($pathToRemove){
    $registryEnvironment='Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment'
    $pathToRemove=if($pathToRemove -match '\\$'){$pathToRemove -replace '.$'}else{$pathToRemove}
        $originalPaths=(Get-ItemProperty -Path $registryEnvironment -Name PATH).path
        $pathsArray=$originalPaths -split ';'|?{$_.trim() -ne ''}|%{if($_ -match '\\$'){$_ -replace '.$'}else{$_}}|Sort-Object -Unique
        if($pathToRemove -notin $pathsArray){
            write-host "$pathToRemove does not exist in the environmental paths: '$originalPaths'"
            return $true
            $newPaths=$newPathsArrayList -join ';'
            Set-ItemProperty -Path $registryEnvironment -Name PATH -Value $newPaths
            $newRegistryEnvironment=(Get-ItemProperty -Path $registryEnvironment -Name PATH).Path
            write-host "Environmental paths have been changed:`r`nFrom: $originalPaths`r`nTo: $newPaths"
            return $true            
        write-warning $_
        return $false

addEnvironmentalPath $pathToAdd
removeEnvironmentalPath $pathToRemove

PowerShell: Find Windows RDS Roles and Their Licensing Servers

# Get TS Licensing Servers (Enterprise or AD Registered)
$termLicenseServers=Get-ADGroupMember -Identity "Terminal Server License Servers"
$termLicenseServers|Select-Object -Property @{label='computername';expression={[regex]::match($_.DistinguishedName,'([\w\d-]+)(?=,OU=)').Value}}

# Get TS Connection Points with Licensing Role Installed (may or may not be registered on the domain)
$termServers=Get-ADObject -Filter {objectClass -eq 'serviceConnectionPoint' -and Name -eq 'TermServLicensing'}
$termServers|Select-Object -Property @{label='computername';expression={[regex]::match($_.DistinguishedName,'([\w\d-]+)(?=,OU=)').Value}}

# Check localhost for TS Licensing Servers
$tsSettings=gwmi -namespace "Root/CIMV2/TerminalServices" Win32_TerminalServiceSetting 

# Find RDS Servers and their Licensing Configs
$servers=Get-ADComputer -Filter {OperatingSystem -Like '*Windows Server*' -and Enabled -eq $true}
write-host "There are $serversCount servers to check..."
foreach($server in $servers.DNSHostName){
	write-host "$initCount of $serversCount`: $server"
	$rdsRole=try{Get-WindowsFeature RDS-RD-Server -ComputerName $server -EA Ignore}catch{$null}	
		$rdsRoleInstalled=$rdsRole.InstallState -eq 'Installed'
			$tsSettings=gwmi -namespace "Root/CIMV2/TerminalServices" Win32_TerminalServiceSetting -computername $server
			'not configured'
		write-host "$server has RDS-RD-Server role installed with licensing server(s) $rdsLicenseServer"
			write-host "$server doesn't have RDS-RD-Server role installed"
		write-warning "$env:computername cannot connect to $server"

$results|%{write-host "$($_.computername)`: $($_.rdsLicenseServer) | $($_.LicensingType)"}
$noResults|%{write-host "$($_.computername)"}
Log Name: System
Source: Microsoft-Windows-DNS-Client
Date: 8/1/2018 2:11:47 AM
Event ID: 8019
Task Category: (1028)
Level: Warning
The system failed to register host (A or AAAA) resource records (RRs) for network adapter
with settings:

Adapter Name : {2F85D40D-4BEB}
Host Name : testwindows
Primary Domain Suffix :
DNS server list : x.x.x.x
Sent update to server : <?>
IP Address(es) : y.y.y.y

The reason the system could not register these RRs was because of a security related problem. The cause of this could be (a) your computer does not have permissions to register and update the specific DNS domain name set for this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS server during the processing of the update request.

You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig /registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems administrator. See event details for specific error code information.
Event Xml:
<Event xmlns="">
<Provider Name="Microsoft-Windows-DNS-Client" Guid="{1C95126E}" />
<TimeCreated SystemTime="2018-08-01T06:11:47.524646900Z" />
<Correlation />
<Execution ProcessID="484" ThreadID="2104" />
<Security UserID="S-1-5-20" />
<Data Name="AdapterName">{2F85D40D}</Data>
<Data Name="HostName">dbmon01l-ops-23</Data>
<Data Name="AdapterSuffixName"></Data>
<Data Name="DnsServerList"> x.x.x.x</Data>
<Data Name="Sent UpdateServer">&lt;?&gt;</Data>
<Data Name="Ipaddress">y.y.y.y</Data>
<Data Name="ErrorCode">9017</Data>

List available NIC’s to pick the correct one

[testwindows]: PS C:\Users\brucelee\Documents> Get-NetAdapter

Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
---- -------------------- ------- ------ ---------- ---------
Ethernet Microsoft Hyper-V Network Adapter 2 Up AA-6C-B8-00-00-00 20 Gbps
Ethernet 2 Cisco AnyConnect Secure Mobility Cli... 6 Not Present 00-05-00-00-00-00 0 bps

Remove the GUI check mark next to ‘Register this connection’s addresses with DNS’
Advanced TCP/IP Settings

[testwindows]: PS C:\Users\brucelee\Documents> Get-NetAdapter Ethernet|Set-DNSClient -RegisterThisConnectionsAddress $F

Verify the result:

[testwindows]: PS C:\Users\brucelee\Documents> Get-NetAdapter Ethernet | Get-DNSClient

InterfaceAlias Interface ConnectionSpecificSuffix ConnectionSpecificSuffix RegisterThisConn UseSuffixWhen
Index SearchList ectionsAddress Registering
-------------- --------- ------------------------ ------------------------ ---------------- -------------
Ethernet 2 {} False True

How to Install Windows Dot Net 3.5 & 4.5

Run these commands to check dot net 3.5:

PS C:\Windows\system32> import-module servermanager
PS C:\Windows\system32> get-windowsfeature web-asp-net

Display Name Name Install State
------------ ---- -------------
[ ] ASP.NET 3.5 Web-Asp-Net Available

Install ASP.NET 3.5:

PS C:\Windows\system32> install-windowsfeature web-asp-net 
Success Restart Needed Exit Code Feature Result
------- -------------- --------- --------------
True No Success {ASP.NET 4.8, Application Development, ASP...

Run this command to check dot net 4.5:

PS C:\Windows\system32> get-windowsfeature Net-Framework-45-Core

Display Name Name Install State
------------ ---- -------------
[X] .NET Framework 4.8 NET-Framework-45-Core Installed

If necessary, install DotNet 4.5:

add-windowsfeature Net-Framework-45-Core

PowerShell: Install App Using MSI on Remote Computers Via WinRM

# installMSiRemoteComputers.ps1
# version 0.0.1


function installMsiOnRemoteComputers($computernames,$msiFile,$appName,$desiredVersion,$maxWaitSeconds){
    function installMsiOnRemoteComputer{
        function translateLocalPathToSmbPath($computername,$localPath,$testFileName){
            $testPath=join-path "\\$computername\$adminDriveLetter`$" "$partialPath"
            if(!(test-path $testPath)){
                    New-Item -Path $testPath -ItemType "directory" -force
                    write-warning "Unable to create $testPath"
                    return $false
                $null=New-Item -Path $testPath -Name $testFileName -ItemType "file" -force
                Remove-Item "$testPath\$testFileName" -force
                return $testPath
                write-warning "Unable to read or write to $testPath"
                return $false
        $msiLocalFilePath=join-path $destinationLocalTempFolder $(split-path $msiFile -leaf)
        foreach ($computername in $computernames){
            $translatedDestination=translateLocalPathToSmbPath $computername $destinationLocalTempFolder $testFileName
                copy-item $msiFile $translatedDestination
                write-warning "Unable to copy $msiFile to $translatedDestination"
            $psSession=new-psSession $computername
            if($psSession.State -eq 'Opened'){
                $result=invoke-command -session $pssession -scriptblock{
                    $file=gi $filePath
                    $DataStamp = get-date -Format yyyyMMddTHHmmss
                    $logFile ="C:\" + '{0}-{1}.log' -f $,$DataStamp
                    $MSIArguments = @(
                        ('"{0}"' -f $file.fullname)
                        [diagnostics.process]::start("msiexec.exe", $MSIArguments).WaitForExit()
                        write-host "MSIEXEC has been called for file $filePath on $env:computername"
                        return $true
                        write-warning $_
                        return $false
                } -Args $msiLocalFilePath
                # Note Error:
                # Resolved by not using -wait switch and calling [diagnostics.process] instead of Start-Process "msiexec.exe"
                # Although, this error would still being thrown with the [diagnostics.process] result of success
                # Processing data for a remote command failed with the following error message: The I/O operation has been aborted
                # because of either a thread exit or an application request. For more information, see the about_Remote_Troubleshooting
                # Help topic.
                #     + CategoryInfo          : OperationStopped: (:String) [], PSRemotingTransportException
                #     + FullyQualifiedErrorId : JobFailure
                #     + PSComputerName        : 
                remove-psSession $psSession
                write-warning "Unable to connect to $computername"
                $results+=[hashtable]@{$computername="Unable to connect to $computername"}
        return $results
    foreach($computername in $computernames){
            installMsiOnRemoteComputer $computername $msiFile
            write-host "Now waiting up to $maxWaitSeconds seconds before checking on the install result"
                start-sleep -seconds 5
                $appVersionPassed=invoke-command -computername $computername {
                    $matchedApp=Get-WmiObject -Class Win32_Product -Filter "Name='$appName'"
                    if($matchedApp.Version -eq $desiredVersion){
                        return $true
                        return $false
                } -Args $appName,$desiredVersion
                    write-host "$appName $desiredVersion installed on $computername successfully"
                    $results+=[hashtable]@{$computername='$appName $desiredVersion installed'}                            
                $exitCondition=$timer.elapsed.totalseconds -ge $maxWaitSeconds
            }until($appVersionPassed -or $exitCondition)
                    write-host "$appName $desiredVersion has NOT been installed successfully on $computername"
                    $results+=[hashtable]@{$computername="$appName $desiredVersion NOT installed"}
            write-warning $_
            exit 1   
    return $results

installMsiOnRemoteComputers $computernames $thisMsiFile $appName $desiredVersion $maxWaitSeconds