Friday 30 November 2018

Network profile reset

The following PowerShell code is designed to reset both the local and network profile (on any number of PCs). Without PowerShell such a task is cumbersome as you need to connect to the C: drive of a PC, navigate to the 'Users' folder, check said user is logged off before renaming/deleting this folder, clear the relevant Registry key for that user ...... repeat this for each PC. Then connect to your network profile share and rename/delete the users folder.

The tool below can do all of this from the PowerShell console within a few keystrokes. It can ultimately be incorporated as a module too.

function Invoke-ProfileReset {
Removes network & local user profile.
Invoke-ProfileReset deletes the network profile of a given user.
It also renames the local user profile on a given PC.
Username of the profile the remove.
.PARAMETER ComputerName
Name of PC(s) to remove local user profile from.

Saturday 24 November 2018

Sigcheck a user profile

The following PowerShell code was built for a malware scanning module. It uses the Microsoft tool Sigcheck to scan for .exe files in a users profile, checks the results with VirusTotal and logs them. It utilises a .csv file as a whitelist of trusted Publishers that I created for omission to reduce the number of results. The code implements a Try/Catch protocol to test certain parameters before proceeding, aiding in error logging should any issues occur prior to scanning. The tool can ultimately be incorporated as a module so you can call it straight from a PowerShell console.

function Get-SigcheckUserProfile {
Performs a Sysinternals Sigcheck scan on a user profile.
Get-SigcheckUserProfile uses the Sysinternals tool 'Sigcheck' on
a username to scan their profile and filter out results
from known-Publishers regarded as safe.
Username of the profile to scan.
Path of the 'Valid Sigcheck Publishers.csv' file to filter out known-Signers.
Defaults to current Powershell directory.

Friday 23 November 2018

Registry wildcard search match itemproperty

The following PowerShell code is part of a larger App Deployment Toolkit for troubleshooting installation problems with Adobe Reader. The issue faced was a '1612' CCM error when trying to upgrade to the latest version. A number of PCs were displaying errors in their logs that the source file for the previous version could not be located. Troubleshooting led to Registry entries that were pointing at CCM cache folders that no longer existed. Recreating these folders and placing the relevant .msi in there allowed for a successful upgrade.

The script searches through the Installer keys of the Registry looking for Adobe Reader, it then gets the property value that identifies the CCM cache folder last used and, if it does not exist, create it and copy the .msi files into it. Finally, initiate the upgrade again.

#Checks success value of previous code and only initiates if a '1612' error is returned
If (($ReturnCode3.ExitCode -eq '1612') -or ($ReturnCode4.ExitCode -eq '1612')) {

    Write-Log 'Install Attempt 2 has failed'

Thursday 15 November 2018

Change laptop power settings

The following PowerShell code was deployed to change the power settings of a number of classroom laptops after they had been rebuilt.

#Turn off sleep
powercfg.exe -change -standby-timeout-ac 0
Write-Host 'Success - turned off sleep' -ForegroundColor Yellow

#Hibernate after 4 hours
powercfg.exe -change -hibernate-timeout-ac 240
Write-Host 'Success - Hibernate to 4 hours' -ForegroundColor Yellow

Wednesday 14 November 2018

Remove folder if empty

The following PowerShell code is part of a larger App Deployment Toolkit for uninstalling an application. As programs are usually organised into department-specific folders on the Start Menu, it is necessary to delete them during the uninstall process, but taking into account that other programs may have shortcuts in there too (hence their scripts also have this uninstall snippet). It performs a count of the objects inside the folder to determine if it can be removed.

#Get any items within the 'Maths & Stats' folder and count them
If ((Get-ChildItem -Path "$envProgramData\Microsoft\Windows\Start Menu\Programs\Maths & Stats").count -eq 0) {

Tuesday 13 November 2018

IF Version AND Service

The following PowerShell code was used to run the updater for a specific version of E-Prime where its 'hasplms' Service had stopped running. By querying the .exe file in the installation folder it was possible to find the product version which could then be compared against.

#Create a variable of the path to the file
$EPrimePath = "$envProgramFilesX86\PST\E-Prime 2.0\Program\E-Studio.exe"
#If the file exists 
If (Test-Path -Path $EPrimePath) {

       #Create a variable of the 'ProductVersionRaw' attribute, as 'ProductVersion' on its own contains commas and spaces in this instance

Monday 12 November 2018

Create a Scheduled Task

The following PowerShell code was used to create a Scheduled Task for an application called Stata which needed to run an update file in its install directory each week. The snippet is part of a larger installation script.

#Create an Action to run PowerShell and feed into it a specific file
$action = New-ScheduledTaskAction -Execute "$envSystem32Directory\WindowsPowerShell\v1.0\powershell.exe" -Argument "-File `"C:\Program Files (x86)\Stata15\run-update.ps1`""

#Create a Trigger for when the task should run
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek 'Monday' -At '9am'

Sunday 11 November 2018

Do ... While command

The following PowerShell code is designed to be used as part of a larger script. My experience of Do ... While has typically been with installing/uninstalling applications where a script has exited before certain Processes have finished. This snippet creates a 10 second delay if the specified Process is found to be still running.

#A variable with the name of the Process is created
$ProcessName = "name_here"

Do {
    #Inside the 'Do' we have the action that should be taken if the Process is detected (so Sleep in this instance)
    Start-Sleep -Seconds 10

Saturday 10 November 2018

Launch a number of programs

The following PowerShell code very simply opens a number of programs when ran. I created this to speed up weekly restarts of my PC where I always had core applications that I used. Just simply add the relevant .exe location as required and the 'Start-Sleep' is there as a precaution to add a slight pause between each one opening. Launching this as an Administrator helped to avoid entering my credentials repeatedly.

Start 'C:\Program Files (x86)\VMware\VMware Workstation\vmware.exe' | Start-Sleep -Seconds 2
Start 'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\Microsoft.ConfigurationManagement.exe' | Start-Sleep -Seconds 2
Start 'C:\Program Files\Client Center for Configuration Manager\SCCMCliCtrWPF.exe' | Start-Sleep -Seconds 2
Start 'C:\Program Files\Saladin\bin\saladin.exe' | Start-Sleep -Seconds 2
Start 'C:\Windows\System32\dsa.msc' | Start-Sleep -Seconds 2
Start 'C:\Windows\regedit.exe' | Start-Sleep -Seconds 2
Start 'C:\Windows\System32\cmd.exe'

Launch a number of programs.ps1

Friday 9 November 2018

Copy file into folder if not exist

The following PowerShell code was my first attempt at automating the copying of files to a large number of PCs (simplified to a single file for the purpose of this example). The destination folder already existed and contained a number of other files, hence the need to check the source file did not exist before copying. The results are additionally outputted to a log file as 100+ PCs were queried and any that failed needed to be followed-up.

Improved version.

#Text file of PCs to query
$targetPCs = Get-Content "C:\User Files\LabVIEW\LabVIEWPCs.txt"

#Location on remote PC to copy file to
$targetdirectory = "C$\PTL\YR1 FOUNDATION LAB\"

#Location on my PC where file exists
$sourcedirectory = "C:\User Files\LabVIEW\Files\*"
$file1 = "2017-18_Y1_Lab1_FoundationElectronics_2.exe"

#Variable to later output a log of results
$output =

Thursday 8 November 2018

Bulk folder creation from spreadsheet

The following PowerShell code was developed to bulk create student folders at the start of term for individual departments. By providing a .csv file a folder can be created for each student using a naming convention derived from the column headings (a convention unique to each department).
Snippet of student_folder.csv data (anonymised)
#File location of .csv
$csvPath = "C:\User Files\student_folder.csv"

#Import .csv into script
$csv = Import-CSV $csvPath

Wednesday 7 November 2018

Bulk combine content of files

The following PowerShell code was developed to copy the content of multiple .xml files and combine them into a single .txt file. At the time this was for a number of EndNote references which needed to be imported into the application.

#Looks for a folder called 'XML' in current working location (or PowerShell directory). Pipes this through to filter .xml files only, then pipes this again to get the raw file content (keeps any white space within the file).
$XMLFolder = Get-ChildItem -Path ((Get-Location).Path + '\XMLs') | Where-Object { $_.Extension -match ".xml" } | Get-Content -Raw

#Check a combined file does not already exist (this was to prevent a user from overriding anything they already had). If file does not exist then create it (hiding 'New-Item' output via 'Out-Null' to simply avoid clogging the console window).
If (-Not(Test-Path ($CombinedFile = ((Get-Location).Path + '\Combined.txt')))) {
    New-Item -ItemType File -Path "$CombinedFile" | Out-Null

Saturday 3 November 2018

Bulk check for a Service

The following PowerShell code was developed to get the status of a specific Service on a list of PCs. It was used to diagnose how many PCs with a piece of licensing software had become inactive - a task requiring bulk automation.

#The script requires a text file containing the names of the PCs to query. It will work through each one in turn
ForEach ($Computer in Get-Content 'Computers.txt') {

    #A list of Services for the PC are acquired, then piped through to specifically find the one that equals the value 'ServiceName'
    If (Get-Service -ComputerName $Computer | Where-Object {$_.Name -eq 'ServiceName'}) {

        #Output the results to the PowerShell console (with a ForegroundColor to help. Also displays the name of the current PC from the input text file
        Write-Host "$Computer service found" -ForegroundColor Green