Posts RSS Comments RSS 253 Posts and 411 Comments till now

Blog Archives

Find-CitrixUser.ps1 (Citrix Top 10)

This is another script that I can use quite often. It is a simple script that queries all the sessions and returns the ones where the User matches. I made the User a RegEx search so you could do multiple users.

Name: Find-CitrixUser.ps1
Purpose: Finds where the user(s) are and outputs session info

# Find-CitrixUser.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Finds where the user(s) are and out puts session info
Param($user=".*",[switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Find-CitrixUser.ps1:" -fore Green
    Write-Host "   Finds where the user(s) are and out puts session info"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -User                  : Optional. Name of the User or RegEx (Default is all users)"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Finds User TestMe and outputs and returns ServerName,ClientAddress, and SessionID" -fore White
    Write-Host "     .\Find-CitrixUser.ps1 | ft ServerName,ClientAddress,SessionID " -fore Yellow
    Write-Host
    Write-Host "   Finds all Users who start with ‘Sales’ and returns UserName,ServerName, and SessionID"  -fore White
    Write-Host "     .\Find-CitrixUser.ps1 `"^sales`" | ft UserName,ServerName,SessionID " -fore Yellow
    Write-Host
    Write-Host "   To View All properties availiable." -fore White
    Write-Host "     .\Find-CitrixUser.ps1 <username> | Get-Member" -fore Yellow
    Write-Host
}

# Check for the Help or if
if($help){helpme;Write-Host;return}

# Code to Get the Farm and Initialize
$farm = New-Object -com "MetaframeCOM.MetaFrameFarm"
$farm.Initialize(1)

# Get the Sessions and Parse for Users who match
$farm.Sessions | ?{$_.UserName -match $user}

Get-CitrixPrinterInfo.ps1 (Citrix Top 10)

This script just collects the Printer Information from all the Servers in the Farm. It will output them to a file or you can pipe them and filter them.

Name: Get-CitrixPrinterInfo.ps1
Purpose: Gets Print Driver Info from all the Servers in the Farm and outputs to file or console

# Get-CitrixPrinterInfo.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Gets Print Driver Info from all the Servers in the Farm
Param($Server,$file,[Switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Get-CitrixPrinterInfo.ps1:" -fore Green
    Write-Host "   Gets Print Driver Info from all the Servers in the Farm"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -Server                : Optional. Server to Get Print Info From "
    Write-Host "   -File                  : Optional. File Name to Export Info to"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Gets Print Info and Exports to File" -fore White
    Write-Host "     .\Get-CitrixPrinterInfo.ps1 -file MyExportFile.txt" -fore Yellow
    Write-Host
    Write-Host "   Gets Print Drivers from a Specific Server and outputs DriverName and SourceServer"  -fore White
    Write-Host "     .\Get-CitrixPrinterInfo.ps1 <serverName> | ft DriverName,SourceServer" -fore Yellow
    Write-Host
}

# Check for Help Flag
if($help){HelpMe;Write-Host;Return}

# Check for File
if($file)
{
    if($server) # If -Server was passed we run check just against it and output to screen
    {
        $mfsrv = new-Object -com "MetaframeCOM.MetaframeServer"
        $mfsrv.Initialize(6,$Server.ToUpper())
        $mfsrv | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table} | out-File $file -enc ASCII
    }
    else # We run the check against the whole farm and output results to file
    {
        $mfarm = new-Object -com "MetaframeCOM.MetaframeFarm"
        $mfarm.Initialize(1)
        $mfarm.Servers | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table} | out-File $file -enc ASCII
    }
}
else
{
    if($server) # If -Server was passed we run check just against it and output to screen
    {
        $mfsrv = new-Object -com "MetaframeCOM.MetaframeServer"
        $mfsrv.Initialize(6,$Server.ToUpper())
        $mfsrv | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table}
    }
    else # We run the check against the whole farm and output results to screen
    {
        $mfarm = new-Object -com "MetaframeCOM.MetaframeFarm"
        $mfarm.Initialize(1)
        $mfarm.Servers | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table}
    }
 }

Find-CitrixIdleUser.ps1 (Citrix Top 10)

This is one of the more useful scripts (at least for me.) It will query the farm and tell you all the user who have exceeded the idle time specified. I also combined another script that logged off users.

Name: Find-CitrixIdleUser.ps1
Purpose: Finds users with idle time greater than value passed and logs them off if -logoff is passed

# Find-CitrixIdleUser.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Finds users with idle time greater than value passed
Param($time,[switch]$day,[switch]$hour,[switch]$minute,[switch]$logoff,[switch]$verbose,[switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Find-CitrixIdleUser.ps1:" -fore Green
    Write-Host "   Finds users with idle time greater than value passed"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -Time                  : Optional. Server to Get Print Info From "
    Write-Host "   -Day                   : Optional. Checks Days of Idle Time "
    Write-Host "   -Hour                  : Optional. Checks Hours of Idle Time (Default)"
    Write-Host "   -Minute                : Optional. Checks Minutes of Idle Time"
    Write-Host "   -Logoff                : Optional. Logs User off if Idle Time exceeds Time"
    Write-Host "   -Verbose               : Optional. Show Verbose Output"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Finds Users who have been idle 2 hours and return AppName, UserName, SessionID, and ClientName" -fore White
    Write-Host "     Find-CitrixIdleUser.ps1 2 -hour | ft AppName,UserName,SessionID,ClientName -auto" -fore Yellow
    Write-Host
    Write-Host "   Finds Users who have been idle 2 hours and Logs them Off" -fore White
    Write-Host "     Find-CitrixIdleUser.ps1 2 -hour -logoff" -fore Yellow
    Write-Host
}
if($verbose){$verbosepreference = "Continue"}
Write-Host
if(!$time -or $help){helpme;Write-Host;Return}

# Get Citrix Farm Object
Write-Verbose " – Creating MFFarm Object"
$farm = new-Object -com "MetaframeCOM.MetaframeFarm"
$farm.Initialize(1)

# Parse Sessions
Write-Verbose " – Parsing Sessions. Total of [$($farm.Sessions.count)] Sessions"
foreach($session in $farm.Sessions)
{
    Write-Verbose "   – Processing Session ID [$($Session.SessionId)]"
    $shouldLogOff = $false

    # Getting Citrix Session Idle Time and Convert to System.DateTime
    Write-Verbose "   – Getting LastInputTime"
    $ctxDate = $session.LastInputTime(1)
    Write-Verbose "   – Checking if idle time is -gt 0"
    if(($ctxDate.HighPart -ne 0) -and ($ctxDate.LowPart -ne 0))
    {
        $date = "{0,4}{1,2:00}{2,2:00}{3,2:00}{4,2:00}" -f $ctxDate.year,$ctxDate.Month,$ctxDate.Day,$ctxDate.Hour,$ctxDate.Minute
        Write-Verbose "   – Converted LastInputTime to [$date]"
        $SessionIdleTime = [system.DateTime]::ParseExact($date,‘yyyyMMddHHmm’,$null)

        # Get Current Time in System.DateTime
        Write-Verbose "   – Getting Current Date"
        $now = Get-Date
        Write-Verbose "   – Current Date is [$now]"

        # Find Difference
        Write-Verbose "   + Getting Time Difference"
        $diff = $now$SessionIdleTime
        Write-Verbose "     – Found Days [$($diff.TotalDays)] Hours [$($diff.Totalhours)] Minutes [$($diff.TotalMinutes)]"

        # Output Sessions that match
        if($day)   {    if($diff.TotalDays    -gt $time)    {$session;$shouldLogOff = $true}  }
        if($hour)  {    if($diff.Totalhours   -gt $time)    {$session;$shouldLogOff = $true}  }
        if($minute){    if($diff.TotalMinutes -gt $time)    {$session;$shouldLogOff = $true}  }

        Write-Verbose "     – Set `$shouldLogOff to [$shouldLogOff]"

        # Logging Off User
        if($logoff -and $shouldLogOff)
        {
            Write-Verbose "   – Logging Off Session ID [$($Session.SessionId)]"
            $session.Logoff($false)
        }
    }
    else
    {
        Write-Verbose "   – Session ID [$($Session.SessionId)] NOT Idle"
    }
    Write-Host
}

Set-CitrixPSVersion.ps1 (Citrix Top 10)

I am constantly looking for content for my blog and tasks that can be automated. I believe this helps me learn and helps other with their needs.

In this search I was directed to convert/write Powershell examples for scripts located here http://community.citrix.com/display/cdn/Script+Exchange

Here is the first of those scripts.

Name: Set-CitrixPSVersion.ps1
Purpose: Sets PS Version on a Server, List of Servers, or all Servers in the Farm

# Set-CitrixPSVersion.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Sets PS Version on a Server, List of Servers, or all Servers in the Farm
Param($file,$server,$PSVer,[switch]$help,[switch]$all,[switch]$whatif,[switch]$show,[switch]$verbose)
function HelpMe{
    Write-Host
    Write-Host " Set-CitrixPSVersion.ps1:" -fore Green
    Write-Host "   Sets PS Version on a Server, List of Servers, or all Servers in the Farm"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -File <fileName>       : Optional. Name of the File of Servers"
    Write-Host "   -Server <serverName>   : Optional. Name of the Server to Change"
    Write-Host "   -Verbose               : Optional. Enables Verbose Output"
    Write-Host "   -All                   : Optional. Sets Version on all Servers [Requires -Server]"
    Write-Host "   -Show                  : Optional. Displays the Version for Server(s)"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host "   -Whatif                : Optional. Will not Commit Info just Display what would change"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Set PS Version on Server1 to STD" -fore White
    Write-Host "     .\Set-CitrixPSVersion.ps1 -Server Server1 -psver STD " -fore Yellow
    Write-Host
    Write-Host "   Set PS Version on Servers in a File" -fore White
    Write-Host "     .\Set-CitrixPSVersion.ps1 -file c:\Mylist.txt -psver STD " -fore Yellow
    Write-Host
    Write-Host "   Get PS Version from ALL server" -fore White
    Write-Host "     .\Set-CitrixPSVersion.ps1 -all -Server myzdcserver" -fore Yellow
    Write-Host
    Write-Host " Product Edition Options" -fore Green
    Write-Host "   STD = Citrix Presentation Server Standard Edition" -fore White
    Write-Host "   ADV = Citrix Presentation Server Advanced Edition" -fore White
    Write-Host "   ENT = Citrix Presentation Server Enterprise Edition" -fore White
    Write-Host "   PLT = Citrix Presentation Server Platinum Edition" -fore White
    Write-Host
}
function Ping-Server {
    Param($srv)
    $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
    if($pingresult.statuscode -eq 0) {$true} else {$false}
}
function Set-PSVer{
    Param($srv)
    Write-Verbose "  Getting Citrix Server Object"
    $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$srv)
    $mfsrv = [system.Activator]::CreateInstance($type)
    $mfsrv.Initialize(6,$srv)
    if(!$?){Write-Host "   – Server [$srv] threw and Error" -fore red;return}

    if($show) # Check for $Show and will display only
    {
        Write-Host "   – PS Version for [$srv]: $($mfsrv.WinServerObject.mpsedition)"
        return
    }
    else
    {
        if($whatif) # Check for $Whatif
        {
            Write-Host "  What if: Performing operation `"Set PS Version [$PSVer]`" on Target `"$srv`"."
        }
        else
        {
            Write-Verbose "   – Setting PSVer to [$PSVer] on [$srv]"
            $mfsrv.WinServerObject.mpsedition = $PSVer
            Write-Host "   – PS Version for [$srv]: $($mfsrv.WinServerObject.mpsedition)"
        }
    }
}
function Set-PSALL{
    $mfarm = new-Object -com "MetaframeCOM.MetaframeFarm"
    $mfarm.Initialize(1)
    foreach($mfsrv in $mfarm.Servers)
    {
        if($show){Write-Host "   – PS Version for [$($mfsrv.ServerName)]: $($mfsrv.WinServerObject.MPSEdition)";continue}
        if($whatif){Write-Host "  What if: Performing operation `"Set PS Version [$PSVer]`" on Target `"$($mfsrv.ServerName)`"."}
        else
        {
            Write-Verbose "   – Setting PSVer to [$PSVer] on [$($mfsrv.ServerName)]"
            $mfsrv.WinServerObject.mpsedition = $PSVer
            Write-Host "   – PS Version for [$($mfsrv.ServerName)]: $($mfsrv.WinServerObject.MPSEdition)"
        }
    }
}

# Script Setup. Checking Parameters
Write-Host

## Checing Verbose flag
if($verbose){$verbosepreference = "Continue"}else{$erroractionpreference = "SilentlyContinue"}

## Verifying that File/Server was passed. If not or -help I Call HelpMe and close.
if(!$file -and !$server -and !$all -or $help){HelpMe;Return}

## Verify Valid Edition was Passed
if(!$show -and ($PSVer -notmatch "STD|ADV|ENT|PLT"))
{
    Write-Host " PS Edition [$PSVER] is NOT Valid. Please use STD, ADV, ENT, or PLT" -fore RED
    Write-Host
    Return
}

# If $Server and we can ping it we run Set-PSVer against Server
if($server -and (ping-server $server))
{
    Set-PSVer $server
    Write-host
}

# Check for -File and Verify the file is valid
if($File -and (test-Path $file))
{
    Write-Verbose " – Processing File [$file]"
    # Process each Server checking for blanks
    foreach($Server in (get-Content $file | where{$_ -match "^\S"}))
    {
        Write-Host " + Processing Server [$Server]"
        if(ping-Server $server){Set-PSVer $Server}else{Write-Host "   – Ping Failed to [$Server]" -fore Red}
        Write-host
    }
}

if($all){Set-PSALL}

Write-Host

Get/Set-ADACL (ACL and SDDLs for Active Directory!)

A friend had a need to get/set Active Directory ACLs. So I wrote these.

They will use [System.DirectoryServices.ActiveDirectoryAccessRule] objects or SDDLs strings.

Note: I put the .NET classes and MS Spec for SDDLs at the bottom. Dont miss it!

Get-ADACL.ps1

# Get-ADACL.ps1
Param($DNPath,[switch]$SDDL,[switch]$help,[switch]$verbose)
function HelpMe{
    Write-Host
    Write-Host " Get-ADACL.ps1:" -fore Green
    Write-Host "   Gets ACL object or SDDL for AD Object"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -DNPath                : Parameter: DN of Object"
    Write-Host "   -sddl                  : [SWITCH]:  Output SDDL instead of ACL Object"
    Write-Host "   -Verbose               : [SWITCH]:  Enables Verbose Output"
    Write-Host "   -Help                  : [SWITCH]:  Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Get ACL for ‘cn=users,dc=corp,dc=lab’" -fore White
    Write-Host "     .\Get-ADACL.ps1 ‘cn=users,dc=corp,dc=lab’" -fore Yellow
    Write-Host "   Get SDDL for ‘cn=users,dc=corp,dc=lab’" -fore White
    Write-Host "     .\Get-ADACL.ps1 ‘cn=users,dc=corp,dc=lab’ -sddl " -fore Yellow
    Write-Host
}

if(!$DNPath -or $help){HelpMe;return}

Write-Host
if($verbose){$verbosepreference="continue"}

Write-Verbose " + Processing Object [$DNPath]"
$DE = [ADSI]"LDAP://$DNPath"

Write-Verbose "   – Getting ACL"
$acl = $DE.psbase.ObjectSecurity
if($SDDL)
{
    Write-Verbose "   – Returning SDDL"
    $acl.GetSecurityDescriptorSddlForm([System.Security.AccessControl.AccessControlSections]::All)
}
else
{
    Write-Verbose "   – Returning ACL Object [System.DirectoryServices.ActiveDirectoryAccessRule]"
    $acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier])
}

Set-ADACL.ps1

# Set-ADACL.ps1
Param($DNPath,$acl,$sddl,[switch]$verbose,[switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Set-ADACL.ps1:" -fore Green
    Write-Host "   Sets the AD Object ACL to ‘ACL Object’ or ‘SDDL’ String"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -DNPath                : Parameter: DN of Object"
    Write-Host "   -ACL                   : Parameter: ACL Object"
    Write-Host "   -sddl                  : Parameter: SDDL String"
    Write-Host "   -Verbose               : [SWITCH]:  Enables Verbose Output"
    Write-Host "   -Help                  : [SWITCH]:  Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Set ACL on ‘cn=users,dc=corp,dc=lab’ using ACL Object" -fore White
    Write-Host "     .\Set-ADACL.ps1 ‘cn=users,dc=corp,dc=lab’ -ACL $acl" -fore Yellow
    Write-Host "   Set ACL on ‘cn=users,dc=corp,dc=lab’ using SDDL" -fore White
    Write-Host "     .\Set-ADACL.ps1 ‘cn=users,dc=corp,dc=lab’ -sddl `$mysddl" -fore Yellow
    Write-Host
}

if(!$DNPath -or (!$acl -and !$sddl) -or $help){HelpMe;Return}

Write-Host
if($verbose){$verbosepreference="continue"}
Write-Verbose " + Processing Object [$DNPath]"

$DE = [ADSI]"LDAP://$DNPath"
if($sddl)
{
    Write-Verbose "   – Setting ACL using SDDL [$sddl]"
    $DE.psbase.ObjectSecurity.SetSecurityDescriptorSddlForm($sddl)
}
else
{
    foreach($ace in $acl)
    {
        Write-Verbose "   – Adding Permission [$($ace.ActiveDirectoryRights)] to [$($ace.IdentityReference)]"
        $DE.psbase.ObjectSecurity.SetAccessRule($ace)
    }
}
$DE.psbase.commitchanges()
Write-Host

More Info
I used the following .NET Classes
System.DirectoryServices.DirectoryEntry
http://msdn2.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx
System.DirectoryServices.ActiveDirectoryAccessRule
http://msdn2.microsoft.com/en-us/library/system.directoryservices.activedirectoryaccessrule.aspx
System.DirectoryServices.ActiveDirectorySecurity
http://msdn2.microsoft.com/en-us/library/system.directoryservices.activedirectorysecurity.aspx
System.Security.AccessControl.AccessControlSections
http://msdn2.microsoft.com/en-us/library/system.security.accesscontrol.accesscontrolsections(vs.80).aspx

SDDL Info
MS: http://msdn2.microsoft.com/en-us/library/aa379567.aspx

More userAccountControl Flag Fun (Convert-ToUACFlag.ps1)

A question on the NG made me think about this. While I personally prefer the decimal that comes from userAccountControl, others may prefer to actually see the FLAGS that are set.

Here is the script I came up with. It will output and array by default, but -toString will output a “,” delimited string.

It has a great -help function with -verbose output that explains each UAC Flag

Convert-ToUACFlag.ps1

# Convert-ToUACFlag.ps1
Param([int]$uac,[switch]$ToString,[switch]$help,[switch]$verbose)
function HelpMe{
    Write-Host
    Write-Host " Convert-ToUACFlag.ps1:" -fore Green
    Write-Host "   Converts UAC from Decimal or Hex to User Account Control Flags (described verbose help)"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -UAC                   : Parameter User Account Control Value"
    Write-Host "   -toString              : [SWITCH]  Output to String instead of Array"
    Write-Host "   -Help                  : [SWITCH]  Displays This"
    Write-Host "   -Verbose               : [SWITCH]  Displays This and User Account Control Definitions"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Convert to Flag getting back array" -fore White
    Write-Host "     .\Convert-ToUACFlag.ps1 69649" -fore Yellow
    Write-Host "   Convert to Flag getting back string" -fore White
    Write-Host "     .\Convert-ToUACFlag.ps1 69649 -toString" -fore Yellow
    Write-Host
    if($verbose)
    {
        Write-Host " User Account Control Flags and Definition" -fore Green
        Write-Host "  + SCRIPT" -fore Yellow
        Write-Host "    – The logon script will be run."
        Write-Host
        Write-Host "  + ACCOUNTDISABLE" -fore Yellow
        Write-Host "    – The user account is disabled."
        Write-Host
        Write-Host "  + HOMEDIR_REQUIRED" -fore Yellow
        Write-Host "    – The home folder is required."
        Write-Host
        Write-Host "  + PASSWD_NOTREQD" -fore Yellow
        Write-Host "    – No password is required."
        Write-Host
        Write-Host "  + PASSWD_CANT_CHANGE" -fore Yellow
        Write-Host "    – The user cannot change the password."
        Write-Host "    – This is a permission on the user’s object."
        Write-Host
        Write-Host "  + ENCRYPTED_TEXT_PASSWORD_ALLOWED" -fore Yellow
        Write-Host "    – The user can send an encrypted password."
        Write-Host
        Write-Host "  + TEMP_DUPLICATE_ACCOUNT" -fore Yellow
        Write-Host "    – This is an account for users whose primary account is in another domain."
        Write-Host "    – This account provides user access to this domain,"
        Write-Host "      but not to any domain that trusts this domain."
        Write-Host "    – This is sometimes referred to as a local user account."
        Write-Host
        Write-Host "  + NORMAL_ACCOUNT" -fore Yellow
        Write-Host "    – This is a default account type that represents a typical user."
        Write-Host
        Write-Host "  + INTERDOMAIN_TRUST_ACCOUNT" -fore Yellow
        Write-Host "    – This is a permit to trust an account for a system domain that trusts other domains."
        Write-Host
        Write-Host "  + WORKSTATION_TRUST_ACCOUNT" -fore Yellow
        Write-Host "    – This is a computer account for a computer that is running"
        Write-Host "    – Microsoft Windows NT 4.0 and above and is a member of this domain."
        Write-Host
        Write-Host "  + SERVER_TRUST_ACCOUNT" -fore Yellow
        Write-Host "    – This is a computer account for a domain controller that is a member of this domain."
        Write-Host
        Write-Host "  + DONT_EXPIRE_PASSWD" -fore Yellow
        Write-Host "    – Represents the password, which should never expire on the account."
        Write-Host
        Write-Host "  + MNS_LOGON_ACCOUNT" -fore Yellow
        Write-Host "    – This is an MNS logon account."
        Write-Host
        Write-Host "  + SMARTCARD_REQUIRED" -fore Yellow
        Write-Host "    – When this flag is set, it forces the user to log on by using a smart card."
        Write-Host
        Write-Host "  + TRUSTED_FOR_DELEGATION" -fore Yellow
        Write-Host "    – When this flag is set, the service account (the user or computer account)"
        Write-Host "      under which a service runs is trusted for Kerberos delegation."
        Write-Host "    – Any such service can impersonate a client requesting the service."
        Write-Host "    – To enable a service for Kerberos delegation, you must set this flag on the"
        Write-Host "      userAccountControl property of the service account."
        Write-Host
        Write-Host "  + NOT_DELEGATED" -fore Yellow
        Write-Host "    – When this flag is set, the security context of the user is not delegated to"
        Write-Host "      a service even if the service account is set as trusted for Kerberos delegation."
        Write-Host
        Write-Host "  + USE_DES_KEY_ONLY" -fore Yellow
        Write-Host "    – (Windows 2000/Windows Server 2003) Restrict this principal to use only"
        Write-Host "      Data Encryption Standard (DES) encryption types for keys."
        Write-Host
        Write-Host "  + DONT_REQUIRE_PREAUTH" -fore Yellow
        Write-Host "    – (Windows 2000/Windows Server 2003) This account does not require"
        Write-Host "      Kerberos pre+authentication for logging on."
        Write-Host
        Write-Host "  + PASSWORD_EXPIRED" -fore Yellow
        Write-Host "    – (Windows 2000/Windows Server 2003) The user’s password has expired."
        Write-Host
        Write-Host "  + TRUSTED_TO_AUTH_FOR_DELEGATION" -fore Yellow
        Write-Host "    – (Windows 2000/Windows Server 2003) The account is enabled for delegation."
        Write-Host "    – This is a security-sensitive setting."
        Write-Host "    – Accounts with this option enabled should be tightly controlled."
        Write-Host "    – This setting allows a service that runs under the account to assume a client’s"
        Write-Host "      identity and authenticate as that user to other remote servers on the network."
    }
    Write-Host
}

if(!$uac -or $help){HelpMe;Return}
$flags = @()
switch ($uac)
{
    {($uac -bor 0x0002) -eq $uac}    {$flags += "ACCOUNTDISABLE"}
    {($uac -bor 0x0008) -eq $uac}    {$flags += "HOMEDIR_REQUIRED"}
    {($uac -bor 0x0010) -eq $uac}    {$flags += "LOCKOUT"}
    {($uac -bor 0x0020) -eq $uac}    {$flags += "PASSWD_NOTREQD"}
    {($uac -bor 0x0040) -eq $uac}    {$flags += "PASSWD_CANT_CHANGE"}
    {($uac -bor 0x0080) -eq $uac}    {$flags += "ENCRYPTED_TEXT_PWD_ALLOWED"}
    {($uac -bor 0x0100) -eq $uac}    {$flags += "TEMP_DUPLICATE_ACCOUNT"}
    {($uac -bor 0x0200) -eq $uac}    {$flags += "NORMAL_ACCOUNT"}
    {($uac -bor 0x0800) -eq $uac}    {$flags += "INTERDOMAIN_TRUST_ACCOUNT"}
    {($uac -bor 0x1000) -eq $uac}    {$flags += "WORKSTATION_TRUST_ACCOUNT"}
    {($uac -bor 0x2000) -eq $uac}    {$flags += "SERVER_TRUST_ACCOUNT"}
    {($uac -bor 0x10000) -eq $uac}   {$flags += "DONT_EXPIRE_PASSWORD"}
    {($uac -bor 0x20000) -eq $uac}   {$flags += "MNS_LOGON_ACCOUNT"}
    {($uac -bor 0x40000) -eq $uac}   {$flags += "SMARTCARD_REQUIRED"}
    {($uac -bor 0x80000) -eq $uac}   {$flags += "TRUSTED_FOR_DELEGATION"}
    {($uac -bor 0x100000) -eq $uac}  {$flags += "NOT_DELEGATED"}
    {($uac -bor 0x200000) -eq $uac}  {$flags += "USE_DES_KEY_ONLY"}
    {($uac -bor 0x400000) -eq $uac}  {$flags += "DONT_REQ_PREAUTH"}
    {($uac -bor 0x800000) -eq $uac}  {$flags += "PASSWORD_EXPIRED"}
    {($uac -bor 0x1000000) -eq $uac} {$flags += "TRUSTED_TO_AUTH_FOR_DELEGATION"}
}
if($toString){$flags | %{if($mystring){$mystring += ",$_"}else{$mystring = $_}};$mystring}else{$flags}

Oisin the “obsessive programmer” sent me this as another option

param
([int]$value)
$flags = @("","ACCOUNTDISABLE","", "HOMEDIR_REQUIRED",
"LOCKOUT", "PASSWD_NOTREQD","PASSWD_CANT_CHANGE", "ENCRYPTED_TEXT_PWD_ALLOWED",
"TEMP_DUPLICATE_ACCOUNT", "NORMAL_ACCOUNT", "","INTERDOMAIN_TRUST_ACCOUNT", "WORKSTATION_TRUST_ACCOUNT",
"SERVER_TRUST_ACCOUNT", "", "", "DONT_EXPIRE_PASSWORD", "MNS_LOGON_ACCOUNT", "SMARTCARD_REQUIRED",
"TRUSTED_FOR_DELEGATION", "NOT_DELEGATED","USE_DES_KEY_ONLY", "DONT_REQ_PREAUTH",
"PASSWORD_EXPIRED", "TRUSTED_TO_AUTH_FOR_DELEGATION")
1..($flags.length) | ? {$value -band [math]::Pow(2,$_)} | % { $flags[$_] }

Restart-Service (recursively)

I often need to restart services on multiple machines and one of the biggest issues is the dependent services that also need to be restarted. I finally found time to write a script that will recursively stop and start dependent services.

Parameters:

  • ServiceName: Name of the Service to restart (REQUIRED)
  • Server: Name of the Server to restart the service on (Default is local server)
  • Verbose: Enable verbose output

More Info:
System.ServiceProcess.ServiceController

Restart-Service


Param($ServiceName = $(throw ‘$ServiceName is Required’),
      $Server = $Env:ComputerName,
      [Switch]$Verbose)

$VerbosePreference = "Continue"

[system.Reflection.Assembly]::LoadWithPartialName("System.ServiceProcess") | out-Null

$ErrorActionPreference = "SilentlyContinue"

Write-Verbose " – ServiceName = $ServiceName"
Write-Verbose " – Server = $Server"

function Get-Dependents{
    Param([System.ServiceProcess.ServiceController]$MasterService)
    Write-Verbose "   + Getting Dependent Services for $($MasterService.Name)"
    foreach($dependent in $MasterService.DependentServices)
    {
        Write-Verbose "     – Found Dependent Service [$($dependent.Name)]"
        $dependent
        Get-Dependents $dependent
    }
}

Write-Verbose " – Getting Service [$ServiceName]"
$Service = New-Object System.ServiceProcess.ServiceController($ServiceName,$Server)

Write-Verbose " – Getting Dependent Services"
$DependentServices = Get-Dependents $Service

Write-Verbose " + Stopping [$ServiceName] and dependent Services"
$Service.Stop()

Write-Verbose "   – Waiting for Service to Stop"
$Service.WaitForStatus("Stopped",(new-object system.TimeSpan(0,0,20)))

Write-Verbose " + Starting [$ServiceName]"
$Service.Start()

Write-Verbose "   – Waiting for Service to Start"
$Service.WaitForStatus("Running",(new-object system.TimeSpan(0,0,20)))

foreach($dependent in $DependentServices )
{
    $dependent.Refresh()
    if($dependent.status -eq "Stopped")
    {
        $dependent.Start()
        $dependent.WaitForStatus("Running",(new-object system.TimeSpan(0,0,5)))
    }
}
$Service.Refresh()
$Service
$Service.DependentServices

Run-Command.ps1 : Run External Commands with Power!

I was working late tonight and we had to run a bunch of third party EXEs and such. We do this a good bit so I can’t always avoid calling external executables and I also find psexec.exe much easier than any powershell way to run remote commands. That said I find myself constantly writing this.

$servers = Get-Content $file
foreach($server in $servers)
{
   Do Something Here Like
   psexec \\$server mycmd.exe param1
}

I decided to write a script call Run-Command.ps1.
This will take three parameters
– File (list of servers to process)
– Cmd (Command to run with %S% where you want the server name to be replaced)
– Check (just shows what command would run)
– Will also take Piped Input

Example:
PS> .\Run-Command.ps1 -file c:\serverlist.txt -cmd “psexec \\%S% mycmd.exe Hello World” -check

Run-Command.ps1

Param($file,$cmd,[switch]$whatif,[switch]$verbose)
Begin{
    function Ping-Server {
        Param([string]$srv)
        $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
        if($pingresult.statuscode -eq 0) {$true} else {$false}
    }
    $servers = @()
}
Process{
    if($_)
    {
        if($_.ServerName){$servers += $_.ServerName}
        else{$servers += $_}
    }
}
End{
    if($file){Get-Content $file | %{$servers += $_}}
    foreach($server in $servers)
    {
        if(ping-server $server)
        {
            if($verbose){Write-Host "+ Processing Server $Server"}
            $mycmd = $cmd -replace "\%S\%",$Server
            if($whatif){Write-Host "  – WOULD RUN $mycmd"}
            else{if($verbose){Write-Host "  – Running $mycmd"};invoke-Expression $mycmd}
        }
        else
        {
            Write-Host "+ $Server FAILED PING" -foregroundcolor RED
        }
    }
}

Get-ChildItem with Pretty Colors (UPDATED)

Cedric Posted a message on the NG (news group) wanting a function like ls for linux. He wanted color while keeping width. I am sure there are other ways to do this, but what I did was created a script (I will convert to a function later) called Get-ChildItemPretty.ps1. The code is at the bottom, but I wanted to point out a few things.

1) It has 3 Parameters and 1 switch
– Dir: This is the Path you want to List (Defaults to $pwd)
– Wide : How Many Colums Wide (Defaults to 3)
– Pad : For Spacing on the Names (Defaults to 30)
– Recurse : Switch to Recurse
– Passtru : outputs objects
2) By default this colors Folders Blue and Exe’s Red, but you could add what ever colors and extentions you want.
3) I have thought about adding a Sort option to Sort by Name or by Type (what do you think?)
4) You could add -full switch that would return fullname instead of just name.
5) You could add -output switch that would return objects as well for pipeline parsing.

### UPDATED ###
Working with /\/\0\/\/ (mostly MOW really) we came up with a better way using $host.UI
This adds a PassTru to output objects

# Colored wide directory list function
#
# /\/\o\/\/ 2007
# www.thePowerShellGuy.com
function List-Wide { param ($dir=$pwd,$Column=3,[Switch]$PassTru,[Switch]$recurse)
    $origFg = $host.ui.rawui.foregroundColor
    if($recurse)
    {
        $list = get-ChildItem $dir -recurse
    }
    else
    {
        $list = get-ChildItem $dir
    }
    foreach ($Item in $list)
    {
        Switch ($Item.Extension)
        {
            ".Exe" {$foregroundColor = "Yellow"}
            ".cmd" {$foregroundColor = "Green"}
            ".ps1" {$foregroundColor = "Red"}
            ".vbs" {$foregroundColor = "Red"}
            Default {$foregroundColor = $origFg}
        }
        if ($item.PSISContainer) {$foregroundColor = "Blue"}
        $max = \[int\]($Host.UI.RawUI.WindowSize.Width / $Column)
        $field = ($item.name.padRight($max).Substring(0,($Max -1)) + ‘ ‘)
        if ($item.name.length -gt $max -1)
        {
            $field = $field.Substring(0,($Max -3)) + ‘\*\*\*’
        }
        if ($Host.UI.RawUI.WindowSize.Width$host.UI.RawUI.CursorPosition.X -lt $max)
        {
            $host.ui.WriteLine()
        }
        $Host.UI.Write($foregroundColor,$host.ui.rawui.BackgroundColor,$field)
        if ($PassTru)
        {
            $Item
        }
    }
    $Host.UI.WriteLine()
}

Old Version

							
					
					
				

Birth of a Script/Function

I know my post have been few and far between, but I have been super swamped at work and will be for a few more months at least.

That said I am writing some scripts and functions for work and as I was writing one today I though maybe I should share how I go about writing a function slash script. I like step-by-step lists so I decided at that format.

1> A purpose
– All Scripts must start with a purpose. Be it install something or check something. It needs to do something.

2> I figure the best process to do what I want
– Can what I want done be remoted?
– Do I use WMI?
– Do I use .NET?
– Do I use external Commands?
– Who is going to be doing it? What rights do they need?
– Does it have potential to break stuff (BIGGY!!!)

3> Write a function or functions that do what I want done on one Server, Device, or file
Example

function Checkhf{
   Param($srv,$ptch)
   $hf = get-WmiObject Win32_QuickfixEngineering -ComputerName $srv | where-Object{$_.HotfixID -match $ptch}
   if($hf)
   {
      return $true
   }
   else
   {
      return $false
   }
}

4> Cut and Paste function into my templates (At the bottom of post)
– Add any missing parameters
– Add any extra parsing
– Add error control if needed

5> Now it looks like this

function Check-Hotfix {
    Param([string]$server,[string]$hotfix)
    Begin{
        function PingServer {
            param([string]$srv)
            $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
            if($pingresult.statuscode -eq 0) {$true} else {$false}
        }
        function Checkhf{
            Param($srv,$ptch)
            $hf = get-WmiObject Win32_QuickfixEngineering -ComputerName $srv | where-Object{$_.HotfixID -match $ptch}
            if($hf)
            {
                return $true
            }
            else
            {
                return $false
            }
        }
        Write-Host
        $process = @()
    }
    Process{
        if($_)
        {
            if($_.ServerName)
            {
                $process += $_.ServerName
            }
            else
            {
                $process += $_
            }
        }
    }
    End{
        if($Server){$Process += $Server}
        if($process.Length -eq 0){$Process += get-content env:COMPUTERNAME}
        foreach($s in $process)
        {
            if(PingServer $s)
            {
                $myobj = "" | select-Object Server,Result
                $myobj.Server = $s
                $myobj.Result = Checkhf -srv $s -ptch $hotfix
                Write-Output $myObj
            }
        }
    }
}

6> Final Test

Here are my Templates
– By default they take a Pipe, Server, or File and will process all three

Template for Script

Param([string]$server,[string]$file)
Begin{
    function PingServer {
        param($srv)
        $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
        if($pingresult.statuscode -eq 0) {$true} else {$false}
    }
    function InsertFunctionHere{
    }
    Write-Host
    $process = @()
}
Process{
    if($_)
    {
        if($_.ServerName)
        {
            $process += $_.ServerName
        }
        else
        {
            $process += $_
        }
    }
}
End{
    # Check if $server is populated and add to Process Array
    if($Server){$Process += $Server}
    # Check if $file is populated and add to Process Array
    if($file)
    {
        foreach($entry in (get-content $file))
        {
            $Process += $entry
        }
    }
    # If Process Array is empty… Add self
    if($process.Length -eq 0){$Process += get-content env:COMPUTERNAME}
    foreach($s in $process)
    {
        if(pingserver $s)
        {
            InsertFunctionHere $s
        }
        Write-Host
    }
}

Template for Function

function Verb-Noun {
    Param([string]$server,[string]$file)
    Begin{
        function PingServer {
            param($srv)
            $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
            if($pingresult.statuscode -eq 0) {$true} else {$false}
        }
        function InsertFunctionHere{
        }
        Write-Host
        $process = @()
    }
    Process{
        if($_)
        {
            if($_.ServerName)
            {
                $process += $_.ServerName
            }
            else
            {
                $process += $_
            }
        }
    }
    End{
        # Check if $server is populated and add to Process Array
        if($Server){$Process += $Server}
        # Check if $file is populated and add to Process Array
        if($file)
        {
            foreach($entry in (get-content $file))
            {
                $Process += $entry
            }
        }
        # If Process Array is empty… Add self
        if($process.Length -eq 0){$Process += get-content env:COMPUTERNAME}
        foreach($s in $process)
        {
            if(pingserver $s)
            {
                InsertFunctionHere $s
            }
            Write-Host
        }
    }
}

« Prev - Next »