PowerShell for Windows Admins


April 22, 2010  3:08 PM

Current logged on user

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

in case you are wondering how I pick the topics for these posts – its quite scientific.  I run

Get-WmiObject -List win32* | where {$_.Name -notlike “*perf*”}

to see the available classes and pick something that catches my eye. Sometimes it leads to a series of posts and other times its a single post.

This time my eye was caught by Win32_LogonSession – which returns the logged on user

PS> Get-WmiObject -Class Win32_LogonSession

AuthenticationPackage : NTLM
LogonId               : 188568
LogonType             : 2
Name                  :
StartTime             : 20100422181039.691600+060
Status                :

AuthenticationPackage : NTLM
LogonId               : 188537
LogonType             : 2
Name                  :
StartTime             : 20100422181039.691600+060
Status
                :

OK thats not good ‘cos I know I’m the only one logged in – unless its my imaginary friend

PS> Get-WmiObject -Class Win32_SessionProcess | select Antecedent

Antecedent
———-
\\.\root\cimv2:Win32_LogonSession.LogonId=”188568″
\\.\root\cimv2:Win32_LogonSession.LogonId=”188568″

etc

Shows that LogonId 188568 is the latest as Win32_SessionProcess shows the processes associated with the current logged on user.

We need to take that fact and find the logged on user

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
## get session process
$proc = Get-WmiObject -Class Win32_SessionProcess | 
select Antecedent -First 1
$filt = ($proc -split “=”)[2] -replace ‘”‘,  -replace “}”,“”

$ltype = DATA {
ConvertFrom-StringData -StringData @’
0 = System
2 = Interactive
3 = Network
4 = Batch
5 = Service
6 = Proxy
7 = Unlock
8 = NetworkCleartext
9 = NewCredentials
10 = RemoteInteractive
11 = CachedInteractive
12 = CachedRemoteInteractive
13 = CachedUnlock
‘@

}
## get logon session
$sess = Get-WmiObject -Class Win32_LogonSession -Filter “LogonId=’$filt'”

## get user
$query = “ASSOCIATORS OF {Win32_LogonSession.LogonId=’$filt’} `
WHERE ResultClass=Win32_UserAccount”

$user = Get-WmiObject -Query  $query
 
Add-Member -InputObject $sess -MemberType NoteProperty -Name User `
 -Value $($user.Caption) -PassThru |
Format-List AuthenticationPackage, LogonId,
@{Name=“Logon Type”; Expression = {$ltype[“$($_.LogonType)”]}},
@{Name=“Time”; Expression = {$_.ConvertToDateTime($_.StartTime)}},
User

 

 

We take our session process – select first 1 and we only need the Antecedent property. We then split it on a “=” sign and do 2 replaces to clean it up.  I was surprised when the operators combined like that.

The here-string defines a the logon types. We find the Win32_LogonSession associated with the logonid and then get the ASSOCIATORS to find the associated user.

We use Add-Member to add the user name property to the session information and then use a couple of calculated fields to display the logon type and the logon date

April 22, 2010  1:15 PM

Windows System Assessment Tool

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The Windows System Assessment Tool was introduced with Windows Vista.  It gives a score 1-7.9 (on Windows 7) for components such as memory, processor and disk. The scores are accessible through the System icon in Control Panel – or we can use a bit of WMI

PS> Get-WmiObject -Class Win32_WinSAT | select __SERVER, *score, *level

__SERVER      : RSLAPTOP01
CPUScore      : 4.7
D3DScore      : 4.6
DiskScore     : 5.5
GraphicsScore : 3.7
MemoryScore   : 5.5
WinSPRLevel   : 3.7

Plus we can use the –computername parameter to retrieve the information for remote machines


April 21, 2010  2:30 PM

Shares:Security

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

In the previous post we saw how to get the Access Mask for the current user for a particular share.  It would be better if we could dump the information for all shares and all security access in one go.

We need to use Win32_LogicalAccess

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
function Get-ShareSecurity {

    Get-WmiObject -Class Win32_LogicalShareAccess |
    foreach {
       $name = ($_.SecuritySetting -split “=”)[1]
       $sid = (($_.Trustee -split “=”)[1]).Replace(‘”‘,)
       $AccessMask = $_.AccessMask
      
       $query =  “ASSOCIATORS OF {Win32_SID.SID='” `
       + $sid + “‘} WHERE ResultClass=Win32_SystemAccount”
      
       $trustee = Get-WmiObject -Query $query 
      
       if($trustee -eq $null){
            $query =  “ASSOCIATORS OF {Win32_SID.SID='” `
            + $sid + “‘} WHERE ResultClass=Win32_UserAccount”
            #$query
            $trustee = Get-WmiObject -Query $query 
       }
      
       if($trustee -eq $null){
            $query =  “ASSOCIATORS OF {Win32_SID.SID='” `
            + $sid + “‘} WHERE ResultClass=Win32_Group”
             $trustee = Get-WmiObject -Query $query 
       }
      
       “`nSHARE: $name USER: $($trustee.Caption) RIGHTS:”
       ## now we need to unravel the rights
        $mask.GetEnumerator()| sort Key | 
        foreach {
            if ($AccessMask -band $_.key){“$($mask[$($_.key)])”}
        }
      
    }
}

 

It returns an object for each share for each user or group that gets access to the share.

For each object returned we get the share name, the SID and the access mask. We use the SID to find the user, system or group account that has that access and then dump out the rights as we saw last time


April 14, 2010  7:08 AM

Shares: Access mask

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The access mask controls what you can do i.e. what rights you have. We can use the GetAccessMask method to find the access mask but all we get back is a number we need unravel it. The number id a bit mask with the following values assigned

$mask = DATA {
ConvertFrom-StringData -StringData @’
1 = Grants the right to read data from the file. For a directory, this value grants the right to list the contents of the directory.
2 = Grants the right to write data to the file. For a directory, this value grants the right to create a file in the directory.
4 = Grants the right to append data to the file. For a directory, this value grants the right to create a subdirectory.
8 = Grants the right to read extended attributes.
16 = Grants the right to write extended attributes.
32 = Grants the right to execute a file. For a directory, the directory can be traversed.
64 = Grants the right to delete a directory and all of the files it contains (its children), even if the files are read-only.
128 = Grants the right to read file attributes.
256 = Grants the right to change file attributes.
65536 = Grants delete access.
131072 = Grants read access to the security descriptor and owner.
262144 = Grants write access to the discretionary access control list (DACL).
524288 = Assigns the write owner.
1048576 = Synchronizes access and allows a process to wait for an object to enter the signaled state.
‘@
}

We can use the mask like this

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
function Get-ShareAccessMask {
[CmdletBinding(SupportsShouldProcess=$True)]
param (
    [string]$name
)   
    $share = Get-WmiObject -Class Win32_Share -Filter "Name=’$name’" 
$ret = (Invoke-WmiMethod -InputObject $share -Name GetAccessMask).ReturnValue
   
    ## now we need to unravel the rights
    $mask.GetEnumerator()| sort Key | foreach {
       if ($ret -band $_.key){
            "$($mask[$($_.key)])"
        }
   
    }
}   

 

We use invoke-wmimethod to get the mask and then compare the keys of our hash table against the access mask.

This returns the mask for the person running the script not the whole mask.

Technorati Tags: ,,,


April 12, 2010  9:58 AM

Powershell User Group Live Meeting: Modules

Richard Siddaway Richard Siddaway Profile: Richard Siddaway


When: Tuesday, Apr 20, 2010 7:30 PM (BST)


Where: Virtual

*~*~*~*~*~*~*~*~*~*

Notes

We will cover the new module functionality introduced with PowerShell v2 with a biref look at some of the functionality available in Windows 7/Windows 2008 R2


Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

  1. Copy this address and paste it into your web browser:
    https://www.livemeeting.com/cc/usergroups/join
  2. Copy and paste the required information:
    Meeting ID: B3FG29
    Entry Code: Zft%D4B7H
    Location: https://www.livemeeting.com/cc/usergroups

If you still cannot enter the meeting, contact support

Notice
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.


April 9, 2010  12:42 PM

PowerShell for DNS

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I’ve blogged on a number of occasions on how to use the DNS WMI provider.

Life just got easier with the release of DnsShell.  Its a PowerShell 2.0 module containing cmdlets for working with DNS.

Underneath the covers there is a lot of WMI involved.

The module is still a work in progress but already includes useful functionality.  I’ll be giving it a try out soon.

The module can be down loaded from http://code.msdn.microsoft.com/dnsshell

Technorati Tags: ,,


April 2, 2010  11:14 AM

Shares: Discovering

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

As I said last time I’ve modified the Get-Share function to accept a share name.

001
002
003
004
005
006
007
function Get-Share {
param (
    [string]$name
)   
    if (!$name) {Get-WmiObject -Class Win32_Share}
    else {Get-WmiObject -Class Win32_Share -Filter “Name=’$name'”}
}

if a name isn’t provided that all shares are returned.  If we supply a name only that share is returned. In either case we can put the object onto the pipeline and perform further processing.

Get-Share | ft name, maximumallowed, description

Get-Share -name test1 | fl name, maximumallowed, description


April 2, 2010  11:07 AM

Shares: Modifying

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

So far we’ve seen how to discover and create shares.  How do we alter a share?

When we created a share we supplied a number of pieces of information:

  1. folder path
  2. name
  3. type – disk share
  4. maximum number of connections
  5. description

The last two and the permissions mask are the ones we want to alter

001
002
003
004
005
006
007
008
009
010
011
012
013
014
function Set-Share {
[CmdletBinding(SupportsShouldProcess=$True)]
param (
    [string]$name,
    [int]$maxcon,
    [string]$desc
)   
    $share = Get-WmiObject -Class Win32_Share -Filter "Name=’$name’" 
    if (!$maxcon){$maxcon = $share.MaximumAllowed }
    if (!$desc){$desc = $share.Description}
   
    $share.SetShareInfo($maxcon, $desc, $null)

}

Use the share name, maximum connections and description as parameters. If either the number of connections or the description is not set we use the current value.

A call to the SetShareInfo method is used to perform the change.  The $null value at the end is the access mask which we will see how to change later.

The function is used like this

Get-Share -name test1 | fl name, maximumallowed, description
Set-Share -name test1 -desc "Changed"
Get-Share -name test1 | fl name, maximumallowed, description

Set-Share -name test1 -maxcon 25
Get-Share -name test1 | fl name, maximumallowed, description

Set-Share -name test1 -maxcon 25 -desc "New Description"
Get-Share -name test1 | fl name, maximumallowed, description

I’ve altered my Get-Share function so that it becomes capable of returning a single share.  I’ll post that change next


April 1, 2010  12:48 PM

MVP re-award

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I had a very nice email from the Microsoft MVP award program today informing me that I had been re-awarded as a PowerShell MVP.

Its a great honour to receive the MVP award and thank you to Microsoft for the award and to the PowerShell community for supporting my efforts.


March 30, 2010  2:34 PM

Shares: Creating III

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

In a previous post

http://itknowledgeexchange.techtarget.com/powershell/shares-creating-ii/

we looked at creating a file share. This function can be expanded to test for the existence of the folder and if we succeed or not.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
function New-Share {
[CmdletBinding(SupportsShouldProcess=$True)]
param (
    [string]$path,
    [string]$name,
    [int][ValidateRange(0,2)]$type,
    [int]$maxcon,
    [string]$desc
)

$fail = DATA {
ConvertFrom-StringData -StringData @’
0 = Success
2 = Access Denied
8 = Unknown Failure
9 = Invalid Name
10 = Invalid Level
21 = Invalid Parameter
22 = Duplicate Share
23 = Redirected Path
24 = Unknown Device or Directory
25 = Net Name Not Found
‘@

}

    if (!(Test-Path -Path $path)){Throw “Folder does not exist”}
    $s = [WmiClass]“Win32_Share” 
    $ret = $s.Create($path, $name, $type, $maxcon, $desc)
    if ($ret.ReturnValue -ne 0){
        Write-Host “Share $name was not created”
        Write-Host “Failure reason: $($fail[“$($ret.ReturnValue)”])”
    }
    else {Write-Host “Share $name was created”}
}

 

 

We add a hash table of the return codes from the create method. A simple Test-Path enables us to determine if the share exists.

We can test the return code and if the value is zero state the creation succeeded otherwise we report failure and the reason.

PS> New-Share -path c:\share1 -name Test1 -type 0 -maxcon $null -desc “Test share 1 from module”
Share Test1 was not created
Failure reason: Duplicate Share

Technorati Tags: ,


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: