Forum

You need to log in to create posts and topics.

Disable Shutdown/Restart button

This script can be used to disable the shutdown and restart buttons in Windows systems. Useful if you need to deny users the ability to shutdown their computers. You need to include psexec.exe in the same path as the script to enable WinRM remotely if it isn't already.

Remove-Shutdown.ps1

Param ( 
  [string]$file = 'computers.txt',
  [int]$MaxThreads = 20
)

# Get current directory
$scriptpath = $MyInvocation.MyCommand.Path
$currentdir = Split-Path $scriptpath

# Get list of objects
$computers = Get-Content "$currentdir\$file"

# Set file names
$LogFile = $currentdir + "\log\log-$(Get-Date -Format 'yyyyMMdd-HHmm').txt"
$ReportFile = $currentdir + "\log\report-$(Get-Date -Format 'yyyyMMdd-HHmm').csv"

# Create report header
$ReportHeader = '"ComputerName","Status"'
Add-Content -Path $ReportFile -Value $ReportHeader

# Set Error Action
$ErrorActionPreference = 'Ignore'

$args = "-RegistryInstance @{'Name' = 'NoClose'; 'Type' = 'Dword'; 'Value' = '1'; 'Path' = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer'}"

function Set-RegistryValueForAllUsers { 
    
    [CmdletBinding()] 
    param ( 
        [Parameter(Mandatory=$true)]
        [string]$args, 
        [hashtable[]]$RegistryInstance 
        
    ) 
    
    try { 
        New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 
         
        ## Change the registry values for the currently logged on user. 
        $LoggedOnSids = (Get-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' }).PSChildName 
        Update-Log "Found $($LoggedOnSids.Count) logged on user SIDs" 
        foreach ($sid in $LoggedOnSids) { 
            Update-Log "Loading the user registry hive for the logged on SID $sid" 
            foreach ($instance in $RegistryInstance) { 
                ## Create the key path if it doesn't exist 
                New-Item -Path "HKU:\$sid\$($instance.Path | Split-Path -Parent)" -Name ($instance.Path | Split-Path -Leaf) -Force | Out-Null 
                ## Create (or modify) the value specified in the param 
                Set-ItemProperty -Path "HKU:\$sid\$($instance.Path)" -Name $instance.Name -Value $instance.Value -Type $instance.Type -Force 
            } 
        } 
        
        ## Create the Active Setup registry key so that the reg add cmd will get ran for each user 
        ## logging into the machine. 
  
        Update-Log "Setting Active Setup registry value to apply to all other users" 
        foreach ($instance in $RegistryInstance) { 
            ## Generate a unique value (usually a GUID) to use for Active Setup 
            $Guid = [guid]::NewGuid().Guid 
            $ActiveSetupRegParentPath = 'HKLM:\Software\Microsoft\Active Setup\Installed Components' 
            ## Create the GUID registry key under the Active Setup key 
            New-Item -Path $ActiveSetupRegParentPath -Name $Guid -Force | Out-Null 
            $ActiveSetupRegPath = "HKLM:\Software\Microsoft\Active Setup\Installed Components\$Guid" 
            
             
             
            switch ($instance.Type) { 
                'String' { 
                    $RegValueType = 'REG_SZ' 
                } 
                'Dword' { 
                    $RegValueType = 'REG_DWORD' 
                } 
                'Binary' { 
                    $RegValueType = 'REG_BINARY' 
                } 
                'ExpandString' { 
                    $RegValueType = 'REG_EXPAND_SZ' 
                } 
                'MultiString' { 
                    $RegValueType = 'REG_MULTI_SZ' 
                } 
                default { 
                    throw "Registry type '$($instance.Type)' not recognized" 
                } 
            } 
             
            ## Build the registry value to use for Active Setup which is the command to create the registry value in all user hives 
            $ActiveSetupValue = "reg add `"{0}`" /v {1} /t {2} /d {3} /f" -f "HKCU\$($instance.Path)", $instance.Name, $RegValueType, $instance.Value 
            Update-Log -Message "Active setup value is '$ActiveSetupValue'" 
            ## Create the necessary Active Setup registry values 
            Set-ItemProperty -Path $ActiveSetupRegPath -Name '(Default)' -Value 'Active Setup Test' -Force 
            Set-ItemProperty -Path $ActiveSetupRegPath -Name 'Version' -Value '1' -Force 
            Set-ItemProperty -Path $ActiveSetupRegPath -Name 'StubPath' -Value $ActiveSetupValue -Force 
        } 
    } catch { 
        Write-Warning -Message $_.Exception.Message 
    } 
}


Function Update-Log
{
  Param ( [string]$logstring )
  
  $logstring = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'): $logstring"
  Update-Log $logstring
  Add-content $LogFile -value $logstring
}

Function Set-PSRemoting
{
  Param ( [string]$address )
  
  $command = $currentdir + "\psexec.exe"
  $run = "$currentdir\winrm.bat"
  
  $comp = '\\' + $address
    
  Update-Log "-- Checking if WinRM is configured for remote management"
  If (-not(Test-WSMan -ComputerName $address -ErrorAction Ignore)) {
    Write-Host "-- Running WinRM quickconfig"
    & $command $comp -h -accepteula -s -c $run
  }
}




Function Update-Log
{
  Param ( [string]$logstring )
  
  $logstring = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'): $logstring"
  Write-Host $logstring
  Add-content $LogFile -value $logstring
}

Function Set-PSRemoting
{
  Param ( [string]$address )
  
  $command = $currentdir + "\psexec.exe"
  $run = "$currentdir\winrm.bat"
  
  $comp = '\\' + $address
    
  Update-Log "-- Checking if WinRM is configured for remote management"
  If (-not(Test-WSMan -ComputerName $address -ErrorAction Ignore)) {
    Write-Host "-- Running WinRM quickconfig"
    & $command $comp -h -accepteula -s -c $run
  }
}


#Create Runspace Pool
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $MaxThreads)
$RunspacePool.Open()
$Jobs = @()




Foreach ($computer in $computers)
{
  Update-Log "$('-' * 50)"
  Update-Log "Processing $computer"
  Update-Log "$('-' * 50)"
  
  Try
  {
    If (Test-Connection -ComputerName $computer -Quiet -Count 1 )
    {
      Update-Log "-- $computer is online"
      
      Set-PSRemoting $computer


# Change the Value Key to a 1 to disable shutdown/restart, set to 0 to allow shutdown/restart

Invoke-Command -ComputerName $computer -ScriptBlock ${ Set-RegistryValueForAllUsers } -ArgumentList $args



          
          
          
          
          $row = '"' + $computer + '","Complete"'
          Add-Content -Path $ReportFile -Value $row
        
        
        
      
      
      Update-Log "-- Adding to runspace queue"

      #Create Thread For Each Target
      $Job = [Powershell]::Create().AddScript($sb).AddArgument($computer).AddArgument($ReportFile)
      $Job.RunspacePool = $RunspacePool
      $Jobs += New-Object PSObject -Property @{
        Target = $Target
        Pipe = $Job
        Result = $Job.BeginInvoke()
      }}
             
    Else 
    {                        
      Update-Log "-- $computer appears to be offline -- skipping"
      $row = '"' + $computer + '","Offline"'
      Add-Content -Path $ReportFile -Value $row
    }}
  
  Catch
        {
          $row = '"' + $computer + '","Failed"'
          Add-Content -Path $ReportFile -Value $row -erroraction ignore
        }
  }


Update-Log "$('-' * 50)"

#Wait For Completion
Do 
{ 
  [int]$pct = ($(($Jobs | Where-Object { $_.Result.IsCompleted -eq $True }).Count)/$Jobs.Count)*100
  
  Write-Progress -Activity 'Processing Jobs' -CurrentOperation "$(($Jobs | Where-Object { $_.Result.IsCompleted -eq $True }).Count) of $($Jobs.Count) Complete" -PercentComplete $pct
  
  #Update-Log "$(($Jobs | Where-Object { $_.Result.IsCompleted -eq $True }).Count) of $($Jobs.Count) Complete"
  
  Start-Sleep -Seconds 5 
}
While ( $Jobs.Result.IsCompleted -contains $false )

Update-Log "All Jobs Complete"	

# Set Error Action
$ErrorActionPreference = 'Continue'

Create a file named winrm.bat and include the following:

winrm.cmd quickconfig -quiet

Create a computers.txt and list each computer on a separate line.

COMMENTS