2020-09-23 21:32:50 -04:00
## Define the MSP name
2020-09-09 21:06:44 -04:00
$MSPName = "Emberkom"
## 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"
## Make sure all the management directories exist
2020-09-23 21:31:52 -04:00
$MSPRoot , $MSPScripts , $MSPTools , $MSPLogs | ForEach-Object {
If ( !( Test-Path $_ ) )
{
2020-10-22 14:01:35 -04:00
Try { New-Item -Path $_ -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null }
Catch { Write-Output $_ . Exception . Message }
2020-09-23 21:31:52 -04:00
}
}
2020-09-09 21:06:44 -04:00
2020-10-22 14:01:35 -04:00
## Setup the log file for messages generated when this script is run
$LogFile = '{0}\ManagementScript_{1}.log' -f $MSPLogs , ( Get-Date -Format "yyyyMMddHHmmss" )
If ( !( Test-Path $LogFile ) ) { New-Item -Path $LogFile -ItemType File -Force | Out-Null }
2020-09-19 15:29:31 -04:00
2020-09-07 13:43:37 -04:00
## Function to log activity to the configured log directory
2020-09-09 21:06:44 -04:00
Function Log
2020-09-07 13:43:37 -04:00
{
2020-09-19 11:14:01 -04:00
param (
2020-09-19 13:27:09 -04:00
[ Parameter ( Mandatory = $true , ValueFromPipeline = $true )][ string ] $Message ,
2020-09-19 16:40:07 -04:00
[ Parameter ( Mandatory = $false )][ switch ] $Error = $false ,
2020-09-21 09:47:00 -04:00
[ Parameter ( Mandatory = $false )][ string ] $Name
2020-09-19 11:14:01 -04:00
)
2020-09-19 16:40:07 -04:00
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
If ( $Error ) { $LogEntry = " ${Timestamp} - Error: ${Message} " }
Else { $LogEntry = " ${Timestamp} - ${Message} " }
2020-10-22 14:01:35 -04:00
Add-Content -Path $LogFile -Value $LogEntry
Write-Output $LogEntry
}
## Log a message to the log file
Function LogMsg
2020-09-09 21:06:44 -04:00
{
2020-10-22 14:01:35 -04:00
param ([ Parameter ( Mandatory = $true , ValueFromPipeline = $true )][ string ] $Message )
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogEntry = " ${Timestamp} - ${Message} "
Add-Content -Path $LogFile -Value $LogEntry
#Write-Output $LogEntry
2020-09-09 21:06:44 -04:00
}
2020-10-22 14:01:35 -04:00
## Log an error to the log file
Function LogErr
{
param ([ Parameter ( Mandatory = $true , ValueFromPipeline = $true )][ string ] $Message )
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogEntry = " ${Timestamp} - Error: ${Message} "
Add-Content -Path $LogFile -Value $LogEntry
#Write-Output "Error: ${LogEntry}"
2020-09-07 13:43:37 -04:00
}
## Function to determine if the current user context is an Administrator
2020-09-09 21:06:44 -04:00
Function IsAdmin
2020-09-07 13:43:37 -04:00
{
If ( ([ Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity ]:: GetCurrent ()). IsInRole ([ Security.Principal.WindowsBuiltInRole ]:: Administrator ) )
{ Return $true } Else { Return $false }
}
2020-09-23 15:24:26 -04:00
## Run a script from the live repo or from a local path
2020-09-23 15:28:43 -04:00
Function Run-Script
2020-09-23 15:24:26 -04:00
{
param (
## Parameters for live-ps scripts
[ Parameter ( Mandatory = $false , ParameterSetName = 'live-ps' )]
[ string ] $Type = 'management-scripts' ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'live-ps' )]
[ string ] $LivePSScript ,
## Parameters for local scripts
[ Parameter ( Mandatory = $true , ParameterSetName = 'local' )]
[ string ] $Path ,
2020-09-23 20:43:29 -04:00
#### $NoWait will prevent waiting for the specified script to finish running
[ Parameter ( Mandatory = $false , ParameterSetName = 'local' )]
[ switch ] $NoWait = $false ,
2020-09-23 15:24:26 -04:00
## Parameters for all scripts
[ Parameter ( Mandatory = $false , ParameterSetName = 'live-ps' )]
[ Parameter ( Mandatory = $false , ParameterSetName = 'local' )]
[ string ] $Arguments = 'null' ,
2020-09-23 20:43:29 -04:00
#### $HaltIfRunning is a collection of app names which, if running, will prevent the script from running
[ Parameter ( Mandatory = $false , ParameterSetName = 'live-ps' )]
[ Parameter ( Mandatory = $false , ParameterSetName = 'local' )]
2020-09-24 13:04:06 -04:00
[ string[] ] $HaltIfRunning = 'null' ,
2020-09-23 20:43:29 -04:00
#### $ForceClose will forcefully close all apps specified in $HaltIfRunning
2020-09-23 15:24:26 -04:00
[ Parameter ( Mandatory = $false , ParameterSetName = 'live-ps' )]
[ Parameter ( Mandatory = $false , ParameterSetName = 'local' )]
2020-09-23 20:43:29 -04:00
[ switch ] $ForceClose = $false
2020-09-23 15:24:26 -04:00
)
If ( $Arguments -eq "null" ) { $Arguments = $null }
2020-09-24 13:04:06 -04:00
If ( $HaltIfRunning -eq "null" ) { $HaltIfRunning = $null }
2020-09-23 21:52:25 -04:00
If ( $LivePSScript )
{
$URL = "https://dev.emberkom.com/emberkom/ ${Type} /raw/branch/master/ ${LivePSScript} .ps1"
2020-10-22 14:01:35 -04:00
If ( !( IsURLValid -URL $URL ) ) { LogMsg "The specified script does not exist: ${LivePSScript} " ; Exit }
2020-09-23 21:52:25 -04:00
}
2020-10-22 14:01:35 -04:00
If ( $Path ) { If ( !( Test-Path $Path ) ) { LogMsg "The specified script does not exist: "" ${Path} """ ; Exit } }
If ( ( $HaltIfRunning -ne $null ) -and ( $ForceClose ) -and ( !( IsAdmin ) ) ) { LogMsg "Cannot close dependent apps because this task does not have administrative privileges" ; Exit }
2020-09-23 20:43:29 -04:00
If ( $HaltIfRunning )
{
$Halt = $false
2020-10-22 14:01:35 -04:00
LogMsg "Checking for running instances of the following dependent apps:"
2020-09-23 20:43:29 -04:00
ForEach ( $name in $HaltIfRunning )
{
$RunningInstances = Get-Process | Where { $_ . Name -like " ${name} " }
If ( $RunningInstances )
{
2020-09-23 21:31:52 -04:00
If ( $ForceClose -eq $true )
{
Try { $name | Stop-Process -Force }
2020-10-22 14:01:35 -04:00
Catch { LogErr $_ . Exception . Message ; Exit }
2020-09-23 21:31:52 -04:00
Log " "" ${name} "" (force closed)" -Name $LogName
}
2020-10-22 14:01:35 -04:00
Else { $Halt = $true ; LogMsg " "" ${name} "" (running)" }
2020-09-23 20:43:29 -04:00
}
2020-10-22 14:01:35 -04:00
Else { LogMsg " "" ${name} "" (not running)" }
2020-09-23 20:43:29 -04:00
}
2020-10-22 14:01:35 -04:00
If ( $Halt -eq $true ) { LogMsg "Dependent apps are currently in use and are preventing the specified script from running" ; Exit }
2020-09-23 20:43:29 -04:00
}
2020-09-23 15:24:26 -04:00
switch ( $PSCmdlet . ParameterSetName )
{
'live-ps'
{
2020-10-22 14:01:35 -04:00
LogMsg "Retrieving : ${LivePSScript} .ps1"
2020-09-23 15:24:26 -04:00
Try { $Script = ( New-Object Net . WebClient ). DownloadString ( $URL ) }
2020-10-22 14:01:35 -04:00
Catch { LogErr $_ . Exception . Message ; Exit }
2020-09-23 15:24:26 -04:00
Try { $ScriptBlock = [ Scriptblock ]:: Create ( $Script ) }
2020-10-22 14:01:35 -04:00
Catch { LogErr $_ . Exception . Message ; Exit }
LogMsg "Executing: ${LivePSScript} .ps1 ${Arguments} "
2020-09-23 15:24:26 -04:00
Try { Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $Arguments }
2020-10-22 14:01:35 -04:00
Catch { LogErr $_ . Exception . Message ; Exit }
2020-09-23 15:24:26 -04:00
}
'local'
{
2020-10-22 14:01:35 -04:00
LogMsg "Executing: ${Path} ${Arguments} "
If ( $NoWait )
2020-09-23 15:24:26 -04:00
{
2020-10-22 14:01:35 -04:00
Try { Start-Process " ${Path} " -ArgumentList "{ $Arguments }" }
Catch { LogErr $_ . Exception . Message }
}
Else
{
LogMsg " Waiting for script to finish..."
Try { Start-Process " ${Path} " -ArgumentList "{ $Arguments }" -Wait }
Catch { LogErr $_ . Exception . Message }
LogMsg " Finished"
2020-09-23 15:24:26 -04:00
}
}
}
}
2020-10-22 14:01:35 -04:00
## Return a Powershell version object from a string
2020-09-07 13:43:37 -04:00
Function Get-Version
{
2020-09-21 09:47:00 -04:00
param ([ Parameter ( Mandatory = $true )][ string ] $Version )
2020-09-07 13:43:37 -04:00
[ int ] $Sets = 4
$VersionArray = $Version . Split ( '.' )
If ( $VersionArray . Count -le $Sets ) { $Sets = $VersionArray . Count }
For ( $i = 0 ; $i -le ( $Sets - 1 ); $i ++)
{ $Return = '{0}.{1}' -f $Return , $VersionArray [ $i ] }
Return [ version ] $Return . Trim ( '.' )
2020-09-07 20:18:06 -04:00
}
2020-09-23 21:52:25 -04:00
## Determines whether a URL is valid
Function IsURLValid
{
param ([ Parameter ( Mandatory = $true , ValueFromPipeline = $true )][ string ] $URL )
2020-10-19 11:24:07 -04:00
Try
{
$HTTPRequest = [ System.Net.WebRequest ]:: Create ( $URL )
$HTTPResponse = $HTTPRequest . GetResponse ()
$HTTPStatus = [ int ] $HTTPResponse . StatusCode
$HTTPResponse . Close ()
}
Catch {}
2020-09-23 21:52:25 -04:00
If ( $HTTPStatus -eq 200 ) { Return $true }
Else { Return $false }
}
2020-10-22 14:01:35 -04:00
## Downloads a file from a URL
2020-10-19 11:24:07 -04:00
Function Download-File
{
param (
[ Parameter ( Mandatory = $true , ValueFromPipeline = $true )][ string ] $URL ,
[ Parameter ( Mandatory = $false , ValueFromPipeline = $false )][ string ] $File
)
2020-10-22 14:01:35 -04:00
If ( !( $File ) ) { $File = '{0}{1}' -f ( GetTempPath ), ( Split-Path $URL -Leaf ) }
2020-10-19 11:24:07 -04:00
If ( IsURLValid $URL )
{
If ( Test-Path $File )
{
2020-10-22 14:01:35 -04:00
LogMsg "Deleting existing file: "" ${File} """
2020-10-19 11:24:07 -04:00
Try { Remove-Item $File -Force }
2020-10-22 14:01:35 -04:00
Catch { LogErr $_ . Exception . Message }
2020-10-19 11:24:07 -04:00
}
2020-10-22 14:01:35 -04:00
LogMsg "Downloading "" ${URL} "" to "" ${File} """
2020-10-19 11:24:07 -04:00
Try { ( New-Object System . Net . WebClient ). DownloadFile ( $URL , $File ) }
2020-10-22 14:01:35 -04:00
Catch { LogErr $_ . Exception . Message }
If ( Test-Path " ${File} " ) { Return " ${File} " }
Else { LogMsg "Downloaded file does not exist at "" ${File} """ ; Return $false }
}
Else { LogMsg "URL is not valid or file cannot be reached: ${URL} " }
}
## Install a program from a provided path
Function Install-Program
{
param (
[ Parameter ( Mandatory = $true )][ string ] $Path ,
[ Parameter ( Mandatory = $false )][ string ] $Arguments = '' ,
[ Parameter ( Mandatory = $false )][ switch ] $Delete = $false
)
If ( Test-Path " ${Path} " )
{
LogMsg "Running installer: "" ${Path} "" ${Arguments} "
Try { Start-Process " ${Path} " -ArgumentList " ${Arguments} " -Wait }
Catch { LogErr $_ . Exception . Message }
LogMsg "Installer finished"
If ( $Delete )
{
LogMsg "Deleting installer: "" ${Path} """
Try { Remove-Item -Path " ${Path} " -Force }
Catch { LogErr $_ . Exception . Message }
}
2020-10-19 11:24:07 -04:00
}
2020-10-22 14:01:35 -04:00
Else { LogMsg "The specified file could not be found: "" ${Path} """ }
2020-10-19 11:24:07 -04:00
}
2020-09-07 20:18:06 -04:00
## Function to compare current Windows version with a supplied version
2020-09-09 16:59:40 -04:00
## The value supplied must be a string and must include at least 1 decimal
2020-09-07 20:18:06 -04:00
Function IsWindowsVersion
{
param (
2020-09-09 16:46:21 -04:00
[ Parameter ( Mandatory = $true , ParameterSetName = 'gt' )][ string ] $gt ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'ge' )][ string ] $ge ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'lt' )][ string ] $lt ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'le' )][ string ] $le ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'eq' )][ string ] $eq
2020-09-07 20:18:06 -04:00
)
[ version ] $WindowsVersion = [ System.Environment ]:: OSVersion . Version
switch ( $PSCmdlet . ParameterSetName )
{
'gt' { If ( $WindowsVersion -gt ( Get-Version $gt ) ) { Return $true } Else { Return $false } }
'ge' { If ( $WindowsVersion -ge ( Get-Version $ge ) ) { Return $true } Else { Return $false } }
'lt' { If ( $WindowsVersion -lt ( Get-Version $lt ) ) { Return $true } Else { Return $false } }
'le' { If ( $WindowsVersion -le ( Get-Version $le ) ) { Return $true } Else { Return $false } }
'eq' { If ( $WindowsVersion -eq ( Get-Version $eq ) ) { Return $true } Else { Return $false } }
}
2020-09-09 16:46:21 -04:00
}
2020-10-22 14:01:35 -04:00
## Compare current Windows build with a supplied version
2020-09-09 16:59:40 -04:00
## The value supplied must be an int
2020-09-09 16:46:21 -04:00
Function IsWindowsBuild
{
param (
2020-09-09 16:59:40 -04:00
[ Parameter ( Mandatory = $true , ParameterSetName = 'gt' )][ int ] $gt ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'ge' )][ int ] $ge ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'lt' )][ int ] $lt ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'le' )][ int ] $le ,
[ Parameter ( Mandatory = $true , ParameterSetName = 'eq' )][ int ] $eq
2020-09-09 16:46:21 -04:00
)
[ int ] $WindowsBuild = [ System.Environment ]:: OSVersion . Version . Build
switch ( $PSCmdlet . ParameterSetName )
{
'gt' { If ( $WindowsBuild -gt $gt ) { Return $true } Else { Return $false } }
'ge' { If ( $WindowsBuild -ge $ge ) { Return $true } Else { Return $false } }
'lt' { If ( $WindowsBuild -lt $lt ) { Return $true } Else { Return $false } }
'le' { If ( $WindowsBuild -le $le ) { Return $true } Else { Return $false } }
'eq' { If ( $WindowsBuild -eq $eq ) { Return $true } Else { Return $false } }
}
2020-09-25 13:13:03 -04:00
}
2020-10-22 14:01:35 -04:00
## Get the path to the TEMP folder (context dependant)
Function GetTempPath
{ Return [ System.IO.Path ]:: GetTempPath () }
## Determine if the system is 64-bit or not
2020-09-25 13:13:03 -04:00
Function Is64bit
{
switch ( $ ( Get-CimInstance -ClassName Win32_OperatingSystem -Property OSArchitecture | Select-Object -ExpandProperty OSArchitecture ) )
{ '64-bit' { Return $true } '32-bit' { Return $false } }
}
2020-10-22 14:01:35 -04:00
## Determine if the Powershell process is 64-bit or not
2020-09-25 13:13:03 -04:00
Function Is64bitShell
2020-09-26 12:33:52 -04:00
{ If ( [ System.Environment ]:: Is64BitProcess ) { Return $true } Else { Return $false } }
2020-10-19 11:24:07 -04:00
2020-10-22 14:01:35 -04:00
## Determine if a user is in a built-in role or specified group
Function IsMemberOf {
param (
[ Parameter ( Mandatory = $false )]
[ switch ] $Builtin = $false ,
[ Parameter ( Mandatory = $true , ValueFromPipeline = $true )]
[ string ] $Group
)
If ( $Builtin ) {
Switch ( $Group ) {
( "Administrator" -or "Administrators" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: Administrator ; break }
( "Backup Operator" -or "Backup Operators" -or "BackupOperator" -or "BackupOperators" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: BackupOperator ; break }
( "System Operator" -or "System Operators" -or "SystemOperator" -or "SystemOperators" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: SystemOperator ; break }
( "Account Operator" -or "Account Operators" -or "AccountOperator" -or "AccountOperators" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: AccountOperator ; break }
( "Print Operator" -or "Print Operators" -or "PrintOperator" -or "PrintOperators" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: PrintOperator ; break }
( "Replicator" -or "Replicators" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: Replicator ; break }
( "Power User" -or "Power Users" -or "PowerUser" -or "PowerUsers" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: PowerUser ; break }
( "User" -or "Users" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: User ; break }
( "Guest" -or "Guests" )
{ $Group = [ System.Security.Principal.WindowsBuiltInRole ]:: Guest ; break }
default { ; break }
}
}
Return ([ Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity ]:: GetCurrent ()). IsInRole ( $Group )
}