Finding Groups of Logged On User

If you’d like to know the group memberships of the currently logged on user (the one that is running a script), you don’t need to query the Active Directory. Instead, examine the access token. It contains all effective group memberships, including nested ones:

#requires -Version 1
  $groups = ([Security.Principal.WindowsIdentity]::GetCurrent()).Groups | 
  ForEach-Object {
  } | Sort-Object
  Write-Warning 'Groups could not be retrieved.' 


Twitter This Tip! ReTweet this Tip!

Creating Dynamic Variable Content

PowerShell 2+

In the previous tip we introduced variables with read-only dynamic content that updated each time the variable was read. This required a little bit of C# code. With Add-Member, you can get a similar result using script properties:

$info = New-Object -TypeName PSObject
$info | Add-Member -Name Random -MemberType ScriptProperty -Value { Get-Random }
$info | Add-Member -Name Now -MemberType ScriptProperty -Value { Get-Date }

You can now call $info.Random or $info.Now to get a new random number or the current date.

Twitter This Tip! ReTweet this Tip!

Creating Dynamic Variable Content

PowerShell 2+

A little-known fact is that you can add variables to PowerShell that automatically update their content. If you need random numbers, for example, this code would add a new variable called $Random that provides a new random number each time it is called:

Add-Type 'using System;
using System.Management.Automation;
public class FixedVariableRandom : PSVariable
Random r;
public FixedVariableRandom()
  : base("Random", 0, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope)
  {r = new Random();}

  public override object Value
    get { return  r.Next(); }

$ExecutionContext.SessionState.PSVariable.Set((New-Object FixedVariableRandom))

Likewise, this example creates a variable named $Now which always returns the current date and time:

Add-Type 'using System;
using System.Management.Automation;
public class FixedVariableNow : PSVariable
public FixedVariableNow()
  : base("Now", 0, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope)

  public override object Value
    get { return  DateTime.Now; }

$ExecutionContext.SessionState.PSVariable.Set((New-Object FixedVariableNow))

Twitter This Tip! ReTweet this Tip!

Create Simple PowerShell Host

PowerShell 2 or better

There are sometimes a lot of good reasons why you’d like to run a script by a different host. powershell.exe might be blocked by an AppLocker policy, or you’d like to run a PowerShell script invisible, without displaying a console.

Any PowerShell host can execute PowerShell scripts, and thanks to Add-Type, it is easy to use PowerShell to compile such a host. When you run this code, you end up with a new console application called PSHost.exe on your desktop:

# this is the C# code for a simple PowerShell host
$code = @'
using System.Management.Automation;  
using System.Collections.ObjectModel;

namespace PowerSaw {  
  class Program {
    static void Main(string[] args) {
      if (args.Length == 0) return;
      using (PowerShell ps = PowerShell.Create()) {
        string code = System.IO.File.ReadAllText(args[0]);
        Collection<PSObject> psobject = ps.Invoke();

# parameters for compilation to a console EXE
$params = @{
  OutputAssembly = "$homeDesktopPSHost.exe"
  OutputType = 'ConsoleApplication'
  ReferencedAssemblies = [PSObject].Assembly.Location
  TypeDefinition = $Code

# create an EXE file
Add-Type @params

# show EXE file
explorer.exe /select,$params.OutputAssembly

Now, you can use this simple host to run arbitrary PowerShell scripts. Simply pass the script path as argument to the EXE. Here is an example (assuming that you ran the above code and have PSHost.exe on your desktop):

$Desktop = "$homedesktop"
$ScriptPath = "$Desktopgetservices.ps1"
'Get-Service | Out-GridView -Wait' | Out-File -FilePath $ScriptPath -Encoding UTF8

& "$Desktoppshost.exe" $ScriptPath

Note that the simple PowerShell host created in this example has no output logic. So use it to call PowerShell scripts that just do things, or pipe the results to some output platform such as Out-GridView. Note also that the host will close as soon as the script is done.

Twitter This Tip! ReTweet this Tip!

Creating PowerShell Web Server

All Versions

Here is an example that implements a simple web server with just a few lines of code. When you run this script, you can enter one of these URLs into any web browser on your machine:



And here is the code:

# enter this URL to reach PowerShell’s web server
$url = 'http://localhost:8080/'

# HTML content for some URLs entered by the user
$htmlcontents = @{
  'GET /'  =  '<html><body>Here is PowerShell</body></html>'
  'GET /services'  =  Get-Service | ConvertTo-Html


# start web server
$listener = New-Object System.Net.HttpListener

  while ($listener.IsListening) {  
    # process received request
    $context = $listener.GetContext()
    $Request = $context.Request
    $Response = $context.Response

    $received = '{0} {1}' -f $Request.httpmethod, $Request.url.localpath
    # is there HTML content for this URL?
    $html = $htmlcontents[$received]
    if ($html -eq $null) {
      $Response.statuscode = 404
      $html = 'Oops, the page is not available!'
    # return the HTML to the caller
    $buffer = [Text.Encoding]::UTF8.GetBytes($html)
    $Response.ContentLength64 = $buffer.length
    $Response.OutputStream.Write($buffer, 0, $buffer.length)

Please note that the listener runs in an endless loop. When you abort the script, it takes another web request from a web browser for PowerShell to return to you.

Twitter This Tip! ReTweet this Tip!

Changing Password

All versions

Here is a simple way how an existing user can change the password for his account. The user must know his old password and does not need Administrator privileges. Make sure you change the user details at the beginning of this script:

$username = 'yourUserName'
$domain = 'test.lab'

$oldPassword = 'OldPassword'
$newPassword = 'NewPassword'

$sourceCode = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern bool NetUserChangePassword(string domain, string username, string oldpassword, string newpassword);  

Add-Type -MemberDefinition $sourceCode -Name 'Api' -Namespace 'Win32'

[Win32.API]::NetUserChangePassword($domain, $username, $oldPassword, $newPassword)

Twitter This Tip! ReTweet this Tip!