PowerShell for Windows Admins


June 24, 2012  9:05 AM

WMI property names

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question brought it home to me that WMI property names don’t always mean what you might think they mean – this is also true of other objects but I tripped over this one with WMI so we’ll stick with that.

PS> Get-CimInstance -ClassName Win32_Desktop -Filter "Name LIKE ‘%Richard’" |
>> Format-List ScreenSaver*
>>

ScreenSaverActive     : True
ScreenSaverExecutable : C:\Windows\system32\PhotoScreensaver.scr
ScreenSaverSecure     : True
ScreenSaverTimeout    : 600

 

The ScreenSaverActive property doesn’t mean that the screen saver is currently active – it means that one has been set!   This is doubly confusing because the documentation states

ScreenSaverActive

Data type: boolean
Access type: Read-only

Screen saver is active.

Which would lead you to think that is was actually running!

The ScreenSaverSecure means that a password has been set to unlock the system once the screen saver kicks in & ScreenSaverTimeout is the idle time in seconds before the screen saver kicks in. The executable is the screen saver that will be used.

If you want to get the information with the WMI cmdlets use

PS> Get-WmiObject Win32_Desktop -Filter "Name LIKE ‘%Richard’" |
>> Format-List ScreenSaver*
>>

ScreenSaverActive     : True
ScreenSaverExecutable : C:\Windows\system32\PhotoScreensaver.scr
ScreenSaverSecure     : True
ScreenSaverTimeout    : 600

June 12, 2012  12:53 PM

UK PowerShell Group–July 2012

Richard Siddaway Richard Siddaway Profile: Richard Siddaway


When: Wednesday, Jul 4, 2012 8:30 PM (BST)


Where: Virtual

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

Jonathan Medd will be talking about using PowerShell to administer a XenDesktop environment

Notes


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: R2TT4R
    Entry Code: Jc-‘8JM;W
    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.


June 8, 2012  12:22 PM

Working with profiles: 2 deleting profiles

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I recently (1 June) showed how to discover the user profiles on your system. Now its time to delete them.

function remove-profile {            
 param (            
  [parameter(Mandatory=$true)]            
  [string]$username            
 )            
            
 $user = Get-CimInstance -Class Win32_UserAccount -Filter "Name = '$username'"             
 $profile = Get-CimInstance -Class Win32_UserProfile -Filter "SID = '$($user.SID)'"            
 $folder = Split-Path -Path $profile.LocalPath -Leaf            
            
 if ($folder -eq $username){            
  Remove-CimInstance -InputObject $profile            
 }            
 else {            
  Write-Warning -Message "Could not resolve profile and user name"             
 }            
            
}

I’m going to start with the CIM cmdlets as these are the way of the future in PowerShell v3.

Start by taking a user name as a parameter. Get the Win32_UserAccount class object representing that account. use the SID to find the profile via Win32_UserProfile.  Take the profile’s localpath and split it. The last part of the path should match the username – if it does then delete the profile otherwise throw a warning. Deleting the profile does delete the folder under c:\users

If you have to use the WMI cmdlets then its very similar

function remove-profile {            
 param (            
  [parameter(Mandatory=$true)]            
  [string]$username            
 )            
            
 $user = Get-WmiObject -Class Win32_UserAccount -Filter "Name = '$username'"             
 $profile = Get-WmiObject -Class Win32_UserProfile -Filter "SID = '$($user.SID)'"            
 $folder = Split-Path -Path $profile.LocalPath -Leaf            
            
 if ($folder -eq $username){            
  Remove-WmiObject -InputObject $profile            
 }            
 else {            
  Write-Warning -Message "Could not resolve profile and user name"             
 }            
            
}

Just the name of the cmdlets change.

You can’t use WMI to delete local accounts as explained on page 363 of PowerShell and WMI 

If you have profiles generated by AD accounts you’ll need to find the SID from the AD account and use that as the filter for deletion


June 8, 2012  7:53 AM

Cleaning up the temp folder

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

This post

http://powershell.com/cs/blogs/tips/archive/2012/06/05/checking-size-of-downloads-folder.aspx

go me thinking about the temp folder. Its one of those areas tucked away in your profile that just seems to get left to grow.  Time to do something about it.

$testdate = (Get-Date).AddDays(-10)            
$names = "FXSAPIDebugLogFile.txt", "hsperfdata_Richard"            
            
## assume TMP = TEMP            
$path = $env:TEMP            
            
Get-ChildItem -Path $path -File  |            
where LastWriteTime -lt $testdate |            
where Name -NotIn $names |            
Remove-Item -Force #-WhatIf            
            
Get-ChildItem -Path $path -Directory |            
where LastWriteTime -lt $testdate |            
where Name -NotIn $names |            
Remove-Item -Force -Recurse #-WhatIf

I decide to use some of the new functionality in PowerShell v3 and separate the file and folder processing so I could play (er experiment) with some of the new parameters in  Get-ChildItem

Get-ChildItem [-Attributes <FileAttributes]>] [-Directory] [-File] [-Force] [-Hidden] [-ReadOnly] [-System]

[-UseTransaction] [<CommonParameters>]

These are a separate parameter set which means that -exclude and –include don’t work with them.

So start by creating a date to test against. Anything older than this will be deleted. Define a few names of things that have to be left alone (these will probably be different on your system) and set the path. I’ve assumed that the TEMP and TMP environmental variables point to the same path. if your system is different put the rest of the code into a foreach loop to iterate through the two variables.

Starting with files we get all the files in the root of TEMP. The –File parameter means we only look at files – folders are automatically excluded.

I’ve then used two where statements. Now the obvious comment is that I could combine them but if I do that I have to check each file for its age and then if its name is in my exclusion list. This way I test for age and immediately filter out any file that it is too young. Then I test for name. Doing it this way gives a small performance increase if you have a lot of young files.

I then pass the files to Remove-Item to delete.

The directories are processed in a similar manner except that we use –Directory on Get-ChildItem and add –Recurse to the Remove-Item call so that non-empty folders are removed.

Next move is to make this a scheduled task using the new PowerShell scheduled task cmdlets.


June 8, 2012  2:34 AM

PowerShell in Depth excerpts

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

If you haven’t seen them already Microsoft’s ScriptingGuy has kindly published a couple of excerpts from PowerShell in Depth by Don Jones, Jeff Hicks and myself

http://blogs.technet.com/b/heyscriptingguy/archive/2012/06/04/powershell-in-depth-part-1.aspx

http://blogs.technet.com/b/heyscriptingguy/archive/2012/06/05/powershell-in-depth-part-2.aspx

Enjoy


June 2, 2012  8:19 AM

Toggling between LAN and Wireless

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

One of the questions in the recent Scripting Games involved toggling between a wireless and LAN connection. Only one was to be up at any one time.

This can be solved using WMI but becomes hugely simpler in Windows 8/2012 as we get a bunch of cmdlets for working with network adapters.

Using WMI

Get-WmiObject -Class Win32_NetworkAdapter | Measure-Object

I get 15 objects returned on my system – but I’m only interested in 2 of them!

Using the new functionality

PS> Get-NetAdapter | ft -a Name, ifIndex, Status

Name             ifIndex Status
—-             ——- ——
Virtual Wireless      21 Disabled
Virtual LAN           12 Up

This leads to a simple piece of code

Get-NetAdapter |
foreach {
  $nic = $_
  switch ($_.Status){
   "Up"        {Disable-NetAdapter -InputObject $nic -Confirm:$false}
   "Disabled"  {Enable-NetAdapter -InputObject $nic -Confirm:$false}

  }
}

Get the adapter, test its status and toggle to the other.

These cmdlets are in the NetAdapter module which is created using the cmdlets over objects techniques to utilise WMI classes in a much friendlier way. Remoting capabilities are supplied by CIMsessions


June 2, 2012  7:58 AM

Using a colon with cmdlet parameters

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Another question at Tuesdays PowerShell group revolved around using colons to link values to parameters. I’d not really thought about before. Thinking about it  later I realised that you only really see it when passing booleans to –Confirm.  If you don’t use a colon then you get this

PS> Disable-NetAdapter -Name "Virtual Wireless" -Confirm $false
Disable-NetAdapter : A positional parameter cannot be found that accepts argument ‘False’.
At line:1 char:1
+ Disable-NetAdapter -Name "Virtual Wireless" -Confirm $false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Disable-NetAdapter], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Disable-NetAdapter

But this will work

PS> Disable-NetAdapter -Name "Virtual Wireless" -Confirm:$false

Just for completeness this works as well

PS> Get-NetAdapter –Name:"Virtual Wireless" 

though it doesn’t tend to get used


June 2, 2012  6:34 AM

Using Windows 2012 Active Directory module in a Windows 2008 R2 domain

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question came up on Tuesdays UK PowerShell Group session about using the Windows 2012 Active Directory module. The recording links are here

http://msmvps.com/blogs/richardsiddaway/archive/2012/05/30/may-2012-powershell-group-recording-and-slides.aspx

The question asked if the new Site, Subnet and Site link cmdlets would work in a legacy environment.

This morning I installed a Windows Server 2012 Release Candidate member server into my Windows 2008 R2 domain. I then installed the RSAT feature on the Windows 2012 server – this includes the Active Directory module.

The site, subnet and site link cmdlets appear to work with NO changes required to the Windows 2008 R2 domain controller. I was able to view and create sites, subnets and site links.

I haven’t tested any other scenario.


June 2, 2012  3:07 AM

PowerShell v3 release candidate

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Hot on the heels of the Windows 8/2012 release candidates comes the PowerShell v3 (well Ok the Windows Management Framework) release candidate.

This is available for

  • Windows 7 SP 1
  • Windows Server 2008 R2 SP 1
  • Windows 2008 SP2

32 and 64 bit versions are available as applicable to the OS

Notice the omissions Vista, Windows 2003 and XP. If that continues into RTM there will be some issues around using the some of the functionality across the estate as it relies on WSMAN 3.0

Details and links from here

http://blogs.msdn.com/b/powershell/archive/2012/06/02/windows-management-framework-3-0-rc-is-available-for-download.aspx


June 1, 2012  1:07 PM

Working with profiles: part 1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question came up on the forum for PowerShell and WMI – how do I delete profiles. I’m going to work up to answering that by looking at using WMI to work with profiles.

So to start how can we find the profiles available on our system

Get-WmiObject -Class Win32_UserProfile |
select LocalPath, SID, @{N="LastUseTime"; E={$_.ConvertToDateTime($_.LastUseTime)}}

LocalPath                   SID                         LastUseTime              
———                   —                         ———–              
C:\Users\Richard            S-1-5-21-2542198769-1191… 01/06/2012 19:56:28      
C:\Windows\ServiceProfil… S-1-5-20                                             
C:\Windows\ServiceProfil… S-1-5-19                                             
C:\Windows\system32\conf… S-1-5-18        

or if you prefer the CIM cmdlets in PowerShell v3

Get-CimInstance -ClassName Win32_UserProfile |
select LocalPath, SID, LastUseTime

C:\Users\Richard            S-1-5-21-2542198769-1191… 01/06/2012 19:56:28      
C:\Windows\ServiceProfil… S-1-5-20                                             
C:\Windows\ServiceProfil… S-1-5-19                                             
C:\Windows\system32\conf… S-1-5-18
   

Notice that with the CIM cmdlet we don’t have to perform any date conversions – worth switching just for that alone.

But the data above doesn’t show the user account.

Unfortunately there isn’t an association between profile and user account so we need to do the filtering ourselves

Get-WmiObject -Class Win32_UserProfile |
select LocalPath, SID,
@{N="LastUseTime"; E={$_.ConvertToDateTime($_.LastUseTime)}},
@{N="User"; E={Get-WmiObject -Class Win32_UserAccount -Filter "SID = ‘$($_.SID)’" | select -ExpandProperty Caption}}

LocalPath            SID                  LastUseTime          User              
———            —                  ———–          —-              
C:\Users\Richard     S-1-5-21-25421987… 01/06/2012 20:01:56  RSLAPTOP01\Richard
C:\Windows\Servic… S-1-5-20                                                    
C:\Windows\Servic… S-1-5-19                                                    
C:\Windows\system… S-1-5-18   

The alternative with the CIM cmdlets

Get-CimInstance -ClassName Win32_UserProfile |
select LocalPath, SID, LastUseTime,
@{N="User"; E={Get-CimInstance -Class Win32_UserAccount -Filter "SID = ‘$($_.SID)’" |
select -ExpandProperty Caption}}

C:\Users\Richard     S-1-5-21-25421987… 01/06/2012 20:01:56  RSLAPTOP01\Richard
C:\Windows\Servic… S-1-5-20                                                    
C:\Windows\Servic… S-1-5-19                                                    
C:\Windows\system… S-1-5-18  

The final part is to filter out any of the well known special accounts such as Local service

Get-WmiObject -Class Win32_UserProfile -Filter "Special = ‘$false’" |
select LocalPath, SID,
@{N="LastUseTime"; E={$_.ConvertToDateTime($_.LastUseTime)}},
@{N="User"; E={Get-WmiObject -Class Win32_UserAccount -Filter "SID = ‘$($_.SID)’" | select -ExpandProperty Caption}}

or

Get-CimInstance -ClassName Win32_UserProfile -Filter "Special = ‘$false’" |
select LocalPath, SID, LastUseTime,
@{N="User"; E={Get-CimInstance -Class Win32_UserAccount -Filter "SID = ‘$($_.SID)’" | select -ExpandProperty Caption}}

either of these will just return the top line in the output above.

Now we can identify our profiles & relate them to user accounts – how do we delete them


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: