# encoding: utf-8
# api: ps
# title: functions
# description: Some utility functions for scripts
# version: 1.0
# type: init
# category: misc
# hidden: 1
# priority: optional
#
# Defines:
# ยท PSExec โ wrap psexec.exe
# ยท Check-PSExecResult โ eval $LASTEXITCODE
# ยท Invoke-ExchangeCommand โ simpler remoting
# ยท Open-RemoteRegistry โ -hive LocalMachine -machine A0004915 -path SOFTWARE
#
#-- check $LASTEXITCODE from psexec invocations
function Check-PSExecResult {
Param($err=$LASTEXITCODE)
switch ($err) {
0 { Write-Host -f Yellow "โ okay" }
1 { Write-Host -f Yellow "โ okay" }
2 { Write-Host -f Red "โ failed" }
default { Write-Host -f Gray "โ Exitcode=$err" }
}
}
#-- might as well define a PSExec wrapper then...
function PSExec {
[CmdletBinding()]
Param($machine, [Parameter(ValueFromRemainingArguments=$true)]$cmd)
$cmd = (($cmd | % { if ($_ -match ' ') { '"'+$_+'"' } else { $_ }}) -join ' ')
#Write-Host -f DarkYellow "โ PSExec($machine $cmd)"
Invoke-Expression "& PSExec.exe $machine $cmd 2>&1" | Select -Skip 3 | Write-Host -b DarkGray
#
[void](Check-PSExecResult $LASTEXITCODE)
}
#-- default session (just started once, then kept in memory)
function Import-ExchangeSession {
$params = $cfg.exchange
if (! (Test-Path function:Get-Mailbox)) {
$null = ( Write-Host -f Green "โ Exchange connection..." )
$global:Exchange_Session = New-PSSession @params
$null = Import-PSSession -Session $global:Exchange_Session
}
else {
$null = ( Write-Host -f DarkGray "โ Exchange conn active." )
}
}
#-- via WMI _ComputerSystem or looking up Owner of Explorer _Process
function Get-CurrentUser {
Param($machine)
if (($W = GWMI win32_computersystem -comp $machine) -and ($W.username)) {
$r = $W.username
}
elseif ($W = GWMI Win32_Process -ComputerName $machine -filter "name='Explorer.exe'") {
$r = ($w | % { $_.getOwner().user } | ? { $_ -notmatch "^SYSTEM$" })
if ($r -is [array]) { $r = $r[0] }
}
else {
$r = "nobody"
}
return $r -replace "^\w+\\(?=\w+)",""
}
#-- via WMI _userAccount
function Get-UserSID {
Param($user)
([WMI]"win32_userAccount.Domain='$($cfg.domain)',Name='$user'").SID
}
#-- remote registry
function Open-RemoteRegistry {
<#
.SYNOPSIS
Open remote registry tree
.DESCRIPTION
Establish a Win32.Registry connection to remote machine. Does not retrieve Leafes/Values itself.
.PARAMETER Path
Can either be a full path such as "\\HOSTNAME\HKLM\SOFTWARE\Windows"
Or just the regpath "SOFTWARE\Windows" when both -Hive and -Machine are given
.PARAMETER Hive
If no full -Path given, should name "HKLM", "HKCR", or "HKCU" (current user is looked up automatically).
.PARAMETER Machine
If no full -Path given, lists the remote hostname to connect to.
.EXAMPLE
$R = Open-RemoteRegisty "\\localhost\HKLM\SW\WindowsCurrentControlSet"
$R = Open-RemoteRegisty -Machine "localhost" -Hive "HKLM" -Path "SW\WindowsCurrentControlSet"
#>
Param(
$path = $null, # preferred: full specifier "\\HOSTNAME\HKLM\RegPath" (host+hive+path; no leaf/value)
$hive = "LocalMachine",
$machine = $null,
$writemode = $true,
[switch]$silent = $false
)
#-- combine path if it starts with "\\" two backslashes
if ((!$machine) -and ($path -match "^\\\\(\w+)\\(\w+)\\(.+)$")) {
$machine = $matches[1]
$hive = $matches[2]
$path = $matches[3]
}
#-- hive aliases
$hive = switch -regex ($hive) {
".*LM" { "LocalMachine" }
".*CR" { "ClassesRoot" }
".*CU" {
$path = (Get-UserSID (Get-CurrentUser $machine)) + "\" + $path
[Microsoft.Win32.RegistryHive]::Users
}
".*USERS" { [Microsoft.Win32.RegistryHive]::Users }
}
if (!$hive) {
$hive = "LocalMachine"
}
#-- open
if (!$silent) {
$null = ( Write-Host -f DarkGray "โ Remote registry connection [$machine\$hive]..." )
}
$R = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("$hive", $machine)
if (!$silent) {
$null = ( Write-Host -f DarkGray "โ Open subkey [$path]..." )
}
return $R.OpenSubKey($path, $writemode)
}
#-- shortcuts
function Set-RemoteRegistry {
Param($path = "\\localhost\HKLM\SOFTWARE\Etc\Key", $value="", $type="String")
if ($path -match "^\\\\(\w+)\\(\w+)\\(.+)\\([^\\]+)$") {
$R = Open-RemoteRegistry -machine $matches[1] -hive $matches[2] -path $matches[3] -Silent
$R.setValue($matches[4], $value, $type)
}
}
function Get-RemoteRegistry {
Param($path = "\\localhost\HKLM\SOFTWARE\Etc\Key")
if ($path -match "^\\\\([\w-]+)\\(\w+)\\(.+)\\([^\\]+)$") {
$R = Open-RemoteRegistry -machine $matches[1] -hive $matches[2] -path $matches[3] -writemode $false -Silent
return $R.getValue($matches[4])
}
}
#-- add and open nested registry paths
function Create-RegPath($r, $path) {
ForEach ($key in $path.split("[\\//]+")) {
if ($next = $r.OpenSubKey($key)) {
$r = $next;
}
elseif ($r = $r.CreateSubKey($key)) {
}
else {
return $null
}
}
$r
}
#-- output variants (Table|HTML|CSV|List|Grid)
function Out-DisplayDispatch {
Param(
$result = @(),
$display = $cfg.gridview,
$export_fn = "P:\temp.txt",
$width = 250
)
# if ($export_fn -notmatch ":\\") {...}
switch -regex ($display) {
"Table" { $result | FT -Wrap | Out-String -Width $width | Write-Host }
"HTML" { Set-ClipboardHtml ($result | ConvertTo-Html); Write-Host -f Green "โ Clipboard set" }
"CSV" { $result | Export-CSV $export_fn -Delimiter ";" -Encoding UTF8; Write-Host -f Green "Saved to $export_fn" }
"List" { $result | FL | Out-String | Write-Host }
"Grid" { $result | Out-GridView }
}
}