major update
This commit is contained in:
@@ -1,32 +0,0 @@
|
|||||||
#Requires -Version 3.0
|
|
||||||
|
|
||||||
param([string]$User)
|
|
||||||
|
|
||||||
## Install ExchangeOnlineManagement module if it doesn't already exist
|
|
||||||
If ( !(Get-Module -ListAvailable -Name ExchangeOnlineManagement) )
|
|
||||||
{
|
|
||||||
Try { Install-Module -Name ExchangeOnlineManagement }
|
|
||||||
Catch { Write-Output $_.Exception.Message ; Exit }
|
|
||||||
}
|
|
||||||
Import-Module ExchangeOnlineManagement
|
|
||||||
|
|
||||||
Connect-ExchangeOnline -UserPrincipalName $User -ShowProgress $true
|
|
||||||
|
|
||||||
|
|
||||||
#$Groups = Get-UnifiedGroup -ResultSize Unlimited
|
|
||||||
#$Groups | ForEach-Object {
|
|
||||||
# $group = Get-UnifiedGroupLinks -Identity $_.Name -LinkType Members -ResultSize Unlimited
|
|
||||||
# $group | ForEach-Object {
|
|
||||||
# New-Object -TypeName PSObject -Property @{
|
|
||||||
# Group = $group.DisplayName
|
|
||||||
# Member = $_.Name
|
|
||||||
# EmailAddress = $_.PrimarySMTPAddress
|
|
||||||
# RecipientType= $_.RecipientType
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
#} | Export-CSV “${Env:UserProfile}\Desktop\group-export.csv" -NoTypeInformation -Encoding UTF8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Disconnect-ExchangeOnline
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
## Stop a process
|
|
||||||
Function End-Process
|
|
||||||
{
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)][string[]]$Name,
|
|
||||||
[Parameter(Mandatory=$false)][switch]$Match=$false,
|
|
||||||
[Parameter(Mandatory=$false)][switch]$Force
|
|
||||||
)
|
|
||||||
ForEach ( $item in $Name ) {
|
|
||||||
$process = Get-Process -Name $item -ErrorAction SilentlyContinue
|
|
||||||
If ( !($process) ) {
|
|
||||||
LogMsg "Cannot find the process '${item}'"
|
|
||||||
If ( $Match ) {
|
|
||||||
LogMsg "Attempting to match '${item}' to all running process names"
|
|
||||||
ForEach ( $proc in ((Get-Process | Where { $_.Name -match $item }).Name) ) {
|
|
||||||
If ( $Force ) { End-Process -Name $proc -Force } Else { End-Process -Name $proc }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
$name = $process.Name
|
|
||||||
If ( $Force ) {
|
|
||||||
LogMsg "Forcefully stopping '${name}' process"
|
|
||||||
Stop-Process $process -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
LogMsg "Attempting to gracefully close '${name}' process"
|
|
||||||
$process.CloseMainWindow() | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
#Requires -Version 3.0
|
|
||||||
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
This script will mount an ISO file and share it on the network.
|
|
||||||
.DESCRIPTION
|
|
||||||
The ISO file can be a local path or fetched from a URL. The share this script creates will allow 'Everyone' read-only access.
|
|
||||||
.PARAMETER ShareName
|
|
||||||
This is the name of the Windows share that will be created.
|
|
||||||
.PARAMETER ISOPath
|
|
||||||
The full absolute path to the ISO. This can be a local path or a URL.
|
|
||||||
.PARAMETER NoShare
|
|
||||||
Will prevent the script from creating a network share. It will return only the drive letter for the mounted ISO file.
|
|
||||||
.PARAMETER Persist
|
|
||||||
Will cause the ISO to remain mounted even after rebooting the endpoint.
|
|
||||||
.PARAMETER Redownload
|
|
||||||
If -ISOPath is a URL, this parameter will delete an existing ISO file with the same name and download a fresh copy.
|
|
||||||
.PARAMETER Remove
|
|
||||||
Will remove the network share, and dismount the ISO file. This will not delete the ISO file.
|
|
||||||
.INPUTS
|
|
||||||
None. This script does not accept pipeline input.
|
|
||||||
.OUTPUTS
|
|
||||||
This script will output only a string containing the status of the shared ISO file.
|
|
||||||
.EXAMPLE
|
|
||||||
.\Create-ISOShare.ps1 -ShareName 'Win10Setup' -ISOPath 'D:\path\to\windows_10_setup.iso'
|
|
||||||
.EXAMPLE
|
|
||||||
.\Create-ISOShare.ps1 -ShareName 'Win10Setup' -ISOPath 'D:\path\to\windows_10_setup.iso' -Remove
|
|
||||||
.EXAMPLE
|
|
||||||
.\Create-ISOShare.ps1 -ShareName 'Win10Setup' -ISOPath 'https://hosted.net/path/to/windows_10_setup.iso'
|
|
||||||
.EXAMPLE
|
|
||||||
.\Create-ISOShare.ps1 -ISOPath 'https://hosted.net/path/to/windows_10_setup.iso' -NoShare
|
|
||||||
.NOTES
|
|
||||||
This script requires an administrative token to run properly.
|
|
||||||
.LINK
|
|
||||||
https://www.microsoft.com/en-us/software-download/windows10
|
|
||||||
#>
|
|
||||||
|
|
||||||
param(
|
|
||||||
[string]$ShareName,
|
|
||||||
[string]$ISOPath,
|
|
||||||
[switch]$NoShare,
|
|
||||||
[switch]$Persist=$false,
|
|
||||||
[switch]$Redownload,
|
|
||||||
[switch]$Remove
|
|
||||||
)
|
|
||||||
|
|
||||||
## Set the download directory for downloaded ISO file
|
|
||||||
## Note: This is only needed if a URL is passed to -ISOPath
|
|
||||||
$DownloadDirectory = $Env:SYSTEMDRIVE
|
|
||||||
|
|
||||||
## Download the ISO if a URL is specified
|
|
||||||
If ( $ISOPath.StartsWith('http') )
|
|
||||||
{
|
|
||||||
## Get the URL into its own variable
|
|
||||||
$DownloadURL = $ISOPath
|
|
||||||
|
|
||||||
## Get the file name from the URL
|
|
||||||
$filename = Split-Path -Path $DownloadURL -Leaf
|
|
||||||
|
|
||||||
## Set the path to the soon-to-be-downloaded ISO file
|
|
||||||
$ISOPath = "${DownloadDirectory}\${filename}"
|
|
||||||
|
|
||||||
## If $Redownload is specified, delete the ISO so we can redownload it
|
|
||||||
If ( ($Redownload) -and (Test-Path $ISOPath) ) { Remove-Item $ISOPath -Force }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Function to remove the share and dismount the ISO
|
|
||||||
Function Remove-ISOShare
|
|
||||||
{
|
|
||||||
## Remove the share
|
|
||||||
Remove-SMBShare -Name $ShareName -Force -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
## Dismount the ISO file
|
|
||||||
If ( Test-Path $ISOPath ) { Dismount-DiskImage -ImagePath $ISOPath -StorageType ISO | Out-Null }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Just remove the share and dismount the ISO if $Remove is specified
|
|
||||||
If ( $Remove ) { Remove-ISOShare }
|
|
||||||
|
|
||||||
## If $Remove is not specified, mount the ISO and create a network share
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
## If $DownloadURL exists and the ISO doesn't, download it
|
|
||||||
If ( ($DownloadURL) -and (!(Test-Path $ISOPath)) )
|
|
||||||
{
|
|
||||||
(New-Object System.Net.WebClient).DownloadFile($DownloadURL, $ISOPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
## Make sure we remove the share and mounted ISO, since both might already exist
|
|
||||||
Remove-ISOShare
|
|
||||||
|
|
||||||
## Mount the ISO and get the drive letter
|
|
||||||
$MountResult = Mount-DiskImage -ImagePath $ISOPath -StorageType ISO -Access ReadOnly -PassThru
|
|
||||||
$DriveLetter = ($MountResult | Get-Volume).DriveLetter
|
|
||||||
|
|
||||||
## Create network share
|
|
||||||
If (! ($NoShare) )
|
|
||||||
{
|
|
||||||
New-SMBShare -Name $ShareName -Path "${DriveLetter}:\" -ContinuouslyAvailable:$Persist -ReadAccess 'Everyone' | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
## Get the share path (or local path if it isn't shared)
|
|
||||||
If ( $NoShare ) { $SharePath = "${DriveLetter}:\" }
|
|
||||||
Else { $SharePath = "\\${Env:COMPUTERNAME}\${ShareName}" }
|
|
||||||
If ( Test-Path $SharePath )
|
|
||||||
{
|
|
||||||
## Return the full share path
|
|
||||||
Write-Output "ISO Share Path:`n`r${SharePath}"
|
|
||||||
|
|
||||||
## Return the full command to upgrade Windows 10 using this share
|
|
||||||
Write-Output "Windows 10 upgrade command:`n`r${SharePath}\setup.exe /auto upgrade /dynamicupdate disable /showoobe none /quiet"
|
|
||||||
|
|
||||||
} Else { Write-Output "ISO could not be shared." }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
rem Print a quick help message if nothing is passed to this script
|
|
||||||
if "%~1"=="" (
|
|
||||||
set SCRIPT=%~0
|
|
||||||
echo Create local administrator user account
|
|
||||||
echo.
|
|
||||||
echo Usage:
|
|
||||||
echo %SCRIPT% -u [username] -p [password] -n [display name]
|
|
||||||
echo.
|
|
||||||
echo Example:
|
|
||||||
echo %SCRIPT% -u myadmin -p p@ssw0rd -n "My Admin"
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
rem Get the params passed in on the command line
|
|
||||||
:parse
|
|
||||||
if "%~1"=="" goto endparse
|
|
||||||
if "%~1"=="-u" set USER=%2
|
|
||||||
if "%~1"=="-p" set PASS=%2
|
|
||||||
if "%~1"=="-n" set NAME=%2
|
|
||||||
shift
|
|
||||||
shift
|
|
||||||
goto parse
|
|
||||||
:endparse
|
|
||||||
|
|
||||||
rem Make sure we don't run this on a domain controller
|
|
||||||
wmic os get producttype | find "2" 1>nul 2>nul && goto domain-controller
|
|
||||||
|
|
||||||
rem Make sure the specified user doesn't already exist
|
|
||||||
net user | find /i "%USER%" >nul || goto create-admin
|
|
||||||
goto reset-password
|
|
||||||
|
|
||||||
rem Create a new user with the specified name and password
|
|
||||||
:create-admin
|
|
||||||
net user %USER% %PASS% /add /fullname:"%NAME%" /active:yes /expires:never /passwordreq:yes /times:all
|
|
||||||
goto make-admin
|
|
||||||
|
|
||||||
rem If the specified user already exists, reset it's password
|
|
||||||
:reset-password
|
|
||||||
net user %USER% %PASS% /fullname:"%NAME%" /active:yes /expires:never /passwordreq:yes /times:all
|
|
||||||
|
|
||||||
rem Add the specified user to the local Administrators group if it isn't already a member
|
|
||||||
rem Note: if you're using Restricted Groups in an Active Directory GPO, this change may be overwritten at the next policy application
|
|
||||||
net localgroup Administrators | find /i "%USER%" >nul || goto make-admin
|
|
||||||
goto remove-logon
|
|
||||||
:make-admin
|
|
||||||
net localgroup Administrators %USER% /add
|
|
||||||
|
|
||||||
rem Remove user from logon screen
|
|
||||||
:remove-logon
|
|
||||||
if exist "%ProgramFiles(x86)%" (
|
|
||||||
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" /v "%USER%" /t REG_DWORD /d 0 /f /reg:64 >nul
|
|
||||||
goto finish-remove-logon
|
|
||||||
)
|
|
||||||
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" /v "%USER%" /t REG_DWORD /d 0 /f >nul
|
|
||||||
:finish-remove-logon
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:domain-controller
|
|
||||||
rem This computer is a domain controller. The local %USER% account cannot be created.
|
|
||||||
|
|
||||||
:end
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
## Set the MSP name and environment variable
|
|
||||||
$MSPName = "Emberkom"
|
|
||||||
|
|
||||||
## Set the name of the module to deploy
|
|
||||||
$ModuleName = "PSModule"
|
|
||||||
|
|
||||||
## Define base URL for downloading module file
|
|
||||||
$ModuleURL = "https://dev.emberkom.com/emberkom/management-scripts/raw/branch/master/${ModuleName}/${ModuleName}.psm1"
|
|
||||||
|
|
||||||
## Setup the MSP management directories
|
|
||||||
If ( Test-Path ${Env:ProgramData} )
|
|
||||||
{ $MSPRoot = "${Env:ProgramData}\${MSPName}" } Else { $MSPRoot = "${Env:SystemDrive}\${MSPName}" }
|
|
||||||
$MSPScripts = "${MSPRoot}\Scripts"
|
|
||||||
$MSPTools = "${MSPRoot}\Tools"
|
|
||||||
$MSPLogs = "${MSPRoot}\Logs"
|
|
||||||
|
|
||||||
## Set the path to this module and make the directory for it
|
|
||||||
$ModulePath = "${MSPRoot}\Scripts\${ModuleName}"
|
|
||||||
|
|
||||||
## Create the path to the module
|
|
||||||
If ( !(Test-Path $ModulePath) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $ModulePath -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Set the environment variable to the module
|
|
||||||
[System.Environment]::SetEnvironmentVariable('MSPPSModule',"${MSPRoot}\Scripts\${ModuleName}",[System.EnvironmentVariableTarget]::Machine)
|
|
||||||
|
|
||||||
## Make sure all the management directories exist
|
|
||||||
If ( !(Test-Path $MSPRoot) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPRoot -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
If ( !(Test-Path $MSPScripts) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPScripts -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
If ( !(Test-Path $MSPTools) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPTools -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
If ( !(Test-Path $MSPLogs) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPLogs -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Create environment variable for the root MSP directory
|
|
||||||
[System.Environment]::SetEnvironmentVariable('MSPDir',"${MSPRoot}",[System.EnvironmentVariableTarget]::Machine)
|
|
||||||
|
|
||||||
## Download the module file
|
|
||||||
Try { (New-Object Net.WebClient).DownloadFile($ModuleURL, "${MSPRoot}\Scripts\${ModuleName}\${ModuleName}.psm1") }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
$RegKey = 'HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\ImmersiveShell'
|
$RegKey = 'HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\ImmersiveShell'
|
||||||
. 'C:\Users\dyoder\Emberkom\Data\Projects\development\management-scripts\Tools.ps1'
|
|
||||||
## Make sure endpoint is running at least Windows 8
|
## Make sure endpoint is running at least Windows 8
|
||||||
If ( IsWindowsVersion -ge '6.3' )
|
If ( IsWindowsVersion -ge '6.3' )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[switch]$SkipDiskRepair=$true,
|
|
||||||
[switch]$PostRestart=$false
|
|
||||||
)
|
|
||||||
|
|
||||||
## Set the file name for this script when copying to $ScriptDirectory
|
|
||||||
## Note: the .ps1 file extension will be automatically added
|
|
||||||
$ScriptName = "Fix-WindowsHealth"
|
|
||||||
|
|
||||||
## File to log messages into
|
|
||||||
$LogFile = "${MSPLogs}\${ScriptName}.log"
|
|
||||||
|
|
||||||
## Copy script locally and schedule chkdsk at next boot
|
|
||||||
If ( ($PostRestart -eq $false) -and ($SkipDiskRepair -eq $false) ) {
|
|
||||||
|
|
||||||
## Copy this script so it can be run post-reboot
|
|
||||||
If (! (Test-Path $ScriptDirectory) ) { New-Item -Path $ScriptDirectory -ItemType Directory -Force | Out-Null }
|
|
||||||
$ScriptFile = "${ScriptDirectory}\${ScriptName}.ps1"
|
|
||||||
If ( $ScriptFile -ne $MyInvocation.MyCommand.Definition ) {
|
|
||||||
If ( Test-Path $ScriptFile ) {
|
|
||||||
Remove-Item $ScriptFile -Force
|
|
||||||
}
|
|
||||||
Copy-Item -Path $MyInvocation.MyCommand.Definition -Destination $ScriptFile -Force
|
|
||||||
If ( Test-Path $ScriptFile ) {
|
|
||||||
Log $LogFile "Successfully copied running script to: ${ScriptFile}"
|
|
||||||
} Else { Log $LogFile "Failed to copy running script to: ${ScriptFile}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Schedule chkdsk for next reboot
|
|
||||||
& cmd.exe /c echo y `| chkdsk.exe /f /r /x
|
|
||||||
Log $LogFile "Scheduled chkdsk.exe for next reboot"
|
|
||||||
|
|
||||||
## Create a RunOnce task to resume this script after the disk has been repaired
|
|
||||||
$command = """%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe"" -ExecutionPolicy Bypass -File ""${ScriptFile}"" -PostRestart"
|
|
||||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name $ScriptName -Value $command
|
|
||||||
If ( (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name $ScriptName) ) {
|
|
||||||
Log $LogFile "Successfully scheduled post-reboot task: ${command}"
|
|
||||||
} Else { Log $LogFile "Failed to schedule post-reboot task" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Get the last log entry from chkdsk
|
|
||||||
If ( $PostRestart ) {
|
|
||||||
|
|
||||||
## Get the last event chkdsk recorded in the Event Log
|
|
||||||
$chkdskmsg = Get-EventLog -LogName 'Application' -Source 'Wininit' -Newest 1 -ErrorAction SilentlyContinue
|
|
||||||
If ( $chkdskmsg ) {
|
|
||||||
|
|
||||||
## Export the chkdsk log to a separate file for review
|
|
||||||
$ChkdskLog = "${LogDirectory}\${ScriptName}-Chkdsk.log"
|
|
||||||
If ( Test-Path $ChkdskLog ) {
|
|
||||||
Remove-Item $ChkdskLog -Force
|
|
||||||
}
|
|
||||||
New-Item -Path $ChkdskLog -ItemType File -Value $chkdskmsg.Message.ToString()
|
|
||||||
If ( Test-Path $ChkdskLog ) {
|
|
||||||
Log $LogFile "Successfully exported chkdsk result"
|
|
||||||
} Else { Log $LogFile "Failed to export chkdsk result" }
|
|
||||||
|
|
||||||
} Else { Log $LogFile "Last chkdsk result could not be obtained" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Cleanup online image and restore health
|
|
||||||
If ( $PostRestart -or $SkipDiskRepair ) {
|
|
||||||
|
|
||||||
## Run enhanced DISM for Windows 8 and higher assets
|
|
||||||
If ( IsWindowsVersion -ge "6.2" ) {
|
|
||||||
|
|
||||||
$BeginDISMRun = $(Get-Date).AddSeconds(-1)
|
|
||||||
|
|
||||||
## Scan the Windows Component Store for problems
|
|
||||||
Log $LogFile "Beginning Windows Component Store scan"
|
|
||||||
Start-Process "dism.exe" -ArgumentList "/online /cleanup-image /scanhealth" -Wait
|
|
||||||
Log $LogFile "Completed Windows Component Store scan"
|
|
||||||
|
|
||||||
## Check to see if the previous command recorded any problems that need repairing
|
|
||||||
Log $LogFile "Beginning Windows Component Store health check"
|
|
||||||
$CheckHealthOutput = $(dism /online /cleanup-image /checkhealth) | Out-String
|
|
||||||
If ( $CheckHealthOutput -match "repairable" ) {
|
|
||||||
|
|
||||||
Log $LogFile "Completed Windows Component Store health check: Problems found"
|
|
||||||
|
|
||||||
## Repair problems with the Windows Component Store
|
|
||||||
Log $LogFile "Beginning Windows Component Store restoration"
|
|
||||||
Start-Process "dism.exe" -ArgumentList "/online /cleanup-image /restorehealth" -Wait
|
|
||||||
Log $LogFile "Completed Windows Component Store restoration"
|
|
||||||
} Else { Log $LogFile "Completed Windows Component Store health check: No problems found" }
|
|
||||||
|
|
||||||
$EndDISMRun = $(Get-Date).AddSeconds(1)
|
|
||||||
|
|
||||||
## Parse DISM log file for recent activity
|
|
||||||
$DISMLogFile = "${LogDirectory}\${ScriptName}-DISM.log"
|
|
||||||
If ( Test-Path $DISMLogFile ) { Remove-Item $DISMLogFile -Force }
|
|
||||||
New-Item -Path $DISMLogFile -ItemType File
|
|
||||||
Log $LogFile "Beginning Windows Component Store log data collection"
|
|
||||||
Get-Content -Path "${Env:WinDir}\Logs\DISM\dism.log" | Select-String -Pattern '^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})' |
|
|
||||||
% { If ( ((Get-Date $_.Line.Substring(0,19)) -gt $BeginDISMRun) -and ((Get-Date $_.Line.Substring(0,19)) -le $EndDISMRun) ) {
|
|
||||||
Add-Content -Path $DISMLogFile -Value $_.Line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log $LogFile "Completed Windows Component Store log data collection"
|
|
||||||
|
|
||||||
} Else { Log $LogFile "Online image cleanup and restoration is only supported on Windows 8 and higher" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Run SFC
|
|
||||||
If ( $PostRestart -or $SkipDiskRepair ) {
|
|
||||||
|
|
||||||
## Start the TrustedInstaller service if it isn't running
|
|
||||||
## Note: this is necessary for the SFC utility to function properly
|
|
||||||
If ( (Get-Service -Name TrustedInstaller).Status -ne "Running" ) {
|
|
||||||
Restart-Service -Name TrustedInstaller -Force
|
|
||||||
Log $LogFile "Started TrustedInstaller service"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Start the SFC utility to check validity of Windows system files
|
|
||||||
Log $LogFile "Beginning SFC scan and fix"
|
|
||||||
|
|
||||||
$BeginSFCRun = $(Get-Date).AddSeconds(-1)
|
|
||||||
Start-Process "sfc" -ArgumentList "/scannow" -Wait
|
|
||||||
$EndSFCRun = $(Get-Date).AddSeconds(1)
|
|
||||||
Log $LogFile "Completed SFC scan and fix"
|
|
||||||
|
|
||||||
## Parse the CBS.log file and export any SFC related messages
|
|
||||||
$SFCLogFile = "${LogDirectory}\${ScriptName}-SFC.log"
|
|
||||||
If ( Test-Path $SFCLogFile ) { Remove-Item $SFCLogFile -Force }
|
|
||||||
New-Item -Path $SFCLogFile -ItemType File
|
|
||||||
Log $LogFile "Beginning SFC log data collection"
|
|
||||||
Get-Content -Path "${Env:WinDir}\Logs\CBS\CBS.log" | Select-String -Pattern '^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}).+\[SR\]' |
|
|
||||||
% { If ( ((Get-Date $_.Line.Substring(0,19)) -gt $BeginSFCRun) -and ((Get-Date $_.Line.Substring(0,19)) -le $EndSFCRun) ) {
|
|
||||||
Add-Content -Path $SFCLogFile -Value $_.Line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log $LogFile "Completed SFC log data collection"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Prepare Log File Upload
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
rem ## Scan the Windows Component Store for problems
|
|
||||||
dism /online /cleanup-image /scanhealth >nul
|
|
||||||
|
|
||||||
rem ## Check to see if the previous command recorded any problems that need repairing
|
|
||||||
rem ## If there aren't any problems, jump to the section labeled skip-restorehealth
|
|
||||||
dism /online /cleanup-image /checkhealth | find /i "repairable" >nul || goto :skip-restorehealth
|
|
||||||
|
|
||||||
rem ## If there are problems with the Windows Component Store, repair them
|
|
||||||
rem ## Once the repair operation completes, jump to the section labeled run-sfc
|
|
||||||
dism /online /cleanup-image /restorehealth >nul
|
|
||||||
|
|
||||||
rem ## If the Windows Component Store gets repaired, the Ninja activity feed will
|
|
||||||
rem ## see the following line:
|
|
||||||
echo The component store has been repaired.
|
|
||||||
goto run-sfc
|
|
||||||
|
|
||||||
rem ## This scetion only runs if there aren't any problems to repair
|
|
||||||
:skip-restorehealth
|
|
||||||
|
|
||||||
rem ## If the Windows Component Store is healthy, the Ninja activity feed will
|
|
||||||
rem ## see the following line:
|
|
||||||
echo No component store corruption detected.
|
|
||||||
|
|
||||||
rem ## This section runs the sfc utility
|
|
||||||
:run-sfc
|
|
||||||
|
|
||||||
rem ## Check to see if the TrustedInstaller is running, if not then start it
|
|
||||||
rem ## This avoids a common problem with sfc not starting
|
|
||||||
sc query trustedinstaller | find /i "running" >nul || net start trustedinstaller >nul
|
|
||||||
|
|
||||||
rem ## This will take a while and the output of sfc will be recorded in a text file
|
|
||||||
sfc /scannow > %SystemDrive%\sfcoutput.txt
|
|
||||||
+22
-35
@@ -1,48 +1,35 @@
|
|||||||
param([switch]$WSUS)
|
## This is the folder we need to rename
|
||||||
|
$TARGET_DIR = "${Env:WinDir}\SoftwareDistribution"
|
||||||
|
|
||||||
LogMsg "Fix-WindowsUpdate.ps1"
|
## This is what we're renaming it to
|
||||||
|
$DEST_DIR = "${Env:WinDir}\SoftwareDistribution.old"
|
||||||
|
|
||||||
## Delete any existing folder from a previous execution of this script
|
## Delete any existing folder from a previous execution of this script
|
||||||
If ( Test-Path "${Env:WinDir}\SoftwareDistribution.old" )
|
LogMsg "Deleting ""${DEST_DIR}"""
|
||||||
{
|
Try { Remove-Item $DEST_DIR -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
LogMsg "Deleting ""${Env:WinDir}\SoftwareDistribution.old"""
|
Catch { LogErr $_.Exception.Message }
|
||||||
Try { Remove-Item "${Env:WinDir}\SoftwareDistribution.old" -Recurse -Force }
|
|
||||||
Catch { LogErr $_.Exception.Message }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Stop Background Intelligent Transfer Services and Windows Update
|
## Stop Background Intelligent Transfer Services and Windows Update
|
||||||
LogMsg "Stopping BITS service"
|
Control-Service -Stop -Name BITS
|
||||||
Try { Stop-Service BITS }
|
Control-Service -Stop -Name wuauserv
|
||||||
Catch { LogErr $_.Exception.Message }
|
|
||||||
LogMsg "Stopping wuauserv service"
|
|
||||||
Try { Stop-Service wuauserv }
|
|
||||||
Catch { LogErr $_.Exception.Message }
|
|
||||||
|
|
||||||
## Rename the SoftwareDistribution folder, forcing Windows Update to recreate all metrics and redownload all updates
|
## Rename the SoftwareDistribution folder, forcing Windows Update to recreate all metrics and redownload all updates
|
||||||
LogMsg "Renaming ""${Env:WinDir}\SoftwareDistribution"" to ""${Env:WinDir}\SoftwareDistribution.old"""
|
LogMsg "Renaming ""${TARGET_DIR}"" to ""${DEST_DIR}"""
|
||||||
Try { Rename-Item -Path "${Env:WinDir}\SoftwareDistribution" -NewName "${Env:WinDir}\SoftwareDistribution.old" -Force }
|
Try { Rename-Item -Path $TARGET_DIR -NewName $DEST_DIR -Force }
|
||||||
Catch { LogErr $_.Exception.Message }
|
Catch { LogErr $_.Exception.Message }
|
||||||
|
|
||||||
## Start Windows Update and Background Intelligent Transfer Services
|
## Start Windows Update and Background Intelligent Transfer Services
|
||||||
LogMsg "Starting wuauserv service"
|
Control-Service -Start -Name BITS
|
||||||
Try { Start-Service wuauserv }
|
Control-Service -Start -Name wuauserv
|
||||||
Catch { LogErr $_.Exception.Message }
|
|
||||||
LogMsg "Starting BITS service"
|
|
||||||
Try { Start-Service BITS }
|
|
||||||
Catch { LogErr $_.Exception.Message }
|
|
||||||
|
|
||||||
## Delete SoftwareDistribution.old from this execution of this script
|
## Delete SoftwareDistribution.old from this execution of this script
|
||||||
If ( Test-Path "${Env:WinDir}\SoftwareDistribution.old" )
|
## Comment this section out if you want to leave the renamed folder there for some reason,
|
||||||
{
|
## but keep in mind this folder can be very large and takes up a lot of space.
|
||||||
LogMsg "Deleting ""${Env:WinDir}\SoftwareDistribution.old"""
|
LogMsg "Deleting ""${DEST_DIR}"""
|
||||||
Try { Remove-Item "${Env:WinDir}\SoftwareDistribution.old" -Recurse -Force }
|
Try { Remove-Item $DEST_DIR -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
Catch { LogErr $_.Exception.Message }
|
Catch { LogErr $_.Exception.Message }
|
||||||
}
|
|
||||||
|
|
||||||
## If using WSUS, reset authorization with server and detect new updates
|
## Force the Windows Update client to check for new updates
|
||||||
If ( $WSUS )
|
LogMsg "Resetting WSUS authorization and starting update detection"
|
||||||
{
|
Try { Start-Process "${Env:WinDir}\System32\wuauctl.exe" -ArgumentList "/resetauthorization /detectnow" }
|
||||||
LogMsg "Resetting WSUS authorization and starting update detection"
|
Catch { LogErr $_.Exception.Message }
|
||||||
Try { Start-Process "${Env:WinDir}\System32\wuauctl.exe" -ArgumentList "/resetauthorization /detectnow" }
|
|
||||||
Catch { LogErr $_.Exception.Message }
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
rem This script will return the highest installed version of the .NET Framework (versions 1.0 to 4.6.2)
|
|
||||||
|
|
||||||
rem Test for .NET 4.6.2
|
|
||||||
rem reg query HLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client 1>NUL 2>NUL || SET /A "INSTALL=INSTALL-1"
|
|
||||||
|
|
||||||
reg query HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client /v Release
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
###
|
|
||||||
# This script exists in N-Central's Automation Manager
|
|
||||||
###
|
|
||||||
|
|
||||||
param(
|
|
||||||
[string]$ShortName = "EK",
|
|
||||||
[string]$LongName = "Emberkom",
|
|
||||||
[string]$NotificationEmail = "notification@emberkom.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
Function source { . 'C:\Users\dyoder\Emberkom\Data\Projects\development\management-scripts\Tools.ps1' }
|
|
||||||
source
|
|
||||||
|
|
||||||
## Because the N-Central Automation Manager can't actually read the full Powershell syntax, we have to first put the passed in variables
|
|
||||||
## into new variables so we can reference the RMM generated data in the standard form and not with the curly braces
|
|
||||||
$short = $ShortName
|
|
||||||
$long = $LongName
|
|
||||||
$email = $NotificationEmail
|
|
||||||
|
|
||||||
$account = "${short}_${Env:COMPUTERNAME}".ToUpper()
|
|
||||||
$email = $email.ToLower()
|
|
||||||
|
|
||||||
## URL to download the branded WholesaleBackup installer
|
|
||||||
$URL = "http://downloads.backupops.com/4Windows/${MSPName}Backup_installer.exe"
|
|
||||||
|
|
||||||
## Silent installation options
|
|
||||||
$Arguments = "/SP- /VERYSILENT /NORESTART /WPUSH /WACCOUNT ""${account}"" /WORG ""${long}"" /WEMAIL ""${email}"""
|
|
||||||
|
|
||||||
## Install Emberkom Backup
|
|
||||||
#Install-Program -Path $(Download-File -URL $URL) -Arguments $Arguments -Delete
|
|
||||||
|
|
||||||
Write-Output $Arguments
|
|
||||||
@@ -18,9 +18,7 @@ Catch { LogErr $_.Exception.Message }
|
|||||||
|
|
||||||
## Delete installer
|
## Delete installer
|
||||||
Try {
|
Try {
|
||||||
If ( Test-Path $INSTALLER ) {
|
LogMsg "Deleting downloaded installation package"
|
||||||
LogMsg "Deleting downloaded installation package"
|
Remove-Item $INSTALLER -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item $INSTALLER -Force
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Catch { LogErr $_.Exception.Message }
|
Catch { LogErr $_.Exception.Message }
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
## Define URL for downloading the installer
|
## Define URL for downloading the installer
|
||||||
$URL = 'https://dev.emberkom.com/emberkom/management-scripts/raw/branch/master/resources/Nextcloud-3.0.3-setup.exe'
|
$URL = 'https://dev.emberkom.com/emberkom/management-scripts/raw/branch/master/resources/Nextcloud-3.0.3-setup.exe'
|
||||||
|
|
||||||
#$FILE = '{0}{1}' -f (GetTempPath), (Split-Path $URL -Leaf)
|
|
||||||
#$FILE = Download-File -URL $URL -File $FILE
|
|
||||||
|
|
||||||
## Stop app if it's currently running
|
## Stop app if it's currently running
|
||||||
End-Process -Name 'nextcloud' -Force
|
End-Process -Name 'nextcloud' -Force
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
Function global:Set-WinEvtLog {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Enable/Disable an event log.
|
|
||||||
.DESCRIPTION
|
|
||||||
Enable or disable a Windows Event Log using the System.Diagnostics.Eventing.Reader.EventLogConfiguration object.
|
|
||||||
This function only outputs terminating errors to the console. If you want to see more detail use -verbose
|
|
||||||
.EXAMPLE
|
|
||||||
Set-WinEvtLog -Enable -Log "Microsoft-Windows-DNS-Client/Operational"
|
|
||||||
.EXAMPLE
|
|
||||||
Set-WinEvtLog -Disable -Log (Get-Content ListOfLogs.txt)
|
|
||||||
.EXAMPLE
|
|
||||||
Get-Content ListOfLogs.txt | Set-WinEvtLog -Enable
|
|
||||||
.PARAMETER Log
|
|
||||||
The log(s) to modIfy.
|
|
||||||
.PARAMETER Enable
|
|
||||||
Enables the log(s).
|
|
||||||
.PARAMETER Disable
|
|
||||||
Disables the log(s).
|
|
||||||
#>
|
|
||||||
|
|
||||||
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
|
|
||||||
param
|
|
||||||
(
|
|
||||||
[Parameter(Mandatory=$True,
|
|
||||||
ValueFromPipeline=$False,
|
|
||||||
ValueFromPipelineByPropertyName=$True,
|
|
||||||
HelpMessage='Which log do you want to enable?')]
|
|
||||||
[string[]]$Log,
|
|
||||||
[Parameter(Mandatory=$True,
|
|
||||||
ValueFromPipelineByPropertyName=$True,
|
|
||||||
ParameterSetName = 'Enable')]
|
|
||||||
[Switch]$Enable,
|
|
||||||
[Parameter(Mandatory=$True,
|
|
||||||
ValueFromPipelineByPropertyName=$True,
|
|
||||||
ParameterSetName = 'Disable')]
|
|
||||||
[Switch]$Disable
|
|
||||||
)
|
|
||||||
|
|
||||||
Begin
|
|
||||||
{
|
|
||||||
# Keep track of changes made to event logs in a separate file.
|
|
||||||
$RecordLog = "${Env:MSPDir}\Logs\WinEvtLogs-Enabled.log"
|
|
||||||
|
|
||||||
If ( !(Test-Path -Path $RecordLog) )
|
|
||||||
{
|
|
||||||
# Create the record keeping log file If it doesn't exist.
|
|
||||||
$NewFile = ((New-Item -Path $RecordLog -ItemType file).name | Out-String)
|
|
||||||
$NewFile = $NewFile.Trim()
|
|
||||||
Write-Verbose "$NewFile did not exist and has been created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process
|
|
||||||
{
|
|
||||||
# Make sure Record Keeping is properly configured, otherwise exit.
|
|
||||||
If ( !($RecordLog) )
|
|
||||||
{
|
|
||||||
Write-Verbose "The record keeping log does not exist, this function will not continue."
|
|
||||||
Return
|
|
||||||
}
|
|
||||||
|
|
||||||
# Loop through the name(s) in the $Log variable passed to this function.
|
|
||||||
ForEach ($name in $Log)
|
|
||||||
{
|
|
||||||
# Process the data only If the script should Process data.
|
|
||||||
If ( $pscmdlet.ShouldProcess($name, 'Enable Log') )
|
|
||||||
{
|
|
||||||
# Load the RecordLog into a variable.
|
|
||||||
$PreviouslyEnabledLogs = Get-Content $RecordLog
|
|
||||||
|
|
||||||
# Determine whether to Enable or Disable logging of the specIfied log.
|
|
||||||
Switch ($PSCmdlet.ParameterSetName)
|
|
||||||
{
|
|
||||||
'Enable' { $SetEnable = $True }
|
|
||||||
'Disable' { $SetEnable = $False }
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create a new object for the specIfied log.
|
|
||||||
$LogObject = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $name
|
|
||||||
|
|
||||||
# Set the variable to determine whether the log has been enabled by this script or not
|
|
||||||
$IsEnabledByFunction = $False
|
|
||||||
|
|
||||||
# Determine whether or not the log had been enabled by this function.
|
|
||||||
ForEach ($item in $PreviouslyEnabledLogs)
|
|
||||||
{ If ($item -eq $name) { $IsEnabledByFunction = $True } }
|
|
||||||
|
|
||||||
# Act based on whether the log is already enabled or not.
|
|
||||||
Switch ($logObject.IsEnabled)
|
|
||||||
{
|
|
||||||
$True
|
|
||||||
{
|
|
||||||
# Inform user whether this log has been enabled by this function or not.
|
|
||||||
If ($IsEnabledByFunction)
|
|
||||||
{ Write-Verbose "$name has previously been enabled by this function." }
|
|
||||||
Else { Write-Verbose "$name has previously been enabled, but not by this function." }
|
|
||||||
}
|
|
||||||
|
|
||||||
$False
|
|
||||||
{
|
|
||||||
# Inform user that this log has been disabled by something other than this function.
|
|
||||||
If ($IsEnabledByFunction)
|
|
||||||
{ Write-Verbose "$name should already be enabled by this function, but has been disabled by other means." }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ModIfy the log to either enable or disable it.
|
|
||||||
If ($LogObject.IsEnabled -eq $SetEnable)
|
|
||||||
{ Write-Verbose "$name is already in the desired state." }
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
# Set the log to the desired state.
|
|
||||||
$LogObject.IsEnabled = $SetEnable
|
|
||||||
|
|
||||||
# Save changes to the log.
|
|
||||||
$LogObject.SaveChanges()
|
|
||||||
|
|
||||||
# VerIfy the change has been made.
|
|
||||||
Switch ($LogObject.IsEnabled)
|
|
||||||
{
|
|
||||||
$True
|
|
||||||
{
|
|
||||||
Write-Verbose "$name has been enabled."
|
|
||||||
|
|
||||||
# Make sure this log wasn't already enabled by this function so we don't write the same name more than once in $RecordLog
|
|
||||||
If (!($IsEnabledByFunction)) { Add-Content -Path $RecordLog "$name" }
|
|
||||||
}
|
|
||||||
|
|
||||||
$False
|
|
||||||
{
|
|
||||||
# Remove $name from $RecordLog If it was put there by this function.
|
|
||||||
If ($IsEnabledByFunction)
|
|
||||||
{
|
|
||||||
# Clear the contents of $RecordLog
|
|
||||||
Clear-Content -Path $RecordLog
|
|
||||||
|
|
||||||
# Add each item back in that was already there except for the current $name
|
|
||||||
ForEach ($filename In $PreviouslyEnabledLogs)
|
|
||||||
{ If ($filename -ne $name) { Add-Content -Path $RecordLog $filename} }
|
|
||||||
}
|
|
||||||
Write-Verbose "$name has been disabled."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end {}
|
|
||||||
}
|
|
||||||
Export-ModuleMember -Function Set-WinEvtLog
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
#Requires -Version 2.0
|
|
||||||
|
|
||||||
## Set the name of this module
|
|
||||||
$ModuleName = "PSModule"
|
|
||||||
|
|
||||||
## Define base URL for updating modules and resources
|
|
||||||
$BaseURL = "https://dev.emberkom.com/emberkom/management-scripts/raw/branch/master/${ModuleName}"
|
|
||||||
|
|
||||||
## Set the path to this module
|
|
||||||
$ModulePath = "${Env:MSPDir}\Scripts\${ModuleName}"
|
|
||||||
|
|
||||||
## Define the paths for where we'll place stuff on the endpoint
|
|
||||||
$MSPRoot = $Env:MSPDir
|
|
||||||
$MSPScripts = "${MSPRoot}\Scripts"
|
|
||||||
$MSPTools = "${MSPRoot}\Tools"
|
|
||||||
$MSPLogs = "${MSPRoot}\Logs"
|
|
||||||
|
|
||||||
## Function to simply import a module and return an error message if it fails
|
|
||||||
Function Load-Module
|
|
||||||
{
|
|
||||||
param([string]$modulename)
|
|
||||||
|
|
||||||
## Get a new copy of the module
|
|
||||||
Get-Module $modulename
|
|
||||||
|
|
||||||
## Form the local file path to the specified module
|
|
||||||
$FilePath = "${ModulePath}\${modulename}.psm1"
|
|
||||||
|
|
||||||
## Import the module
|
|
||||||
If ( Test-Path $FilePath )
|
|
||||||
{
|
|
||||||
Try { Import-Module -Name $FilePath }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
} Else { Write-Output "Module does not exist: ${FilePath}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Function to update or install a module
|
|
||||||
Function Get-Module
|
|
||||||
{
|
|
||||||
param([string]$modulename)
|
|
||||||
|
|
||||||
## Form the URL to the specified module
|
|
||||||
$ModuleURL = "${BaseURL}/${modulename}.psm1"
|
|
||||||
|
|
||||||
## Form the local file path to the specified module
|
|
||||||
$FilePath = "${ModulePath}\${modulename}.psm1"
|
|
||||||
|
|
||||||
## Download the new file, overwriting the local copy
|
|
||||||
If ( IsDownloadable $ModuleURL )
|
|
||||||
{
|
|
||||||
Try { (New-Object Net.WebClient).DownloadFile($ModuleURL, $FilePath) }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
} Else { Write-Output "Could not download ${ModuleURL}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Determines whether a file can be downloaded or not
|
|
||||||
Function IsDownloadable
|
|
||||||
{
|
|
||||||
param([string]$url)
|
|
||||||
|
|
||||||
## Create a web request
|
|
||||||
$HTTPRequest = [System.Net.WebRequest]::Create($url)
|
|
||||||
|
|
||||||
Try
|
|
||||||
{
|
|
||||||
## Get the response
|
|
||||||
$HTTPResponse = $HTTPRequest.GetResponse()
|
|
||||||
|
|
||||||
## Save the status code
|
|
||||||
$HTTPStatus = [int]$HTTPResponse.StatusCode
|
|
||||||
}
|
|
||||||
Catch [System.Net.WebException] { $HTTPResponse = $_.Exception.Response }
|
|
||||||
|
|
||||||
## Close the connection, because we're done with it
|
|
||||||
Finally { $HTTPResponse.Close() }
|
|
||||||
|
|
||||||
## Test to make sure we received a status of 200 "OK" from the resource
|
|
||||||
If ($HTTPStatus -eq 200) { Return $true }
|
|
||||||
|
|
||||||
## If the status code is anything other than 200, return $false
|
|
||||||
Else { Return $false }
|
|
||||||
}
|
|
||||||
|
|
||||||
## EXPORT FUNCTION
|
|
||||||
## Function to log activity to the configured log directory
|
|
||||||
Function global:Log
|
|
||||||
{
|
|
||||||
Begin {}
|
|
||||||
Process {}
|
|
||||||
End {}
|
|
||||||
}
|
|
||||||
|
|
||||||
## EXPORT FUNCTION
|
|
||||||
## Function to determine if the current user context is an Administrator
|
|
||||||
Function global:IsAdmin
|
|
||||||
{
|
|
||||||
Begin {}
|
|
||||||
Process
|
|
||||||
{
|
|
||||||
If ( ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) )
|
|
||||||
{ Return $true } Else { Return $false }
|
|
||||||
}
|
|
||||||
End {}
|
|
||||||
}
|
|
||||||
|
|
||||||
## EXPORT FUNCTION
|
|
||||||
## Function to retrieve and run a powershell script
|
|
||||||
Function Run-PSScript
|
|
||||||
{
|
|
||||||
param(
|
|
||||||
[string]$Type='management-scripts',
|
|
||||||
[string]$Name,
|
|
||||||
[string]$Arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
## Form the URL to the specified script
|
|
||||||
$URL = "https://dev.emberkom.com/emberkom/${Type}/raw/branch/master/${Name}.ps1"
|
|
||||||
|
|
||||||
If ( IsDownloadable $URL )
|
|
||||||
{
|
|
||||||
$Script = (New-Object Net.WebClient).DownloadString($URL)
|
|
||||||
$ScriptBlock = [Scriptblock]::Create($Script)
|
|
||||||
Try { Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $Arguments }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
} Else { Write-Output "Could not retrieve ${URL}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Make sure all the management directories exist
|
|
||||||
If ( !(Test-Path $MSPRoot) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPRoot -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
If ( !(Test-Path $MSPScripts) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPScripts -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
If ( !(Test-Path $MSPTools) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPTools -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
If ( !(Test-Path $MSPLogs) )
|
|
||||||
{
|
|
||||||
Try { New-Item -Path $MSPLogs -ItemType Directory -Force | Out-Null }
|
|
||||||
Catch { Write-Output $_.Exception.Message }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Import all modules
|
|
||||||
$ListOfModules = @(
|
|
||||||
"PSModule",
|
|
||||||
"PSModule-SetWinEvtLog"
|
|
||||||
)
|
|
||||||
ForEach ($module in $ListOfModules) { Load-Module $module }
|
|
||||||
|
|
||||||
## Make sure this module exports only the functions that should be exported
|
|
||||||
Export-ModuleMember -Function Log,IsAdmin,Run-PSScript
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
param([string]$Name,[switch]$Force=$false)
|
|
||||||
|
|
||||||
If ( $Name )
|
|
||||||
{
|
|
||||||
## Get all matching processes
|
|
||||||
$Processes = Get-Process | Where { $_.Name -ilike $Name }
|
|
||||||
|
|
||||||
## Get the total number of matching processes
|
|
||||||
$NumMatches = $Processes.Count
|
|
||||||
|
|
||||||
If ( $NumMatches -ge 1 )
|
|
||||||
{
|
|
||||||
## Forcefully close matching processes
|
|
||||||
If ( $Force )
|
|
||||||
{
|
|
||||||
Foreach ( $proc in $Processes ) { Stop-Process $proc -Force -ErrorAction SilentlyContinue }
|
|
||||||
Write-Output "Forcefully closed ${NumMatches} matching instance(s) of ${Name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Gracefully close matching processes
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
Foreach ( $proc in $Processes ) { $proc.CloseMainWindow() | Out-Null }
|
|
||||||
Write-Output "Gracefully closed ${NumMatches} matching instance(s) of ${Name}"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Else { Write-Output "No running processes match the name ${Name}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
Else { Write-Output "No process name was specified!" }
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
## Cleanup Ninja's 3pp cache
|
|
||||||
If ( Test-Path "${Env:SystemDrive}\ProgramData\NinjaRMMAgent\components\app-patching\SIGNATURES" )
|
|
||||||
{ Remove-Item "${Env:SystemDrive}\ProgramData\NinjaRMMAgent\components\app-patching\SIGNATURES" -Force -Recurse }
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Remove files older than the specified number of days.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
This script will delete all files in a directory which are older than the specified number of days.
|
|
||||||
It will not search recursively for files and will only look in the directory specified.
|
|
||||||
|
|
||||||
.PARAMETER
|
|
||||||
-Path
|
|
||||||
This is the directory to search for old files
|
|
||||||
|
|
||||||
.PARAMETER
|
|
||||||
-OlderThan
|
|
||||||
This is the number of days that limits the files that are deleted.
|
|
||||||
Anything newer than the value specified here will be retained, while anything older than the value specified here will be deleted.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Remove-OldFiles -Path "C:\Windows\TEMP" -OlderThan 30
|
|
||||||
This will remove all files in C:\Windows\TEMP that are older than 30 days
|
|
||||||
#>
|
|
||||||
|
|
||||||
Param(
|
|
||||||
[string]$Path="C:\Users\dyoder\Desktop",
|
|
||||||
[int]$OlderThan=7
|
|
||||||
)
|
|
||||||
|
|
||||||
If ( Test-Path $Path ) {
|
|
||||||
$files = Get-ChildItem $Path | Where { !$_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-${OlderThan}) }
|
|
||||||
foreach ( $f in $files ) { write-host $f.FullName }
|
|
||||||
} Else { Write-Host "The path does not exist: ${Path}" }
|
|
||||||
@@ -1,678 +0,0 @@
|
|||||||
<#
|
|
||||||
|
|
||||||
.SYNOPSIS
|
|
||||||
Provides friendly messages reminding a user to restart their computer based on events that require it.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
The Set-RebootSchedule script is called from any computer management software to notify a user of a required restart.
|
|
||||||
This script accepts several different parameters which change the messages displayed to the user.
|
|
||||||
Some logic is used when determining the best time to remind the user to restart.
|
|
||||||
|
|
||||||
.PARAMETER SysPerf
|
|
||||||
The -SysPerf parameter will remind the user to restart due to system performance.
|
|
||||||
This parameter should be called if the computer has had consistently high memory usage, recurring application hangs, or stuck processes.
|
|
||||||
If this parameter is used it will simply tell the user that a restart is needed to improve overall stability.
|
|
||||||
|
|
||||||
.PARAMETER OSUpdate
|
|
||||||
The -OSUpdate parameter will remind the user to restart due to operating system updates.
|
|
||||||
|
|
||||||
.PARAMETER Uptime
|
|
||||||
The -Uptime parameter will remind the user to restart due to long uptimes.
|
|
||||||
This script does not define the length of time the computer has been on, but will display the number of days to the end user.
|
|
||||||
If the computer has been on for 10 days and this parameter is used, it will tell the user this computer has been on for 10 days.
|
|
||||||
|
|
||||||
.PARAMETER AllowMinimize
|
|
||||||
The -AllowMinimize parameter will let the prompts and reminders be minimized by the user.
|
|
||||||
By default, the user is not allowed to minimize the window.
|
|
||||||
|
|
||||||
.PARAMETER Override
|
|
||||||
The -Override parameter is used with either the -OSUpdate or -Uptime parameters.
|
|
||||||
This parameter will override the priority of the existing reminder schedule and overwrite any existing schedule with the one set when -Override is called.
|
|
||||||
See the NOTES section for additional information on schedule priorities.
|
|
||||||
|
|
||||||
.PARAMETER Remove
|
|
||||||
The -Remove parameter will simply delete any scheduled restart reminder.
|
|
||||||
|
|
||||||
.PARAMETER Task
|
|
||||||
The -Task parameter will allow this script to run without scheduling a task. This switch is called when this task creates a scheduled task of itself.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -SysPerf
|
|
||||||
Prompt the user to restart because you've seen problems in multiple areas of the computer.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -OSUpdate
|
|
||||||
Prompt the user to restart because Windows was recently updated.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -Uptime
|
|
||||||
Prompt the user to restart because the computer has been up for a long time.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -OSUpdate -Override
|
|
||||||
Prompt the user to restart because Windows was recently updated, overwriting any existing reminder schedule.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -Uptime -Override
|
|
||||||
Prompt the user to restart because the computer has been up for a long time, overwriting any existing reminder schedule.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -Remove
|
|
||||||
There is no longer a need to remind the user to restart, or you just want to clear an existing reminder schedule.
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
Calling this script with no parameters does nothing, the script will just exit without prompting the user for anything.
|
|
||||||
|
|
||||||
This is the order of schedule priority when this script is called:
|
|
||||||
1.) SysPerf
|
|
||||||
2.) OSUpdate
|
|
||||||
3.) Uptime
|
|
||||||
|
|
||||||
If -Uptime is called but a schedule has already been set by -OSUpdate, the user will not be prompted to schedule a restart.
|
|
||||||
If -OSUpdate is called but a schedule has already been set by -SysPerf, the user will not be prompted to schedule a restart.
|
|
||||||
If -SysPerf is called but a schedule has already been set by -OSUpdate, the user will be prompted to schedule a restart and the existing schedule will be overwritten.
|
|
||||||
|
|
||||||
The -Override parameter is used to modify this logic such that a lower priority schedule can overwrite a higher priority schedule.
|
|
||||||
|
|
||||||
#>
|
|
||||||
|
|
||||||
## Define parameters
|
|
||||||
Param(
|
|
||||||
[switch]$SysPerf,
|
|
||||||
[switch]$OSUpdate,
|
|
||||||
[switch]$Uptime,
|
|
||||||
[switch]$AllowMinimize=$false,
|
|
||||||
[switch]$Override,
|
|
||||||
[switch]$Force,
|
|
||||||
[switch]$Remove
|
|
||||||
)
|
|
||||||
|
|
||||||
## Add Windows Forms support to this script
|
|
||||||
Add-Type -AssemblyName System.Windows.Forms
|
|
||||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
|
||||||
|
|
||||||
## Functions and subroutines
|
|
||||||
#region begin FUNCTIONS {
|
|
||||||
|
|
||||||
## Copy this script to a directory where it can be called by a scheduled task
|
|
||||||
Function Copy-ThisScript {
|
|
||||||
|
|
||||||
## Get the current directory path and file name of this script
|
|
||||||
$ThisDirectory = Split-Path -Parent $MyInvocation.PSCommandPath
|
|
||||||
$ThisScript = Split-Path -Leaf $MyInvocation.PSCommandPath
|
|
||||||
|
|
||||||
## Check to make sure we don't copy this script if it's already been copied to $CopyDirectory
|
|
||||||
If ( !($ThisDirectory -eq $CopyDirectory) ) {
|
|
||||||
|
|
||||||
## Create the destination directory if it doesn't already exist
|
|
||||||
If ( !(Test-Path -Path $CopyDirectory) ) { New-Item -ItemType Directory -Force -Path $CopyDirectory }
|
|
||||||
|
|
||||||
## Delete the existing script in $CopyDirectory
|
|
||||||
If ( Test-Path -Path "${CopyDirectory}\${CopyFilename}" ) { Remove-Item -Path "${CopyDirectory}\${CopyFilename}" -Force }
|
|
||||||
|
|
||||||
## Copy the script to $CopyDirectory\$CopyFilename
|
|
||||||
Copy-Item -Path "${ThisDirectory}\${ThisScript}" -Destination "${CopyDirectory}\${CopyFilename}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## Gets the number of days the system has been up.
|
|
||||||
Function Get-UptimeDays {
|
|
||||||
|
|
||||||
## Get a new instance of the Win32_OperatingSystem WMI object
|
|
||||||
$WMIOS = Get-WmiObject Win32_OperatingSystem
|
|
||||||
|
|
||||||
## Get the last boot time and convert it to a DateTime value
|
|
||||||
$LastBootTime = $WMIOS.ConvertToDateTime($WMIOS.LastBootUpTime)
|
|
||||||
|
|
||||||
## Get the number of days since the last time the system was powered on
|
|
||||||
[string]$Uptime = (New-TimeSpan -Start $LastBootTime -End $(Get-Date)).Days.ToString()
|
|
||||||
|
|
||||||
Return $Uptime
|
|
||||||
}
|
|
||||||
|
|
||||||
## Determines whether the logo can be downloaded or not
|
|
||||||
Function IsLogoDownloadable {
|
|
||||||
|
|
||||||
## Create a web request
|
|
||||||
$HTTPRequest = [System.Net.WebRequest]::Create($LogoURL)
|
|
||||||
|
|
||||||
## Get the response
|
|
||||||
Try { $HTTPResponse = $HTTPRequest.GetResponse() }
|
|
||||||
|
|
||||||
## Catch any error2 when trying to connect to the resource (including 404)
|
|
||||||
Catch [System.Net.WebException] { $HTTPResponse = $_.Exception.Response }
|
|
||||||
|
|
||||||
## Save the status code
|
|
||||||
$HTTPStatus = [int]$HTTPResponse.StatusCode
|
|
||||||
|
|
||||||
## Close the connection, because we're done with it
|
|
||||||
$HTTPResponse.Close()
|
|
||||||
|
|
||||||
## Test to make sure we received a status of 200 "OK" from the resource
|
|
||||||
If ($HTTPStatus -eq 200) { Return $true }
|
|
||||||
|
|
||||||
## If the status code is anything other than 200, return $false so we can do something else
|
|
||||||
Else { Return $false }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Returns the local path of a file downloaded from a URL
|
|
||||||
Function Get-LogoPath {
|
|
||||||
|
|
||||||
## Get the file name from $url
|
|
||||||
$filename = [System.IO.Path]::GetFileName($LogoURL)
|
|
||||||
|
|
||||||
## Set the destination to download to
|
|
||||||
$localpath = "${Env:TEMP}\${filename}"
|
|
||||||
|
|
||||||
## Make sure the file is downloadable
|
|
||||||
If ( IsLogoDownloadable ) {
|
|
||||||
|
|
||||||
## Try downloading the file
|
|
||||||
Try { (New-Object Net.WebClient).DownloadFile($LogoURL, $localpath) }
|
|
||||||
|
|
||||||
## If you want to handle any download errors, put that code in here
|
|
||||||
Catch { $_ }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Now that the file *may* be downloaded, check to make sure it exists
|
|
||||||
If ( Test-Path $localpath ) {
|
|
||||||
|
|
||||||
## Return $localpath to the caller
|
|
||||||
Return $localpath
|
|
||||||
}
|
|
||||||
|
|
||||||
## If $localpath doesn't exist (ie: from a previous execution of this script) then return $false
|
|
||||||
Else { Return $false }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Base64 encode something
|
|
||||||
Function Get-Base64($data) {
|
|
||||||
$bytes = [System.Text.Encoding]::Unicode.GetBytes($data)
|
|
||||||
$encoded = [Convert]::ToBase64String($bytes)
|
|
||||||
Return $encoded
|
|
||||||
}
|
|
||||||
|
|
||||||
## Create a scheduled task
|
|
||||||
Function Create-ScheduledTask([string]$name,[string]$description,$action,$principal,$trigger) {
|
|
||||||
|
|
||||||
## Unregister any existing task with the same name as the one we're trying to create
|
|
||||||
## This needs to be fixed. If the task does not exist, it throws an error.
|
|
||||||
Try { Unregister-ScheduledTask -TaskName $name -Confirm:$false }
|
|
||||||
Catch { $_ }
|
|
||||||
|
|
||||||
## Configure the task
|
|
||||||
$Task = New-ScheduledTask -Description $description -Action $action -Principal $principal -Trigger $trigger
|
|
||||||
|
|
||||||
## Register the scheduled task
|
|
||||||
Register-ScheduledTask -TaskName $name -InputObject $Task
|
|
||||||
}
|
|
||||||
|
|
||||||
## Create a task to delete another task
|
|
||||||
## This will run at boot time to make sure that the user doesn't get unnessarily disrupted by
|
|
||||||
## a previously scheduled restart task after the computer has already been restarted.
|
|
||||||
Function Create-DeleteTask([string]$tasktodelete) {
|
|
||||||
|
|
||||||
## Create a RunOnce task to delete the specified task in the Task Scheduler
|
|
||||||
## PROBLEM: How can this occur if the user isn't an admin?
|
|
||||||
## Will this work the same if we write to HKCU instead?
|
|
||||||
#Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name '!DeleteScheduledRebootReminder' -Value "schtasks.exe /Delete /TN ${tasktodelete} /F"
|
|
||||||
|
|
||||||
## Set the task name
|
|
||||||
$TaskName = "${CompanyAbbr} - Delete Task: ${tasktodelete}"
|
|
||||||
|
|
||||||
## Se the task description
|
|
||||||
$TaskDescription = "This task deletes the task: ${tasktodelete}"
|
|
||||||
|
|
||||||
## Configure the task action
|
|
||||||
$args = "/delete /tn " + '"' + "\${tasktodelete}" + '"' + " /f"
|
|
||||||
$TaskAction = New-ScheduledTaskAction -Execute "schtasks.exe" -Argument $args
|
|
||||||
|
|
||||||
## Configure the user account the task will run under
|
|
||||||
$TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
||||||
|
|
||||||
## Configure the trigger to start at the specified time
|
|
||||||
$Trigger = New-ScheduledTaskTrigger -AtStartup
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
## Create a restart task
|
|
||||||
#Function Create-RestartTask([datetime]$starttime) {
|
|
||||||
#
|
|
||||||
# ## Set the task name
|
|
||||||
# $TaskName = "${CompanyAbbr} - Computer Restart Task"
|
|
||||||
#
|
|
||||||
# ## Set the task description
|
|
||||||
# $TaskDescription = "This task restarts the computer"
|
|
||||||
#
|
|
||||||
# ## Convert $script to Base64
|
|
||||||
# $EncodedScript = Get-Base64 $RestartComputerTaskScript
|
|
||||||
#
|
|
||||||
# ## Configure the task action
|
|
||||||
# $TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${EncodedScript}"
|
|
||||||
#
|
|
||||||
# ## Configure the user account the task will run under
|
|
||||||
# $TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
||||||
#
|
|
||||||
# ## Configure the trigger to start at the specific time
|
|
||||||
# $Trigger = New-ScheduledTaskTrigger -Once -At $starttime
|
|
||||||
#
|
|
||||||
# ## Create a new task to delete the one we're about to create the next time the compter boots
|
|
||||||
# Create-DeleteTask $TaskName
|
|
||||||
#
|
|
||||||
# ## Create the restart task
|
|
||||||
# Create-ScheduledTask $TaskName $TaskDescription $TaskAction $TaskPrincipal $TaskTrigger
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Create a reminder task
|
|
||||||
#Function Create-ReminderTask([datetime]$starttime) {
|
|
||||||
#
|
|
||||||
# ## Set the task name
|
|
||||||
# $TaskName = "${CompanyAbbr} - Computer Restart Reminder Task"
|
|
||||||
#
|
|
||||||
# ## Set the task description
|
|
||||||
# $TaskDescription = "This task reminds the user to restart their computer"
|
|
||||||
#
|
|
||||||
# ## Convert $script to Base64
|
|
||||||
# $EncodedScript = Get-Base64 $ReminderTaskScript
|
|
||||||
#
|
|
||||||
# ## Configure the task action
|
|
||||||
# $TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${EncodedScript}"
|
|
||||||
#
|
|
||||||
# ## Configure the user account the task will run under
|
|
||||||
# $TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
||||||
#
|
|
||||||
# ## Configure the trigger to start at boot
|
|
||||||
# $Trigger = New-ScheduledTaskTrigger -Once -At $starttime
|
|
||||||
#
|
|
||||||
# ## Create the restart task
|
|
||||||
# Create-ScheduledTask $TaskName $TaskDescription $TaskAction $TaskPrincipal $TaskTrigger
|
|
||||||
#
|
|
||||||
# ## Create a new task to delete the one we just created the next time the compter boots
|
|
||||||
# Create-DeleteTask $TaskName
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Create a reminder task
|
|
||||||
Function Create-ReminderTask([datetime]$starttime) {
|
|
||||||
|
|
||||||
## Set the task name
|
|
||||||
$TaskName = "${CompanyAbbr} - Computer Restart Reminder Task"
|
|
||||||
|
|
||||||
## Set the task description
|
|
||||||
$TaskDescription = "This task reminds the user to restart their computer"
|
|
||||||
|
|
||||||
## Convert $script to Base64
|
|
||||||
$EncodedScript = Get-Base64 $ReminderTaskScript
|
|
||||||
|
|
||||||
## Configure the task action
|
|
||||||
$TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -File `"${CopyDirectory}\${CopyFilename}`""
|
|
||||||
|
|
||||||
## Configure the user account the task will run under
|
|
||||||
$TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
||||||
|
|
||||||
## Configure the trigger to start at boot
|
|
||||||
$Trigger = New-ScheduledTaskTrigger -Once -At $starttime
|
|
||||||
|
|
||||||
## Create the restart task
|
|
||||||
Create-ScheduledTask $TaskName $TaskDescription $TaskAction $TaskPrincipal $TaskTrigger
|
|
||||||
|
|
||||||
## Create a new task to delete the one we just created the next time the compter boots
|
|
||||||
Create-DeleteTask $TaskName
|
|
||||||
}
|
|
||||||
|
|
||||||
## Determine if the current time is earlier than the given time
|
|
||||||
#Function EarlierThan($time) {
|
|
||||||
#
|
|
||||||
# ## If it's earlier, return $true
|
|
||||||
# If ( (Get-Date) -lt $time ) { Return $true }
|
|
||||||
#
|
|
||||||
# ## If it's later, return false
|
|
||||||
# Else { Return $false }
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Get the closest time to schedule a restart
|
|
||||||
#Function Get-NearestRestartTime {
|
|
||||||
#
|
|
||||||
# ## Find out what day it is
|
|
||||||
# switch ( (Get-Date).DayOfWeek ) {
|
|
||||||
#
|
|
||||||
# ## On weekends, the nearest time to schedule a restart will be:
|
|
||||||
# ## 1.) Lunch time
|
|
||||||
# ## 2.) Sometime in the afternoon
|
|
||||||
# ## 3.) About 20 minutes from the current time
|
|
||||||
# { $WeekendDays -contains $_ } {
|
|
||||||
#
|
|
||||||
# ## If it's earlier than $Lunchime, return $LunchTime
|
|
||||||
# If ( EarlierThan $LunchTime ) { Return $LunchTime }
|
|
||||||
#
|
|
||||||
# ## If it's earlier than $AfternoonTime, return $AfternoonTime
|
|
||||||
# ElseIf ( EarlierThan $AfternoonTime ) { Return $AfternoonTime }
|
|
||||||
#
|
|
||||||
# ## If it's after $AfternoonTime, return $ShortTimeFromNow
|
|
||||||
# Else { Return $ShortTimeFromNow }
|
|
||||||
# break
|
|
||||||
# }
|
|
||||||
# ## Throughout the week the nearest time to remind to restart will be:
|
|
||||||
# ## 1.) Lunch time
|
|
||||||
# ## 2.) Close of business
|
|
||||||
# ## 3.) Late at night
|
|
||||||
# { $WeekDays -contains $_ } {
|
|
||||||
#
|
|
||||||
# ## If it's earlier than $LunchTime, return $LunchTime
|
|
||||||
# If ( EarlierThan $LunchTime ) { Return $LunchTime }
|
|
||||||
#
|
|
||||||
# ## If it's earlier than $CloseOfBusiness, return $CloseOfBusiness
|
|
||||||
# ElseIf ( EarlierThan $CloseOfBusiness ) { Return $CloseOfBusiness }
|
|
||||||
#
|
|
||||||
# ## If it's after $CloseOfBusiness, return $LateAtNight
|
|
||||||
# Else { Return $LateAtNight }
|
|
||||||
# break
|
|
||||||
# }
|
|
||||||
# default { break }
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Get the next time to remind the user to restart
|
|
||||||
#Function Get-NextReminderTime {
|
|
||||||
#
|
|
||||||
# ## Find out what day it is
|
|
||||||
# switch ( (Get-Date).DayOfWeek ) {
|
|
||||||
#
|
|
||||||
# { $TwoDayReminderDays -contains $_ } {
|
|
||||||
#
|
|
||||||
# ## Add 2 days to the current day, then add the $ReminderDelay
|
|
||||||
# $next = $StartOfBusiness + (New-TimeSpan -Days 2) + $ReminderDelay
|
|
||||||
# Return $next
|
|
||||||
# break
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# { $OneDayReminderDays -contains $_ } {
|
|
||||||
#
|
|
||||||
# ## Add 1 day to the current day, then add the $ReminderDelay
|
|
||||||
# $next = $StartOfBusiness + (New-TimeSpan -Days 1) + $ReminderDelay
|
|
||||||
# Return $next
|
|
||||||
# break
|
|
||||||
# }
|
|
||||||
# default { break }
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
|
|
||||||
Function Get-NextReminderTime {
|
|
||||||
|
|
||||||
$next = (Get-Date) + $ReminderInterval
|
|
||||||
Return $next
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
## Builds the Windows form to display to the user
|
|
||||||
Function Display-Prompt([string]$message) {
|
|
||||||
|
|
||||||
## Set the form's overall parameters
|
|
||||||
$Form = New-Object System.Windows.Forms.Form
|
|
||||||
$Form.ClientSize = '400,360'
|
|
||||||
$Form.Text = $WindowTitle
|
|
||||||
$Form.TopMost = $true
|
|
||||||
$Form.MaximizeBox = $false
|
|
||||||
$Form.MinimizeBox = $AllowMinimize
|
|
||||||
$Form.FormBorderStyle = 'FixedDialog'
|
|
||||||
$Form.StartPosition = 'CenterScreen'
|
|
||||||
|
|
||||||
## Download the logo
|
|
||||||
$Logo = (Get-LogoPath)
|
|
||||||
|
|
||||||
## Add a picturebox to the form
|
|
||||||
If ( $Logo ) {
|
|
||||||
$pbLogo = New-Object system.Windows.Forms.PictureBox
|
|
||||||
$pbLogo.Width = $Form.ClientSize.Width - 20
|
|
||||||
$pbLogo.Height = 90
|
|
||||||
$pbLogo.Anchor = [System.Windows.Forms.AnchorStyles]::None
|
|
||||||
$pbLogo.Location = New-Object System.Drawing.Point(10,10)
|
|
||||||
$pbLogo.ImageLocation = $Logo
|
|
||||||
$pbLogo.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::CenterImage
|
|
||||||
$Form.Controls.Add($pbLogo)
|
|
||||||
}
|
|
||||||
|
|
||||||
## If the logo isn't available, add label to the form instead of a picturebox
|
|
||||||
Else {
|
|
||||||
$lblCompany = New-Object System.Windows.Forms.Label
|
|
||||||
$lblCompany.Text = $CompanyName
|
|
||||||
$lblCompany.AutoSize = $false
|
|
||||||
## The TextAlign enumerations can be found here:
|
|
||||||
## https://docs.microsoft.com/en-us/dotnet/api/system.drawing.contentalignment?view=netframework-2.0
|
|
||||||
$lblCompany.TextAlign = 32
|
|
||||||
$lblCompany.Width = $Form.ClientSize.Width - 20
|
|
||||||
$lblCompany.Height = 60
|
|
||||||
$lblCompany.Location = New-Object System.Drawing.Point(10,10)
|
|
||||||
$lblCompany.Font = 'Microsoft Sans Serif,24,style=Bold'
|
|
||||||
$Form.Controls.Add($lblCompany)
|
|
||||||
}
|
|
||||||
|
|
||||||
## This is the label that contains the reason for the restart
|
|
||||||
$lblReason = New-Object System.Windows.Forms.Label
|
|
||||||
$lblReason.Text = $message
|
|
||||||
$lblReason.AutoSize = $false
|
|
||||||
$lblReason.TextAlign = 1
|
|
||||||
$lblReason.Width = $Form.ClientSize.Width - 50
|
|
||||||
$lblReason.Height = 180
|
|
||||||
$lblReason.Location = New-Object System.Drawing.Point(25,100)
|
|
||||||
$lblReason.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$Form.Controls.Add($lblReason)
|
|
||||||
|
|
||||||
## This is the label that contains a static message about how to proceed
|
|
||||||
$lblProceed = New-Object System.Windows.Forms.Label
|
|
||||||
$lblProceed.Text = $ProceedText
|
|
||||||
$lblProceed.AutoSize = $true
|
|
||||||
$lblProceed.TextAlign = 1
|
|
||||||
$lblProceed.Location = New-Object System.Drawing.Point(25,280)
|
|
||||||
$lblProceed.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$Form.Controls.Add($lblProceed)
|
|
||||||
|
|
||||||
# ## This is the button that displays the nearest time to schedule a reboot
|
|
||||||
# $btnNearestTime = New-Object System.Windows.Forms.Button
|
|
||||||
# $btnNearestTime.Text = (Get-Date -Date $NearestRestartTime -Format "hh:mm tt").ToString()
|
|
||||||
# $btnNearestTime.Width = 130
|
|
||||||
# $btnNearestTime.Height = 30
|
|
||||||
# $btnNearestTime.Location = New-Object System.Drawing.Point(45,310)
|
|
||||||
# $btnNearestTime.Font = 'Microsoft Sans Serif,11'
|
|
||||||
# $btnNearestTime.Add_Click({
|
|
||||||
#
|
|
||||||
# ## Create the "Computer Restart Task" scheduled task
|
|
||||||
# Create-ReminderTask $NearestRestartTime
|
|
||||||
#
|
|
||||||
# ## We're done for now, just close the window.
|
|
||||||
# $Form.Close()
|
|
||||||
# })
|
|
||||||
|
|
||||||
## This is the button that displays the nearest time to schedule a reboot
|
|
||||||
$btnNearestTime = New-Object System.Windows.Forms.Button
|
|
||||||
$btnNearestTime.Text = $RebootNowText
|
|
||||||
$btnNearestTime.Width = 130
|
|
||||||
$btnNearestTime.Height = 30
|
|
||||||
$btnNearestTime.Location = New-Object System.Drawing.Point(45,310)
|
|
||||||
$btnNearestTime.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$btnNearestTime.Add_Click({
|
|
||||||
|
|
||||||
## Create the "Computer Restart Task" scheduled task
|
|
||||||
Restart-Computer
|
|
||||||
|
|
||||||
## We're done for now, just close the window.
|
|
||||||
$Form.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
$Form.AcceptButton = $btmNearestTime
|
|
||||||
$Form.Controls.Add($btnNearestTime)
|
|
||||||
|
|
||||||
## This is the placebo button, it just closes the form when clicked.
|
|
||||||
## The reminder schedule has already been created, so this button doesn't need to do anything.
|
|
||||||
$btnPlacebo = New-Object System.Windows.Forms.Button
|
|
||||||
$btnPlacebo.Text = $PlaceboText
|
|
||||||
$btnPlacebo.Width = 130
|
|
||||||
$btnPlacebo.Height = 30
|
|
||||||
$btnPlacebo.Location = New-Object System.Drawing.Point(225,310)
|
|
||||||
$btnPlacebo.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$btnPlacebo.Add_Click({ $Form.Close() })
|
|
||||||
$Form.Controls.Add($btnPlacebo)
|
|
||||||
|
|
||||||
|
|
||||||
[void]$Form.ShowDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion FUNCTIONS }
|
|
||||||
|
|
||||||
#region begin SCRIPTS {
|
|
||||||
|
|
||||||
## This script is used to remind the user to restart their computer
|
|
||||||
$ReminderTaskScript = '&{
|
|
||||||
## code here
|
|
||||||
}'
|
|
||||||
|
|
||||||
#endregion SCRIPTS }
|
|
||||||
|
|
||||||
## Define custom company name, logo, window title, and messages
|
|
||||||
#region begin CUSTOMIZATIONS {
|
|
||||||
|
|
||||||
## The following 2 settings are specific to your company
|
|
||||||
## This is the name of your company.
|
|
||||||
$CompanyName = "Emberkom"
|
|
||||||
## This is the short or abbreviated name of your company
|
|
||||||
## It's used to prefix the scheduled tasks so they're easy to identify
|
|
||||||
$CompanyAbbr = "EK"
|
|
||||||
## This is the URL to your company logo.
|
|
||||||
## If your company logo cannot be downloaded, $CompanyName will be used instead.
|
|
||||||
## If the image you specify is larger than 380x90, it will shrink to fit that size.
|
|
||||||
$LogoURL = 'https://emberkom.s3.amazonaws.com/management/scripts/resources/small-web-logo.jpg'
|
|
||||||
|
|
||||||
## This script will start by copying itself into a local directory on the computer.
|
|
||||||
## This will allow the scheduled tasks this script creates to call it later.
|
|
||||||
## Directory to copy this script into (do not put in an ending "\")
|
|
||||||
$CopyDirectory = "${Env:ProgramData}\${CompanyName}\Scripts"
|
|
||||||
## The name of the file this script should have when copied to the $CopyDirectory
|
|
||||||
$CopyFilename = "Set-RebootSchedule.ps1"
|
|
||||||
|
|
||||||
## The following 6 settings control text displayed on the form when prompting the user to choose a time to restart their computer
|
|
||||||
## The title of the window
|
|
||||||
$WindowTitle = "Restart Required - ${CompanyName}"
|
|
||||||
## The message displayed to the user when -SysPerf is called.
|
|
||||||
$SysPerfText = "It looks like your computer isn't performing like it should.`n`nRestarting it will help to resolve some of the problems its been having."
|
|
||||||
## The message displayed to the user when -OSUpdate is called.
|
|
||||||
$OSUpdateText = "Good news!`n`nYour computer has recently installed some updates and it needs to be restarted soon."
|
|
||||||
## Thhe message displayed to the user when -Uptime is called.
|
|
||||||
$UptimeText = "It looks like your computer has been on for more than $(Get-UptimeDays) days.`n`nIt's probably best to restart soon so it doesn't start causing problems for you."
|
|
||||||
## This is the message displayed just above the buttons - it should ask the user how they want to proceed
|
|
||||||
$ProceedText = "When can we make this happen?"
|
|
||||||
## This is the text for a placebo button. Regardless of whether the user clicks this button or not,
|
|
||||||
## a reminder has already been created. Clicking the button will just close the form.
|
|
||||||
## This is simply because I don't want the user to be able to dismiss restarting their
|
|
||||||
## computer, but I still want them to feel like they're involved and have some control
|
|
||||||
## over the situation. Automatically reminding them some other time won't hurt anything.
|
|
||||||
$PlaceboText = "Remind me later"
|
|
||||||
|
|
||||||
|
|
||||||
############### NEW SETTINGS ###############
|
|
||||||
|
|
||||||
## The message on the button that immediately restarts the computer
|
|
||||||
$RebootNowText = "Restart Now"
|
|
||||||
|
|
||||||
## When to begin notifying the user they need to reboot their computer
|
|
||||||
$StartReminderAt = Get-Date -Hour 9 -Minute 0 -Second 0
|
|
||||||
|
|
||||||
## When to stop notifying the user to reboot.
|
|
||||||
## If the next notification to restart is scheduled to happen after this time,
|
|
||||||
## it will be automatically rescheduled until $StartReminderAt of the following day.
|
|
||||||
$StopReminderAt = Get-Date -Hour 16 -Minute 50 -Second 0
|
|
||||||
|
|
||||||
## The amount of time between restart notifications
|
|
||||||
$ReminderInterval = New-TimeSpan -Hours 2 -Minutes 45
|
|
||||||
|
|
||||||
|
|
||||||
## This is some small amount of time in the future where the user can schedule a reboot. This isn't used often, but is used
|
|
||||||
## The formula used here will add 20 minutes to the current time and round it to the nearest 5 minute mark.
|
|
||||||
## I referenced the code by Tony Hinkle in this post:
|
|
||||||
## https://stackoverflow.com/questions/39728485/rounding-down-minutes-to-the-nearest-10-minutes#39728699
|
|
||||||
$ShortTimeFromNow = (Get-Date).AddMinutes(-(((Get-Date).Minute % 5) - 20))
|
|
||||||
|
|
||||||
## The following 5 settings configure the date and time this script will use to schedule reminders and restarts
|
|
||||||
## All times will be today's date at the hour, minute, and second specified.
|
|
||||||
## Specify the business start time.
|
|
||||||
## This time is used to remind the user to restart their computer. The reminder won't show up until at least the value defined here.
|
|
||||||
## The $ReminderDelay time will be added to $StartOfBusiness to come up with the time to remind the user to restart their computer.
|
|
||||||
$StartOfBusiness = Get-Date -Hour 8 -Minute 30 -Second 0
|
|
||||||
## Specify the lunch time
|
|
||||||
## This time is used to schedule a restart all through the week and weekends.
|
|
||||||
$LunchTime = Get-Date -Hour 12 -Minute 0 -Second 0
|
|
||||||
## Specify the afternoon time
|
|
||||||
## This time is used to schedule a restart only on the weekends and is based on $LunchTime
|
|
||||||
$AfternoonTime = $LunchTime + (New-TimeSpan -Hours 2 -Minutes 30)
|
|
||||||
## Specify the close-of-business time. In reality this should be a little bit before the actual close of business time.
|
|
||||||
## This time is used to remind to restart only during the weekdays. This should be just before everyone starts leaving the office.
|
|
||||||
$CloseOfBusiness = Get-Date -Hour 16 -Minute 50 -Second 0
|
|
||||||
## Specify the late-at-night time
|
|
||||||
## This time is used to schedule a restart only during the weekdays. You should use a time when users are least likely to work
|
|
||||||
$LateAtNight = Get-Date -Hour 22 -Minute 0 -Second 0
|
|
||||||
|
|
||||||
## Specify delay after the $StartOfBusiness when the user will be reminded to restart
|
|
||||||
## If the user does not restart, this is used to delay the reminder until most people are in the office
|
|
||||||
## For example: if $StartOfBusiness is 8am, but most people aren't in the office until 8:30am,
|
|
||||||
## you'll want to specify a value of 30 minutes here.
|
|
||||||
## They probably don't want to come in and immediately see a reminder to restart their computer. Let them get coffee first :-)
|
|
||||||
$ReminderDelay = New-TimeSpan -Minutes 40
|
|
||||||
|
|
||||||
## The next two settings define the week for your customer.
|
|
||||||
## If their weekend is not Saturday and Sunday, define that here.
|
|
||||||
## Weekend days
|
|
||||||
$WeekendDays = @("Saturday","Sunday")
|
|
||||||
## Week days
|
|
||||||
$WeekDays = @("Monday","Tuesday","Wednesday","Thursday","Friday")
|
|
||||||
|
|
||||||
## The next two settings define the 2-day reminders and the 1-day reminders.
|
|
||||||
## On the day this script is run, a reminder is automatically created.
|
|
||||||
## If the user closes the window or clicks the placebo button, the reminder is already created
|
|
||||||
## for either the next day, or 2 days from now.
|
|
||||||
## If you changed the previous 2 settings to specify different weekend and week days,
|
|
||||||
## you'll probably want to change this setting too.
|
|
||||||
## The idea behind this is to guide the user to restarting their computer sooner rather than later.
|
|
||||||
## The default options will push them towards restarting at the end of the work week, but if the
|
|
||||||
## script runs on the weekend, the reminder won't bother them again until the start of the work week.
|
|
||||||
## Specify the 2-day reminder days (user will be reminded 2 days after the days in this setting)
|
|
||||||
$TwoDayReminderDays = @("Monday","Tuesday","Wednesday","Saturday")
|
|
||||||
## Specify the 1-day reminder days (user will be reminded the day after the days in this setting)
|
|
||||||
$OneDayReminderDays = @("Thursday","Friday","Sunday")
|
|
||||||
|
|
||||||
#endregion CUSTOMIZATIONS }
|
|
||||||
|
|
||||||
## This is where we do everything needed to either prompt or remind the user to restart their computer
|
|
||||||
## This will involve copying the script locally, checking for existing reminder priorities, etc...
|
|
||||||
#region begin PREFLIGHT {
|
|
||||||
|
|
||||||
## Copy this script to $CopyDirectory if it isn't being run from $CopyDirectory
|
|
||||||
If ( $MyInvocation.PSCommandPath -ne "${CopyDirectory}\${CopyFilename}" ) { Copy-ThisScript }
|
|
||||||
|
|
||||||
## Disallow this script to display to the user before we check the parameters
|
|
||||||
$AllowDisplay = $false
|
|
||||||
|
|
||||||
## If the last argument is -Task, then make sure we allow this script to display to the user
|
|
||||||
If ( $args[$args.Count - 1].ToString() -ieq "-Task" ) { $AllowDisplay = $true }
|
|
||||||
|
|
||||||
## If the last argument isn't -Task, then we need to create a scheduled task for 10 seconds from now to run this script
|
|
||||||
Else {
|
|
||||||
|
|
||||||
Write-Host "No Task"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion PREFLIGHT }
|
|
||||||
|
|
||||||
## This is where we gather the necessary info and prompt the user to restart
|
|
||||||
#region begin DISPLAY_FORM
|
|
||||||
|
|
||||||
## Get the nearest time to schedule a restart
|
|
||||||
#$NearestRestartTime = Get-NearestRestartTime
|
|
||||||
|
|
||||||
## Get the next reminder time
|
|
||||||
$NextReminderTime = Get-NextReminderTime
|
|
||||||
|
|
||||||
##
|
|
||||||
|
|
||||||
## Display the form
|
|
||||||
If ( $AllowDisplay ) { Display-Prompt $SysPerfText }
|
|
||||||
|
|
||||||
#endregion DISPLAY_FORM
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
<#
|
|
||||||
|
|
||||||
.SYNOPSIS
|
|
||||||
Provides friendly messages reminding a user to restart their computer based on events that require it.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
The Set-RebootSchedule script is called from any computer management software to notify a user of a required restart.
|
|
||||||
This script accepts several different parameters which change the messages displayed to the user.
|
|
||||||
|
|
||||||
.PARAMETER SysPerf
|
|
||||||
The -SysPerf parameter will remind the user to restart due to system performance.
|
|
||||||
This parameter should be called if the computer has had consistently high memory usage, recurring application hangs, or stuck processes.
|
|
||||||
If this parameter is used it will simply tell the user that a restart is needed to improve overall stability.
|
|
||||||
|
|
||||||
.PARAMETER OSUpdate
|
|
||||||
The -OSUpdate parameter will remind the user to restart due to operating system updates.
|
|
||||||
|
|
||||||
.PARAMETER Uptime
|
|
||||||
The -Uptime parameter will remind the user to restart due to long uptimes.
|
|
||||||
This script does not define the length of time the computer has been on, but will display the number of days to the end user.
|
|
||||||
If the computer has been on for 10 days and this parameter is used, it will tell the user this computer has been on for 10 days.
|
|
||||||
|
|
||||||
.PARAMETER AllowMinimize
|
|
||||||
The -AllowMinimize parameter will let the prompt be minimized by the user.
|
|
||||||
By default, the user is not allowed to minimize the window.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -SysPerf
|
|
||||||
Prompt the user to restart because you've seen problems in multiple areas of the computer.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -OSUpdate
|
|
||||||
Prompt the user to restart because Windows was recently updated.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Set-RebootSchedule -Uptime
|
|
||||||
Prompt the user to restart because the computer has been up for a long time.
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
Calling this script with no parameters does nothing, the script will just exit without prompting the user for anything.
|
|
||||||
#>
|
|
||||||
|
|
||||||
## Define parameters
|
|
||||||
|
|
||||||
Param(
|
|
||||||
[switch]$SysPerf=$false,
|
|
||||||
[switch]$OSUpdate=$false,
|
|
||||||
[switch]$Uptime=$false,
|
|
||||||
[switch]$AllowMinimize=$false
|
|
||||||
)
|
|
||||||
|
|
||||||
## Get the name of this script
|
|
||||||
$ScriptName = $MyInvocation.MyCommand.Name
|
|
||||||
|
|
||||||
## Get a list of running PowerShell scripts
|
|
||||||
$RUnningPSScripts = Get-WmiObject Win32_Process -Filter "Name='powershell.exe'" | Select-Object ProcessId,CommandLine
|
|
||||||
|
|
||||||
## Loop through all other running instances of this script and kill each one that isn't the current instance.
|
|
||||||
ForEach ( $script in $RUnningPSScripts ) {
|
|
||||||
$OtherPID = $script.ProcessId
|
|
||||||
$OtherCMD = $script.CommandLine
|
|
||||||
|
|
||||||
## Check for other instances of this script that might be running
|
|
||||||
If ( ($OtherCMD -like "*${ScriptName}*") -and ($OtherPID -ne $PID) ) {
|
|
||||||
|
|
||||||
## Kill the other instance
|
|
||||||
Stop-Process -Id $script.ProcessId -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## Add Windows Forms support to this script
|
|
||||||
Add-Type -AssemblyName System.Windows.Forms
|
|
||||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
|
||||||
|
|
||||||
## Functions and subroutines
|
|
||||||
#region begin FUNCTIONS {
|
|
||||||
|
|
||||||
## Gets the number of days the system has been up.
|
|
||||||
Function Get-UptimeDays {
|
|
||||||
|
|
||||||
## Get a new instance of the Win32_OperatingSystem WMI object
|
|
||||||
$WMIOS = Get-WmiObject Win32_OperatingSystem
|
|
||||||
|
|
||||||
## Get the last boot time and convert it to a DateTime value
|
|
||||||
$LastBootTime = $WMIOS.ConvertToDateTime($WMIOS.LastBootUpTime)
|
|
||||||
|
|
||||||
## Get the number of days since the last time the system was powered on
|
|
||||||
[string]$Uptime = (New-TimeSpan -Start $LastBootTime -End $(Get-Date)).Days.ToString()
|
|
||||||
|
|
||||||
Return $Uptime
|
|
||||||
}
|
|
||||||
|
|
||||||
## Determines whether the logo can be downloaded or not
|
|
||||||
Function IsLogoDownloadable {
|
|
||||||
|
|
||||||
## Create a web request
|
|
||||||
$HTTPRequest = [System.Net.WebRequest]::Create($LogoURL)
|
|
||||||
|
|
||||||
## Get the response
|
|
||||||
Try { $HTTPResponse = $HTTPRequest.GetResponse() }
|
|
||||||
|
|
||||||
## Catch any error2 when trying to connect to the resource (including 404)
|
|
||||||
Catch [System.Net.WebException] { $HTTPResponse = $_.Exception.Response }
|
|
||||||
|
|
||||||
## Save the status code
|
|
||||||
$HTTPStatus = [int]$HTTPResponse.StatusCode
|
|
||||||
|
|
||||||
## Close the connection, because we're done with it
|
|
||||||
$HTTPResponse.Close()
|
|
||||||
|
|
||||||
## Test to make sure we received a status of 200 "OK" from the resource
|
|
||||||
If ($HTTPStatus -eq 200) { Return $true }
|
|
||||||
|
|
||||||
## If the status code is anything other than 200, return $false so we can do something else
|
|
||||||
Else { Return $false }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Returns the local path of a file downloaded from a URL
|
|
||||||
Function Get-LogoPath {
|
|
||||||
|
|
||||||
## Get the file name from $url
|
|
||||||
$filename = [System.IO.Path]::GetFileName($LogoURL)
|
|
||||||
|
|
||||||
## Set the destination to download to
|
|
||||||
$localpath = "${Env:TEMP}\${filename}"
|
|
||||||
|
|
||||||
## Make sure the file is downloadable
|
|
||||||
If ( IsLogoDownloadable ) {
|
|
||||||
|
|
||||||
## Try downloading the file
|
|
||||||
Try { (New-Object Net.WebClient).DownloadFile($LogoURL, $localpath) }
|
|
||||||
|
|
||||||
## If you want to handle any download errors, put that code in here
|
|
||||||
Catch { $_ }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Now that the file *may* be downloaded, check to make sure it exists
|
|
||||||
If ( Test-Path $localpath ) {
|
|
||||||
|
|
||||||
## Return $localpath to the caller
|
|
||||||
Return $localpath
|
|
||||||
}
|
|
||||||
|
|
||||||
## If $localpath doesn't exist (ie: from a previous execution of this script) then return $false
|
|
||||||
Else { Return $false }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## Builds the Windows form to display to the user
|
|
||||||
Function Display-Prompt([string]$message) {
|
|
||||||
|
|
||||||
## Set the form's overall parameters
|
|
||||||
$Form = New-Object System.Windows.Forms.Form
|
|
||||||
$Form.ClientSize = '400,360'
|
|
||||||
$Form.Text = $WindowTitle
|
|
||||||
$Form.TopMost = $true
|
|
||||||
$Form.MaximizeBox = $false
|
|
||||||
$Form.MinimizeBox = $AllowMinimize
|
|
||||||
$Form.FormBorderStyle = 'FixedDialog'
|
|
||||||
$Form.StartPosition = 'CenterScreen'
|
|
||||||
|
|
||||||
## Download the logo
|
|
||||||
$Logo = (Get-LogoPath)
|
|
||||||
|
|
||||||
## Add a picturebox to the form
|
|
||||||
If ( $Logo ) {
|
|
||||||
$pbLogo = New-Object system.Windows.Forms.PictureBox
|
|
||||||
$pbLogo.Width = $Form.ClientSize.Width - 20
|
|
||||||
$pbLogo.Height = 90
|
|
||||||
$pbLogo.Anchor = [System.Windows.Forms.AnchorStyles]::None
|
|
||||||
$pbLogo.Location = New-Object System.Drawing.Point(10,10)
|
|
||||||
$pbLogo.ImageLocation = $Logo
|
|
||||||
$pbLogo.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::CenterImage
|
|
||||||
$Form.Controls.Add($pbLogo)
|
|
||||||
}
|
|
||||||
|
|
||||||
## If the logo isn't available, add label to the form instead of a picturebox
|
|
||||||
Else {
|
|
||||||
$lblCompany = New-Object System.Windows.Forms.Label
|
|
||||||
$lblCompany.Text = $CompanyName
|
|
||||||
$lblCompany.AutoSize = $false
|
|
||||||
## The TextAlign enumerations can be found here:
|
|
||||||
## https://docs.microsoft.com/en-us/dotnet/api/system.drawing.contentalignment?view=netframework-2.0
|
|
||||||
$lblCompany.TextAlign = 32
|
|
||||||
$lblCompany.Width = $Form.ClientSize.Width - 20
|
|
||||||
$lblCompany.Height = 60
|
|
||||||
$lblCompany.Location = New-Object System.Drawing.Point(10,10)
|
|
||||||
$lblCompany.Font = 'Microsoft Sans Serif,24,style=Bold'
|
|
||||||
$Form.Controls.Add($lblCompany)
|
|
||||||
}
|
|
||||||
|
|
||||||
## This is the label that contains the reason for the restart
|
|
||||||
$lblReason = New-Object System.Windows.Forms.Label
|
|
||||||
$lblReason.Text = $message
|
|
||||||
$lblReason.AutoSize = $false
|
|
||||||
$lblReason.TextAlign = 1
|
|
||||||
$lblReason.Width = $Form.ClientSize.Width - 50
|
|
||||||
$lblReason.Height = 180
|
|
||||||
$lblReason.Location = New-Object System.Drawing.Point(25,100)
|
|
||||||
$lblReason.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$Form.Controls.Add($lblReason)
|
|
||||||
|
|
||||||
## This is the label that contains a static message about how to proceed
|
|
||||||
$lblProceed = New-Object System.Windows.Forms.Label
|
|
||||||
$lblProceed.Text = $ProceedText
|
|
||||||
$lblProceed.AutoSize = $true
|
|
||||||
$lblProceed.TextAlign = 1
|
|
||||||
$lblProceed.Location = New-Object System.Drawing.Point(25,280)
|
|
||||||
$lblProceed.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$Form.Controls.Add($lblProceed)
|
|
||||||
|
|
||||||
## This is the button that displays the nearest time to schedule a reboot
|
|
||||||
$btnRestartNow = New-Object System.Windows.Forms.Button
|
|
||||||
$btnRestartNow.Text = $RestartNowText
|
|
||||||
$btnRestartNow.Width = 130
|
|
||||||
$btnRestartNow.Height = 30
|
|
||||||
$btnRestartNow.Location = New-Object System.Drawing.Point(45,310)
|
|
||||||
$btnRestartNow.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$btnRestartNow.Add_Click({
|
|
||||||
|
|
||||||
## Restart the computer
|
|
||||||
Restart-Computer
|
|
||||||
|
|
||||||
## We're done for now, just close the window.
|
|
||||||
$Form.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
$Form.AcceptButton = $btmRestartNow
|
|
||||||
$Form.Controls.Add($btnRestartNow)
|
|
||||||
|
|
||||||
## This is the placebo button, it just closes the form when clicked.
|
|
||||||
## The reminder schedule has already been created, so this button doesn't need to do anything.
|
|
||||||
$btnCancel = New-Object System.Windows.Forms.Button
|
|
||||||
$btnCancel.Text = $CancelText
|
|
||||||
$btnCancel.Width = 130
|
|
||||||
$btnCancel.Height = 30
|
|
||||||
$btnCancel.Location = New-Object System.Drawing.Point(225,310)
|
|
||||||
$btnCancel.Font = 'Microsoft Sans Serif,11'
|
|
||||||
$btnCancel.Add_Click({ $Form.Close() })
|
|
||||||
$Form.Controls.Add($btnCancel)
|
|
||||||
|
|
||||||
|
|
||||||
[void]$Form.ShowDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion FUNCTIONS }
|
|
||||||
|
|
||||||
## Define custom company name, logo, window title, and messages
|
|
||||||
#region begin CUSTOMIZATIONS {
|
|
||||||
|
|
||||||
## The following 2 settings are specific to your company
|
|
||||||
## This is the name of your company.
|
|
||||||
$CompanyName = "Emberkom"
|
|
||||||
## This is the URL to your company logo.
|
|
||||||
## If your company logo cannot be downloaded, $CompanyName will be used instead.
|
|
||||||
## If the image you specify is larger than 380x90, it will be centered in that area (clipping will occur).
|
|
||||||
$LogoURL = 'https://emberkom.s3.amazonaws.com/management/scripts/resources/small-web-logo.png'
|
|
||||||
|
|
||||||
## The following 7 settings control text displayed on the form when prompting the user to choose a time to restart their computer
|
|
||||||
## The title of the window
|
|
||||||
$WindowTitle = "Restart Required - ${CompanyName}"
|
|
||||||
## The message displayed to the user when -SysPerf is called.
|
|
||||||
$SysPerfText = "It looks like your computer isn't performing like it should.`n`nRestarting it will help to resolve some of the problems its been having."
|
|
||||||
## The message displayed to the user when -OSUpdate is called.
|
|
||||||
$OSUpdateText = "Good news!`n`nYour computer has recently installed some updates and it needs to be restarted soon."
|
|
||||||
## The message displayed to the user when -Uptime is called.
|
|
||||||
$UptimeText = "It looks like your computer has been on for more than $(Get-UptimeDays) days.`n`nIt's probably best to restart soon so it doesn't start causing problems for you."
|
|
||||||
## This is the message displayed just above the buttons - it should ask the user how they want to proceed
|
|
||||||
$ProceedText = "Can we make this happen?"
|
|
||||||
## This is the text for the cancel button. Clicking this button will just close the form
|
|
||||||
$CancelText = "Remind me later"
|
|
||||||
## The message on the button that immediately restarts the computer
|
|
||||||
$RestartNowText = "Restart Now"
|
|
||||||
|
|
||||||
#endregion CUSTOMIZATIONS }
|
|
||||||
|
|
||||||
## Display the form
|
|
||||||
If ( $SysPerf ) { Display-Prompt $SysPerfText }
|
|
||||||
ElseIf ( $OSUpdate ) { Display-Prompt $OSUpdateText }
|
|
||||||
ElseIF ( $Uptime ) { Display-Prompt $UptimeText }
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
Function global:Set-WinEvtLog {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Enable/Disable an event log.
|
|
||||||
.DESCRIPTION
|
|
||||||
Enable or disable a Windows Event Log using the System.Diagnostics.Eventing.Reader.EventLogConfiguration object.
|
|
||||||
This function only outputs terminating errors to the console. If you want to see more detail use -verbose
|
|
||||||
.EXAMPLE
|
|
||||||
Set-WinEvtLog -Enable -Log "Microsoft-Windows-DNS-Client/Operational"
|
|
||||||
.EXAMPLE
|
|
||||||
Set-WinEvtLog -Disable -Log (Get-Content ListOfLogs.txt)
|
|
||||||
.EXAMPLE
|
|
||||||
Get-Content ListOfLogs.txt | Set-WinEvtLog -Enable
|
|
||||||
.PARAMETER Log
|
|
||||||
The log(s) to modIfy.
|
|
||||||
.PARAMETER Enable
|
|
||||||
Enables the log(s).
|
|
||||||
.PARAMETER Disable
|
|
||||||
Disables the log(s).
|
|
||||||
#>
|
|
||||||
|
|
||||||
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
|
|
||||||
param
|
|
||||||
(
|
|
||||||
[Parameter(Mandatory=$True,
|
|
||||||
ValueFromPipeline=$False,
|
|
||||||
ValueFromPipelineByPropertyName=$True,
|
|
||||||
HelpMessage='Which log do you want to enable?')]
|
|
||||||
[string[]]$Log,
|
|
||||||
[Parameter(Mandatory=$True,
|
|
||||||
ValueFromPipelineByPropertyName=$True,
|
|
||||||
ParameterSetName = 'Enable')]
|
|
||||||
[Switch]$Enable,
|
|
||||||
[Parameter(Mandatory=$True,
|
|
||||||
ValueFromPipelineByPropertyName=$True,
|
|
||||||
ParameterSetName = 'Disable')]
|
|
||||||
[Switch]$Disable
|
|
||||||
)
|
|
||||||
|
|
||||||
Begin
|
|
||||||
{
|
|
||||||
# Keep track of changes made to event logs in a separate file.
|
|
||||||
$RecordLog = "${Env:MSPDir}\Logs\WinEvtLogs-Enabled.log"
|
|
||||||
|
|
||||||
If ( !(Test-Path -Path $RecordLog) )
|
|
||||||
{
|
|
||||||
# Create the record keeping log file If it doesn't exist.
|
|
||||||
$NewFile = ((New-Item -Path $RecordLog -ItemType file).name | Out-String)
|
|
||||||
$NewFile = $NewFile.Trim()
|
|
||||||
Write-Verbose "$NewFile did not exist and has been created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process
|
|
||||||
{
|
|
||||||
# Make sure Record Keeping is properly configured, otherwise exit.
|
|
||||||
If ( !($RecordLog) )
|
|
||||||
{
|
|
||||||
Write-Verbose "The record keeping log does not exist, this function will not continue."
|
|
||||||
Return
|
|
||||||
}
|
|
||||||
|
|
||||||
# Loop through the name(s) in the $Log variable passed to this function.
|
|
||||||
ForEach ($name in $Log)
|
|
||||||
{
|
|
||||||
# Process the data only If the script should Process data.
|
|
||||||
If ( $pscmdlet.ShouldProcess($name, 'Enable Log') )
|
|
||||||
{
|
|
||||||
# Load the RecordLog into a variable.
|
|
||||||
$PreviouslyEnabledLogs = Get-Content $RecordLog
|
|
||||||
|
|
||||||
# Determine whether to Enable or Disable logging of the specIfied log.
|
|
||||||
Switch ($PSCmdlet.ParameterSetName)
|
|
||||||
{
|
|
||||||
'Enable' { $SetEnable = $True }
|
|
||||||
'Disable' { $SetEnable = $False }
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create a new object for the specIfied log.
|
|
||||||
$LogObject = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $name
|
|
||||||
|
|
||||||
# Set the variable to determine whether the log has been enabled by this script or not
|
|
||||||
$IsEnabledByFunction = $False
|
|
||||||
|
|
||||||
# Determine whether or not the log had been enabled by this function.
|
|
||||||
ForEach ($item in $PreviouslyEnabledLogs)
|
|
||||||
{ If ($item -eq $name) { $IsEnabledByFunction = $True } }
|
|
||||||
|
|
||||||
# Act based on whether the log is already enabled or not.
|
|
||||||
Switch ($logObject.IsEnabled)
|
|
||||||
{
|
|
||||||
$True
|
|
||||||
{
|
|
||||||
# Inform user whether this log has been enabled by this function or not.
|
|
||||||
If ($IsEnabledByFunction)
|
|
||||||
{ Write-Verbose "$name has previously been enabled by this function." }
|
|
||||||
Else { Write-Verbose "$name has previously been enabled, but not by this function." }
|
|
||||||
}
|
|
||||||
|
|
||||||
$False
|
|
||||||
{
|
|
||||||
# Inform user that this log has been disabled by something other than this function.
|
|
||||||
If ($IsEnabledByFunction)
|
|
||||||
{ Write-Verbose "$name should already be enabled by this function, but has been disabled by other means." }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ModIfy the log to either enable or disable it.
|
|
||||||
If ($LogObject.IsEnabled -eq $SetEnable)
|
|
||||||
{ Write-Verbose "$name is already in the desired state." }
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
# Set the log to the desired state.
|
|
||||||
$LogObject.IsEnabled = $SetEnable
|
|
||||||
|
|
||||||
# Save changes to the log.
|
|
||||||
$LogObject.SaveChanges()
|
|
||||||
|
|
||||||
# VerIfy the change has been made.
|
|
||||||
Switch ($LogObject.IsEnabled)
|
|
||||||
{
|
|
||||||
$True
|
|
||||||
{
|
|
||||||
Write-Verbose "$name has been enabled."
|
|
||||||
|
|
||||||
# Make sure this log wasn't already enabled by this function so we don't write the same name more than once in $RecordLog
|
|
||||||
If (!($IsEnabledByFunction)) { Add-Content -Path $RecordLog "$name" }
|
|
||||||
}
|
|
||||||
|
|
||||||
$False
|
|
||||||
{
|
|
||||||
# Remove $name from $RecordLog If it was put there by this function.
|
|
||||||
If ($IsEnabledByFunction)
|
|
||||||
{
|
|
||||||
# Clear the contents of $RecordLog
|
|
||||||
Clear-Content -Path $RecordLog
|
|
||||||
|
|
||||||
# Add each item back in that was already there except for the current $name
|
|
||||||
ForEach ($filename In $PreviouslyEnabledLogs)
|
|
||||||
{ If ($filename -ne $name) { Add-Content -Path $RecordLog $filename} }
|
|
||||||
}
|
|
||||||
Write-Verbose "$name has been disabled."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end {}
|
|
||||||
}
|
|
||||||
Export-ModuleMember -Function Set-WinEvtLog
|
|
||||||
@@ -6,7 +6,7 @@ function process_debian()
|
|||||||
apt-get update
|
apt-get update
|
||||||
|
|
||||||
## Upgrade packages
|
## Upgrade packages
|
||||||
apt-get upgrade -y
|
apt-get upgrade --with-new-pkgs -y
|
||||||
|
|
||||||
## Remove unused packages
|
## Remove unused packages
|
||||||
apt autoremove
|
apt autoremove
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
REM Windows Server 2012 x64
|
|
||||||
set Win62x64=https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/W2K12-KB3191565-x64.msu
|
|
||||||
set Win62x64File=W2K12-KB3191565-x64.msu
|
|
||||||
|
|
||||||
REM Windows 8.1 x86
|
|
||||||
set Win63x86=https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win8.1-KB3191564-x86.msu
|
|
||||||
set Win63x86File=Win8.1-KB3191564-x86.msu
|
|
||||||
|
|
||||||
REM Windows 8.1 and Server 2012 R2 x64
|
|
||||||
set Win63x64=https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win8.1AndW2K12R2-KB3191564-x64.msu
|
|
||||||
set Win63x64File=Win8.1AndW2K12R2-KB3191564-x64.msu
|
|
||||||
|
|
||||||
REM Windows 7 x86
|
|
||||||
set Win61x86=https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win7-KB3191566-x86.zip
|
|
||||||
set Win61x86File=Win7-KB3191566-x86.zip
|
|
||||||
|
|
||||||
Rem Windows 7 and Server 2008 R2 x64
|
|
||||||
set Win61x64=https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win7AndW2K8R2-KB3191566-x64.zip
|
|
||||||
set Win61x64File=Win7AndW2K8R2-KB3191566-x64.zip
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#Requires -version 2
|
|
||||||
|
|
||||||
## Get the Windows version information
|
|
||||||
$WinVersion = "{0}.{1}" -f ([System.Environment]::OSVersion.Version).Major,([System.Environment]::OSVersion.Version).Minor
|
|
||||||
$WinBuild = ([System.Environment]::OSVersion.Version).Build
|
|
||||||
|
|
||||||
## Get PowerShell version information
|
|
||||||
$CurrentVersion = "{0}.{1}" -f $PSVersionTable.PSVersion.Major,$PSVersionTable.PSVersion.Minor
|
|
||||||
|
|
||||||
## Check the OS architecture
|
|
||||||
If ( Test-Path -PathType Container -Path ${env:ProgramFiles(x86)} ) { $Is64bit = $true } Else { $Is64bit = $false }
|
|
||||||
|
|
||||||
## Set a variable to make sure the current Windows version is supported
|
|
||||||
$InstallSupported = $true
|
|
||||||
|
|
||||||
Switch ( $WinVersion ) {
|
|
||||||
|
|
||||||
## Windows Vista
|
|
||||||
"6.0" {
|
|
||||||
If ( $Is64bit ) { $URL = 'https://download.microsoft.com/download/E/7/6/E76850B8-DA6E-4FF5-8CCE-A24FC513FD16/Windows6.0-KB2506146-x64.msu' }
|
|
||||||
Else { $URL = 'https://download.microsoft.com/download/E/7/6/E76850B8-DA6E-4FF5-8CCE-A24FC513FD16/Windows6.0-KB2506146-x86.msu' }
|
|
||||||
$UpgradeVersion = 3.0
|
|
||||||
; break }
|
|
||||||
|
|
||||||
## Windows 7
|
|
||||||
"6.1" {
|
|
||||||
## PowerShell 4.0
|
|
||||||
If ( $Is64bit ) { $URL = 'https://download.microsoft.com/download/3/D/6/3D61D262-8549-4769-A660-230B67E15B25/Windows6.1-KB2819745-x64-MultiPkg.msu' }
|
|
||||||
Else { $URL = 'https://download.microsoft.com/download/3/D/6/3D61D262-8549-4769-A660-230B67E15B25/Windows6.1-KB2819745-x86-MultiPkg.msu' }
|
|
||||||
$UpgradeVersion = 4.0
|
|
||||||
; break }
|
|
||||||
|
|
||||||
## Windows 8
|
|
||||||
#"6.2" {; break }
|
|
||||||
|
|
||||||
## Windows 8.1
|
|
||||||
#"6.3" {; break }
|
|
||||||
|
|
||||||
## Windows 10
|
|
||||||
#"10.0" {; break }
|
|
||||||
|
|
||||||
## Not Supported
|
|
||||||
default { $InstallSupported = $false ; break }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Make sure installation is supported
|
|
||||||
If ( ($InstallSupported) -and ($CurrentVersion -lt $UpgradeVersion) ) {
|
|
||||||
|
|
||||||
## Get the file type so we install it the correct way
|
|
||||||
$FileType = ([System.IO.Path]::GetExtension($File)).ToUpper()
|
|
||||||
|
|
||||||
## Set the destination file for the downloaded package
|
|
||||||
$File = "${env:TEMP}\$(Split-Path -Leaf $URL)"
|
|
||||||
|
|
||||||
## Download the installation package
|
|
||||||
(New-Object Net.WebClient).DownloadFile($URL,$File)
|
|
||||||
|
|
||||||
If ( Test-Path $File ) {
|
|
||||||
|
|
||||||
## Get the file extension so we use the correct method to install the update
|
|
||||||
$FileType = [System.IO.Path]::GetExtension($File)
|
|
||||||
|
|
||||||
## Write a message so we know what version was upgraded.
|
|
||||||
Write-Host "Upgrading PowerShell ${CurrentVersion} to version ${UpgradeVersion}"
|
|
||||||
|
|
||||||
## Install the package
|
|
||||||
If ( $FileType -ieq "MSU" ) { Start-Process wusa.exe -ArgumentList "${File} /quiet /norestart" -Wait }
|
|
||||||
If ( $FileType -ieq "MSI" ) { Start-Process msiexec.exe -ArgumentList "/i ${File} /qn /norestart" -Wait }
|
|
||||||
|
|
||||||
## Delete the downloaded package
|
|
||||||
Remove-Item -Path $File -Force
|
|
||||||
}
|
|
||||||
|
|
||||||
} Else { Write-Host "This script cannot upgrade PowerShell on this endpoint." }
|
|
||||||
@@ -426,4 +426,20 @@ Function Create-Shortcut {
|
|||||||
Catch { LogErr $_.Exception.Message }
|
Catch { LogErr $_.Exception.Message }
|
||||||
}
|
}
|
||||||
Else { LogMsg "Cannot create shortcut because the target path does not exist" }
|
Else { LogMsg "Cannot create shortcut because the target path does not exist" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to enable or disable a specified log
|
||||||
|
function Toggle-Log {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true)][string]$Name,
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = 'Enable')][switch]$Enable,
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = 'Disable')][switch]$Disable
|
||||||
|
)
|
||||||
|
Try {
|
||||||
|
$log = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $Name
|
||||||
|
If ( $Enable ) { $log.IsEnabled = $true }
|
||||||
|
If ( $Disable ) { $log.IsEnabled = $false }
|
||||||
|
$log.SaveChanges()
|
||||||
|
}
|
||||||
|
Catch { LogMsg $_.Exception.Message }
|
||||||
}
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
@echo off
|
|
||||||
if exist "%ProgramFiles(x86)%\CCleaner Cloud\uninst.exe" start "" /w "%ProgramFiles(x86)%\CCleaner Cloud\uninst.exe" /S
|
|
||||||
goto end
|
|
||||||
if exist "%ProgramFiles%\CCleaner Cloud\uninst.exe" start "" /w "%ProgramFiles%\CCleaner Cloud\uninst.exe" /S
|
|
||||||
:end
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
$AppList = @(
|
$AppList = @(
|
||||||
## Office Apps
|
## Office Apps
|
||||||
'Microsoft.Office.Sway',
|
'Microsoft.Office.Sway',
|
||||||
'Microsoft.Office.OneNote',
|
#'Microsoft.Office.OneNote',
|
||||||
'Microsoft.MicrosoftOfficeHub',
|
'Microsoft.MicrosoftOfficeHub',
|
||||||
'Microsoft.Office.Desktop',
|
'Microsoft.Office.Desktop',
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
If ( Test-Path "${Env:SystemDrive}\ProgramData\Autodesk\Revit Server 2016\Config\RSN.ini")
|
|
||||||
{
|
|
||||||
Remove-Item "${Env:SystemDrive}\ProgramData\Autodesk\Revit Server 2016\Config\RSN.ini"
|
|
||||||
$server = "va01rvt02.dbia.com"
|
|
||||||
$server | Out-File "${Env:SystemDrive}\ProgramData\Autodesk\Revit Server 2016\Config\RSN.ini"
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
param (
|
|
||||||
[string]$Path,
|
|
||||||
[string]$Password,
|
|
||||||
[int]$SpeedLimit=300,
|
|
||||||
[switch]$SelfDestruct
|
|
||||||
)
|
|
||||||
|
|
||||||
## Immediately delete this script from disk, if requested
|
|
||||||
if ( $SelfDestruct ) {
|
|
||||||
try { Remove-Item $MyINvocation.InvocationName -Force }
|
|
||||||
catch { Write-Host "Self destruct failed, killing script!"; exit } }
|
|
||||||
|
|
||||||
## Download required tools
|
|
||||||
$DOWNLOAD_TOOLS_SCRIPT = "https://emberkom.s3.amazonaws.com/management/scripts/Download-Tools.ps1"
|
|
||||||
try { Invoke-Expression ((New-Object System.Net.WebClient).DownloadString($DOWNLOAD_TOOLS_SCRIPT)) }
|
|
||||||
catch { Write-Host "Required tools failed to download!"; exit }
|
|
||||||
|
|
||||||
## Make sure WinSCP exists
|
|
||||||
$WINSCP = "${Env:Temp}\Emberkom\Tools\winscp.com"
|
|
||||||
if ( !(Test-Path "${WINSCP}") ) {
|
|
||||||
if ( Test-Path "${Env:ProgramData}\Emberkom\Tools\winscp.com" ) {
|
|
||||||
$WINSCP = "${Env:ProgramData}\Emberkom\Tools\winscp.com"
|
|
||||||
} else { Write-Host "WinSCP does not exist!"; exit } }
|
|
||||||
|
|
||||||
## Prepare WinSCP script file
|
|
||||||
$HOSTNAME = 'xfer.emberkom.net'
|
|
||||||
$HOSTKEY = 'ecdsa-sha2-nistp256 256 5iJFeMzLK5Ld7gbLn+NlcYyI+DvbSXB8fmFJLLDh7s0='
|
|
||||||
$USERNAME = 'JeQCXVBI80Pj3nL'
|
|
||||||
#$PASSWORD = ''
|
|
||||||
$SCRIPT_FILE = [System.IO.Path]::GetTempFileName()
|
|
||||||
$UPLOAD_SCRIPT = @(
|
|
||||||
"echo off",
|
|
||||||
"option batch on",
|
|
||||||
"option confirm off",
|
|
||||||
"open sftp://${USERNAME}:${Password}@${HOSTNAME}/ -hostkey=`"${HOSTKEY}`"",
|
|
||||||
"mkdir `"${Env:ComputerName}`"",
|
|
||||||
"cd `"${Env:ComputerName}`"",
|
|
||||||
"mkdir `"${Env:Username}`"",
|
|
||||||
"cd `"${Env:Username}`"",
|
|
||||||
"mkdir `"Manual Upload`"",
|
|
||||||
"cd `"Manual Upload`"",
|
|
||||||
"put -resume -nopermissions -preservetime -speed=${SpeedLimit} -resumesupport=on -neweronly `"${Path}`"",
|
|
||||||
"exit")
|
|
||||||
try { ForEach ($line in $UPLOAD_SCRIPT) { $line | Out-File "${SCRIPT_FILE}" -Append } }
|
|
||||||
catch { Write-Host "Script file could not be created: ${SCRIPT_FILE}"; exit }
|
|
||||||
|
|
||||||
## Upload the data
|
|
||||||
try { Start-Process -WindowStyle Hidden "${WINSCP}" -ArgumentList "/script=`"${SCRIPT_FILE}`"" -Wait }
|
|
||||||
catch { Write-Host "Data transfer failed!" }
|
|
||||||
|
|
||||||
## Delete the script file
|
|
||||||
try { Remove-Item -Path "${SCRIPT_FILE}" -Force }
|
|
||||||
catch { Write-Host "Script file could not be deleted: ${SCRIPT_FILE}" }
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
param (
|
|
||||||
[string]$Path,
|
|
||||||
[string]$Filedrop = 'https://xfer.emberkom.net/filedrop/cmd',
|
|
||||||
[string]$From,
|
|
||||||
[string]$Subject = "Upload from ${Env:COMPUTERNAME}",
|
|
||||||
[string]$Message = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
## Build the from address if it isn't specified
|
|
||||||
If ( !($From) )
|
|
||||||
{
|
|
||||||
If ( "${Env:USERDOMAIN}" -eq "${Env:COMPUTERNAME}" ) { $From = "${Env:COMPUTERNAME}@localdomain.local".ToLower() }
|
|
||||||
Else { $From = "${Env:COMPUTERNAME}@${Env:USERDOMAIN}".ToLower() }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Download required tools
|
|
||||||
$DOWNLOAD_TOOLS_SCRIPT = "https://emberkom.s3.amazonaws.com/management/scripts/Download-Tools.ps1"
|
|
||||||
Try { Invoke-Expression ((New-Object System.Net.WebClient).DownloadString($DOWNLOAD_TOOLS_SCRIPT)) }
|
|
||||||
Catch { Write-Host "Required tools failed to download!" }
|
|
||||||
|
|
||||||
## Get the path to the LiquidFilesCLI application
|
|
||||||
If ( Test-Path "${Env:ProgramData}\Emberkom\Tools\LiquidFilesCLI.exe" ) { $LFCLI = "${Env:ProgramData}\Emberkom\Tools\LiquidFilesCLI.exe" }
|
|
||||||
ElseIf ( Test-Path "${Env:AppData}\Emberkom\Tools\LiquidFilesCLI.exe" ) { $LFCLI = "${Env:AppData}\Emberkom\Tools\LiquidFilesCLI.exe" }
|
|
||||||
Else { Write-Host "Could not find LiquidFilesCLI.exe"; exit }
|
|
||||||
|
|
||||||
## Get the path to the 7za.exe application
|
|
||||||
If ( Test-Path "${Env:ProgramData}\Emberkom\Tools\7za.exe" ) { $ZIPUTIL = "${Env:ProgramData}\Emberkom\Tools\7za.exe" }
|
|
||||||
ElseIf ( Test-Path "${Env:AppData}\Emberkom\Tools\7za.exe" ) { $ZIPUTIL = "${Env:AppData}\Emberkom\Tools\7za.exe" }
|
|
||||||
Else { Write-Host "Could not find 7za.exe"; exit }
|
|
||||||
|
|
||||||
## Set the base args
|
|
||||||
$ARGS = "filedrop /url:${Filedrop} /from:`"${From}`" /subject:`"${Subject}`" /msg:`"${Message}`" /c:s"
|
|
||||||
|
|
||||||
## Make sure $Path exists
|
|
||||||
If ( Test-Path $Path )
|
|
||||||
{
|
|
||||||
## If $Path is a folder...
|
|
||||||
If ( Test-Path $Path -PathType Container )
|
|
||||||
{
|
|
||||||
## Set the archive type
|
|
||||||
$ARCHIVE_TYPE = "7z"
|
|
||||||
|
|
||||||
## Set the temporary archive
|
|
||||||
$TEMP_PATH = [System.IO.Path]::GetTempPath()
|
|
||||||
$TEMP_FILE = Split-Path $Path -Leaf
|
|
||||||
$TEMP_ARCHIVE = "${TEMP_PATH}${TEMP_FILE}.${ARCHIVE_TYPE}"
|
|
||||||
|
|
||||||
## Delete $TEMP_ARCHIVE if it somehow already exists
|
|
||||||
If ( Test-Path $TEMP_ARCHIVE ) { Remove-Item $TEMP_ARCHIVE -Force }
|
|
||||||
|
|
||||||
## Compress the folder into the archive
|
|
||||||
Try { Start-Process -WindowStyle Hidden "${ZIPUTIL}" -ArgumentList "a -r -t${ARCHIVE_TYPE} -w `"${TEMP_ARCHIVE}`" `"${Path}`"" -Wait }
|
|
||||||
Catch { Write-Host "Could not create ${TEMP_ARCHIVE}"; exit }
|
|
||||||
|
|
||||||
$ARGS = "${ARGS} /f:`"${TEMP_ARCHIVE}`""
|
|
||||||
}
|
|
||||||
|
|
||||||
## If $Path is a file...
|
|
||||||
ElseIf ( Test-Path $Path -PathType Leaf ) { $ARGS = "${ARGS} /f:`"${Path}`"" }
|
|
||||||
|
|
||||||
## If $Path doesn't exist...
|
|
||||||
Else { Write-Host "${Path} doesn't exist!"; exit }
|
|
||||||
}
|
|
||||||
|
|
||||||
## Upload the file
|
|
||||||
Try { Start-Process -WindowStyle Hidden "${LFCLI}" -ArgumentList "${ARGS}" -Wait }
|
|
||||||
Catch { Write-Host "Upload failed!" }
|
|
||||||
|
|
||||||
## Delete the local archive (if it exists)
|
|
||||||
Finally { If ( Test-Path $TEMP_ARCHIVE ) { Remove-Item $TEMP_ARCHIVE -Force } }
|
|
||||||
Reference in New Issue
Block a user