Scripted Screen Resolution and Rotation

The following script can be executed on first deployment, on a specific users logon, on every user’s logon, etc.

Param (
    [Parameter (Mandatory=$true)]
    [ValidateRange(0,3)]
    [int]$Rotation,
    [Parameter (Mandatory=$true)]
    [int]$Width,
    [Parameter (Mandatory=$true)]
    [int]$Height
)

<# 
    .Synopsis
        Sets the Screen Resolution and orientation of the primary monitor 
        Adapted from,
        https://stackoverflow.com/questions/12644786/powershell-script-to-change-screen-orientation
        https://blogs.technet.microsoft.com/heyscriptingguy/2010/07/07/hey-scripting-guy-how-can-i-change-my-desktop-monitor-resolution-via-windows-powershell/
    .Description 
        Uses Pinvoke and ChangeDisplaySettings Win32API to make the change
        Windows API enumeration of display rotation is counter-clockwise
    .Example 
        Powershell.exe -executionpolicy bypass -file ".\Set-OrientationAndResolution.ps1" 0 1920 1080

            Parameter: "Rotation" is desired rotation
                0 = rotate 0   = landscape
                1 = rotate 270 = portrait flipped
                2 = rotate 180 = landscape flipped
                3 = rotate 90  = portrait

            Parameter: "Width" is the pixel measurement parrallel to the task bar after rotation

            Parameter: "Height" is the pixel measurement perpendicular to the task bar after rotation
#>

Function Set-ScreenResolutionAndOrientation ($r, $w, $h){

$pinvokeCode = @" 

using System; 
using System.Runtime.InteropServices; 

namespace Resolution 
{ 

    [StructLayout(LayoutKind.Sequential)] 
    public struct DEVMODE 
    { 
       [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]
       public string dmDeviceName;

       public short  dmSpecVersion;
       public short  dmDriverVersion;
       public short  dmSize;
       public short  dmDriverExtra;
       public int    dmFields;
       public int    dmPositionX;
       public int    dmPositionY;
       public int    dmDisplayOrientation;
       public int    dmDisplayFixedOutput;
       public short  dmColor;
       public short  dmDuplex;
       public short  dmYResolution;
       public short  dmTTOption;
       public short  dmCollate;

       [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
       public string dmFormName;

       public short  dmLogPixels;
       public short  dmBitsPerPel;
       public int    dmPelsWidth;
       public int    dmPelsHeight;
       public int    dmDisplayFlags;
       public int    dmDisplayFrequency;
       public int    dmICMMethod;
       public int    dmICMIntent;
       public int    dmMediaType;
       public int    dmDitherType;
       public int    dmReserved1;
       public int    dmReserved2;
       public int    dmPanningWidth;
       public int    dmPanningHeight;
    }; 

    class NativeMethods 
    { 
        [DllImport("user32.dll")] 
        public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode); 
        [DllImport("user32.dll")] 
        public static extern int ChangeDisplaySettings(ref DEVMODE devMode, int flags); 

        public const int ENUM_CURRENT_SETTINGS = -1; 
        public const int CDS_UPDATEREGISTRY = 0x01; 
        public const int CDS_TEST = 0x02; 
        public const int DISP_CHANGE_SUCCESSFUL = 0; 
        public const int DISP_CHANGE_RESTART = 1; 
        public const int DISP_CHANGE_FAILED = -1;
        public const int DMDO_DEFAULT = 0;
        public const int DMDO_90 = 1;
        public const int DMDO_180 = 2;
        public const int DMDO_270 = 3;
    } 

    public class PrmaryScreenResolution 
    { 
        static public string ChangeResolution(int rotation, int width, int height) 
        { 

            DEVMODE dm = GetDevMode(); 

            if (0 != NativeMethods.EnumDisplaySettings(null, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm)) 
            {

                // swap width and height
                if (rotation == 1 || rotation == 3)
                {
                    if (dm.dmPelsWidth > dm.dmPelsHeight)
                    {
                        int temp = dm.dmPelsHeight;
                        dm.dmPelsHeight = dm.dmPelsWidth;
                        dm.dmPelsWidth = temp;
                    }
                }
                
                if (rotation == 0 || rotation == 2)
                {
                    if (dm.dmPelsWidth < dm.dmPelsHeight)
                    {
                        int temp = dm.dmPelsHeight;
                        dm.dmPelsHeight = dm.dmPelsWidth;
                        dm.dmPelsWidth = temp;
                    }
                }
                dm.dmPelsHeight = height;
                dm.dmPelsWidth = width;

                // determine new orientation based on the current orientation
                switch(rotation)
                {
                    case 1:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_270;
                        break;
                    case 2:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_180;
                        break;
                    case 3:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_90;
                        break;
                    case 0:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_DEFAULT;
                        break;
                    default:
                        // unknown orientation value
                        // add exception handling here
                        break;
                }

                int iRet = NativeMethods.ChangeDisplaySettings(ref dm, NativeMethods.CDS_TEST); 

                if (iRet == NativeMethods.DISP_CHANGE_FAILED) 
                { 
                    return "Unable To Process Your Request. Sorry For This Inconvenience."; 
                } 
                else 
                { 
                    iRet = NativeMethods.ChangeDisplaySettings(ref dm, NativeMethods.CDS_UPDATEREGISTRY); 
                    switch (iRet) 
                    { 
                        case NativeMethods.DISP_CHANGE_SUCCESSFUL: 
                            { 
                                return "Success"; 
                            } 
                        case NativeMethods.DISP_CHANGE_RESTART: 
                            { 
                                return "You Need To Reboot For The Change To Happen.\n If You Feel Any Problem After Rebooting Your Machine\nThen Try To Change Resolution In Safe Mode."; 
                            } 
                        default: 
                            { 
                                return "Failed To Change The Resolution"; 
                            } 
                    } 

                } 

            } 
            else 
            { 
                return "Failed To Change The Resolution."; 
            } 
        } 

        private static DEVMODE GetDevMode() 
        { 
            DEVMODE dm = new DEVMODE(); 
            dm.dmDeviceName = new String(new char[32]); 
            dm.dmFormName = new String(new char[32]); 
            dm.dmSize = (short)Marshal.SizeOf(dm); 
            return dm; 
        } 
    } 
} 

"@ 

Add-Type $pinvokeCode -ErrorAction SilentlyContinue 
[Resolution.PrmaryScreenResolution]::ChangeResolution($r, $w, $h) 
}

Set-ScreenResolutionAndOrientation $Rotation $Width $Height

Toggle Password Protected Sharing on Windows 10

Script the toggling of the switch outlined above…
Param (
    [switch]$Reboot=$false
)
$scriptpath = $MyInvocation.MyCommand.Path | Split-Path
$script = $MyInvocation.MyCommand.Path


If (([Security.Principal.WindowsIdentity]::GetCurrent()).Name -eq "NT AUTHORITY\SYSTEM")
{
    # Add the network access permission for the Everyone group
    # This allows the radio button to be flipped
    $everyonepath='HKLM:\SECURITY\Policy\Accounts\S-1-1-0\ActSysAc'
    $ekv=(Get-ItemProperty $everyonepath).'(Default)'
    $eBit=2
    $eDisable=0

    # Add the share permission for the Guest user
    # This flips the radio button
    $guestSID=(Get-Localuser | Where { $_.SID -match ".*-501" }).SID.Value
    $guestpath="HKLM:\SECURITY\Policy\Accounts\$guestSID\ActSysAc"
    # Guest account must be enabled to allow no password setting
    Get-LocalUser -SID $guestSID | Enable-LocalUser
    $gkv=(Get-ItemProperty $guestpath).'(Default)'
    $gBit=128
    $gDisable=1

    # Bit flips
    if (($ekv[0] -band $eBit) -eq 0) # If radio button can't be flipped
    {
        $ekv[0] = $ekv[0] + $eBit # Allow flip
        if (($gkv[0] -band $gBit) -ne 0) # If radio button isn't flipped on already
        {
            $gkv[0] = $gkv[0] - $gBit # Flip it on
        }
    }
    else # If radio button can be flipped
    {
        $ekv[0] = $ekv[0] - $eBit # Disallow flip
        if (($gkv[0] -band $gBit) -eq 0) # If radio button is flipped on already
        {
            $gkv[0] = $gkv[0] + $gBit # Flip it off
        }
    }

    New-ItemProperty -Path $everyonepath -Name '(Default)' -PropertyType None -Value $ekv -Force
    New-ItemProperty -Path $guestpath -Name '(Default)' -PropertyType None -Value $gkv -Force
    #gpupdate /force # Contrary to documentation, this does not update the security template. Reboot required
}
Else
{
    try
    {
        $taskname = "temp_ToggleNoPWShare"
        $taskdescription = $taskname
        $arguments = "-Executionpolicy bypass -NoProfile -file `"$script`""
        If ($Reboot) { $arguments = $arguments + " -Reboot" }
        $action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument $arguments
        Register-ScheduledTask -Action $action -TaskName $taskname -Description $taskdescription -User "System"
        Start-ScheduledTask -TaskName "$taskname"
        Sleep 5
        Unregister-ScheduledTask -TaskName $taskname -Confirm:$false
        If ($Reboot) { Start-Process -FilePath "shutdown.exe" -ArgumentList "-r -t 15" }
    }
    catch
    {
        Write-Host "Exception $_"
        Get-Variable -Scope Script
    }
}

Run Powershell Script upon Network Connection

Do you handle any scripting with batch still? No?!

Do you need to make a scheduled task using schtasks.exe that runs a PS script in a hidden window every time a network connection is made? No?!

Perfect!

Here is a one line cmd batch script for adding exactly that!

schtasks /create /tn "Net-Connected" /tr "powershell -executionpolicy bypass -file '%SYSTEMDRIVE%\example.ps1'" /SC ONEVENT /EC Microsoft-Windows-NetworkProfile/Operational /MO "*[System[Provider[@Name='Microsoft-Windows-NetworkProfile'] and EventID=10000]]" /RU "System" /F

User’s Taskbar Position

Configure a user’s taskbar position and autohidden status. The user must not be logged in locally. (Edited to properly close handle to registry)

# Script to autohide taskbar on account dictated below. User account must exist first.
Param(
    [string]$username = $(throw "-username is required."),
    [string]$password,
    [string]$domain = $(throw '-domain is required ("local" for local accounts).'),
    [bool]$hide = $true,
    [int]$position = 3
)

# Wrap reg edits in function to ensure no handles left on the registry
Function SafetyReg {
    # Hardcode hex key, if no HKCU key exists to use as a template.
    $HardcodeW7 = "28,00,00,00,ff,ff,ff,ff,03,00,00,00,03,00,00,00,3e,00,00,00,28,00,00,00,00,00,00,00,d8,02,00,00,00,04,00,00,00,03,00,00"
    # $HardcodeW8 = "28,00,00,00,ff,ff,ff,ff,03,02,00,00,03,00,00,00,3e,00,00,00,28,00,00,00,00,00,00,00,d8,02,00,00,00,04,00,00,00,03,00,00"
    $HardcodeW10 = "30,00,00,00,fe,ff,ff,ff,03,02,00,00,03,00,00,00,7c,00,00,00,28,00,00,00,00,00,00,00,10,04,00,00,80,07,00,00,38,04,00,00,60,00,00,00,01,00,00,00"

    If (Test-Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2) {
        $stuckrects = "StuckRects2"
        $Hardcode = $HardcodeW7
    } Else {
        $stuckrects = "StuckRects3"
        $Hardcode = $HardcodeW10
    }
    
    # Need to manually close handles to registry keys created by New-Item cmdlet
    $handle1 = New-Item -Path "HKLM:\Temp\Software\Microsoft\Windows\CurrentVersion\Explorer" -Name $StuckRects –Force
    $keyuser = "HKLM:\Temp\Software\Microsoft\Windows\CurrentVersion\Explorer\$StuckRects"
    $keytemplate = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\$StuckRects"

    $data = (Get-ItemProperty -Path $keytemplate -Name Settings).Settings
    if ($data -eq $null) {
        $hex = $hardcode.Split(',') | % { "0x$_"}
        If ($hide) { $hex[8] = 3 } Else { $hex[8] = 2 }
        $hex[12] = $position
        New-ItemProperty -Path $keyuser -Name Settings -PropertyType Binary -Value ([byte[]]$hex) -Force
    } else {
        If ($hide) { $data[8] = 3 } Else { $data[8] = 2 }
        $data[12] = $position
        Set-ItemProperty -Path $keyuser -Name Settings -Value $data
    }

    # Garbage collection maintenance
    $handle1.Handle.Close()
    [gc]::collect()
}

If([String]::IsNullOrEmpty($password))
{
    $secpassword = New-Object System.Security.SecureString
}
Else
{
    $secpassword = $password | ConvertTo-SecureString -AsPlainText -Force
}
if ($domain -eq "local") {$domain = $env:COMPUTERNAME}

# Details and credentials with which to run a new process
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = "cmd.exe"
$startInfo.WorkingDirectory = "$($env:windir)\system32\"
$startInfo.RedirectStandardOutput = $true
$startInfo.UseShellExecute = $false
$startInfo.CreateNoWindow = $false
$startInfo.Username = $username
$startInfo.Password = $secpassword
$startInfo.Domain = $domain
$startInfo.LoadUserProfile = $true

# Run the new process as the user, ensuring the user's hive file is created
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
$proc = $process.Start()
Stop-Process $process.Id -Force

# User hive file
$ntuserlocation = "$env:Systemdrive\users\" + $username + "\ntuser.dat"
reg load 'HKLM\Temp' $ntuserlocation
SafetyReg
reg unload HKLM\Temp

Getting LSASecret registry entries

Script by Niklas Goude
https://blogs.technet.microsoft.com/heyscriptingguy/2012/07/06/use-powershell-to-decrypt-lsa-secrets-from-the-registry/
https://gallery.technet.microsoft.com/scriptcenter/Get-TSLSASecret-9bf94965

Posting this script here to avoid Defender reading/deleting it on the computers that it’s used on.


function Get-TSLsaSecret {

  param(
    [Parameter(Position = 0,
      ValueFromPipeLine= $true
    )]
    [Alias("RegKey")]
    [string[]]$RegistryKey
  ) 

Begin {
# Check if User is Elevated
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent())
if($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -ne $true) {
  Write-Warning "Run the Command as an Administrator"
  Break
} 

# Check if Script is run in a 32-bit Environment by checking a Pointer Size
if([System.IntPtr]::Size -eq 8) {
  Write-Warning "Run PowerShell in 32-bit mode"
  Break
} 

# Check if RegKey is specified
if([string]::IsNullOrEmpty($registryKey)) {
  [string[]]$registryKey = (Split-Path (Get-ChildItem HKLM:\SECURITY\Policy\Secrets | Select -ExpandProperty Name) -Leaf)
} 

# Create Temporary Registry Key
if( -not(Test-Path "HKLM:\\SECURITY\Policy\Secrets\MySecret")) {
  mkdir "HKLM:\\SECURITY\Policy\Secrets\MySecret" | Out-Null
} 

$signature = @"
[StructLayout(LayoutKind.Sequential)]
public struct LSA_UNICODE_STRING
{
  public UInt16 Length;
  public UInt16 MaximumLength;
  public IntPtr Buffer;
} 

[StructLayout(LayoutKind.Sequential)]
public struct LSA_OBJECT_ATTRIBUTES
{
  public int Length;
  public IntPtr RootDirectory;
  public LSA_UNICODE_STRING ObjectName;
  public uint Attributes;
  public IntPtr SecurityDescriptor;
  public IntPtr SecurityQualityOfService;
} 

public enum LSA_AccessPolicy : long
{
  POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,
  POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,
  POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,
  POLICY_TRUST_ADMIN = 0x00000008L,
  POLICY_CREATE_ACCOUNT = 0x00000010L,
  POLICY_CREATE_SECRET = 0x00000020L,
  POLICY_CREATE_PRIVILEGE = 0x00000040L,
  POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,
  POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,
  POLICY_AUDIT_LOG_ADMIN = 0x00000200L,
  POLICY_SERVER_ADMIN = 0x00000400L,
  POLICY_LOOKUP_NAMES = 0x00000800L,
  POLICY_NOTIFICATION = 0x00001000L
} 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaRetrievePrivateData(
  IntPtr PolicyHandle,
  ref LSA_UNICODE_STRING KeyName,
  out IntPtr PrivateData
); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaStorePrivateData(
  IntPtr policyHandle,
  ref LSA_UNICODE_STRING KeyName,
  ref LSA_UNICODE_STRING PrivateData
); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaOpenPolicy(
  ref LSA_UNICODE_STRING SystemName,
  ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
  uint DesiredAccess,
  out IntPtr PolicyHandle
); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaNtStatusToWinError(
  uint status
); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaClose(
  IntPtr policyHandle
); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaFreeMemory(
  IntPtr buffer
);
"@ 

Add-Type -MemberDefinition $signature -Name LSAUtil -Namespace LSAUtil
} 

  Process{
    foreach($key in $RegistryKey) {
      $regPath = "HKLM:\\SECURITY\Policy\Secrets\" + $key
      $tempRegPath = "HKLM:\\SECURITY\Policy\Secrets\MySecret"
      $myKey = "MySecret"
      if(Test-Path $regPath) {
        Try {
          Get-ChildItem $regPath -ErrorAction Stop | Out-Null
        }
        Catch {
          Write-Error -Message "Access to registry Denied, run as NT AUTHORITY\SYSTEM" -Category PermissionDenied
          Break
        }       

        if(Test-Path $regPath) {
          # Copy Key
          "CurrVal","OldVal","OupdTime","CupdTime","SecDesc" | ForEach-Object {
            $copyFrom = "HKLM:\SECURITY\Policy\Secrets\" + $key + "\" + $_
            $copyTo = "HKLM:\SECURITY\Policy\Secrets\MySecret\" + $_ 

            if( -not(Test-Path $copyTo) ) {
              mkdir $copyTo | Out-Null
            }
            $item = Get-ItemProperty $copyFrom
            Set-ItemProperty -Path $copyTo -Name '(default)' -Value $item.'(default)'
          }
        }
        # Attributes
        $objectAttributes = New-Object LSAUtil.LSAUtil+LSA_OBJECT_ATTRIBUTES
        $objectAttributes.Length = 0
        $objectAttributes.RootDirectory = [IntPtr]::Zero
        $objectAttributes.Attributes = 0
        $objectAttributes.SecurityDescriptor = [IntPtr]::Zero
        $objectAttributes.SecurityQualityOfService = [IntPtr]::Zero 

        # localSystem
        $localsystem = New-Object LSAUtil.LSAUtil+LSA_UNICODE_STRING
        $localsystem.Buffer = [IntPtr]::Zero
        $localsystem.Length = 0
        $localsystem.MaximumLength = 0 

        # Secret Name
        $secretName = New-Object LSAUtil.LSAUtil+LSA_UNICODE_STRING
        $secretName.Buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($myKey)
        $secretName.Length = [Uint16]($myKey.Length * [System.Text.UnicodeEncoding]::CharSize)
        $secretName.MaximumLength = [Uint16](($myKey.Length + 1) * [System.Text.UnicodeEncoding]::CharSize) 

        # Get LSA PolicyHandle
        $lsaPolicyHandle = [IntPtr]::Zero
        [LSAUtil.LSAUtil+LSA_AccessPolicy]$access = [LSAUtil.LSAUtil+LSA_AccessPolicy]::POLICY_GET_PRIVATE_INFORMATION
        $lsaOpenPolicyHandle = [LSAUtil.LSAUtil]::LSAOpenPolicy([ref]$localSystem, [ref]$objectAttributes, $access, [ref]$lsaPolicyHandle) 

        if($lsaOpenPolicyHandle -ne 0) {
          Write-Warning "lsaOpenPolicyHandle Windows Error Code: $lsaOpenPolicyHandle"
          Continue
        } 

        # Retrieve Private Data
        $privateData = [IntPtr]::Zero
        $ntsResult = [LSAUtil.LSAUtil]::LsaRetrievePrivateData($lsaPolicyHandle, [ref]$secretName, [ref]$privateData) 

        $lsaClose = [LSAUtil.LSAUtil]::LsaClose($lsaPolicyHandle) 

        $lsaNtStatusToWinError = [LSAUtil.LSAUtil]::LsaNtStatusToWinError($ntsResult) 

        if($lsaNtStatusToWinError -ne 0) {
          Write-Warning "lsaNtsStatusToWinError: $lsaNtStatusToWinError"
        } 

        [LSAUtil.LSAUtil+LSA_UNICODE_STRING]$lusSecretData =
        [LSAUtil.LSAUtil+LSA_UNICODE_STRING][System.Runtime.InteropServices.marshal]::PtrToStructure($privateData, [System.Type][LSAUtil.LSAUtil+LSA_UNICODE_STRING]) 

        Try {
          [string]$value = [System.Runtime.InteropServices.marshal]::PtrToStringAuto($lusSecretData.Buffer)
          $value = $value.SubString(0, ($lusSecretData.Length / 2))
        }
        Catch {
          $value = ""
        } 

        if($key -match "^_SC_") {
          # Get Service Account
          $serviceName = $key -Replace "^_SC_"
          Try {
            # Get Service Account
            $service = Get-WmiObject -Query "SELECT StartName FROM Win32_Service WHERE Name = '$serviceName'" -ErrorAction Stop
            $account = $service.StartName
          }
          Catch {
            $account = ""
          }
        } else {
          $account = ""
        } 

        # Return Object
        New-Object PSObject -Property @{
          Name = $key;
          Secret = $value;
          Account = $Account
        } | Select-Object Name, Account, Secret, @{Name="ComputerName";Expression={$env:COMPUTERNAME}}
      } else {
        Write-Error -Message "Path not found: $regPath" -Category ObjectNotFound
      }
    }
  }
  end {
    if(Test-Path $tempRegPath) {
      Remove-Item -Path "HKLM:\\SECURITY\Policy\Secrets\MySecret" -Recurse -Force
    }
  }
}