Archive

Archive for the ‘PowerShell’ Category

Powershell: Get scheduled tasks list from Windows 7/2008 computers

The below script helps you to query scheduled tasks from remote computer which is running with Windows 7/Windows 2008  or above. You can use this script to query multiple computers to get all the scheduled tasks. You can also query the computer by using a scheduled task name as well.

<#

    .Synopsis
        Get the list of scheduled Tasks from Windows 7 or Windows 2008 computers
        
    .Description
        This script displays all the scheduled tasks available in a windows 7 or windows 2008 computer.
 
    .Parameter ComputerName    
        Computer Name(s) from which you want to get the scheduled tasks information. If this
        parameter is not used, the the script gets the scheduled tasks list from local computer.
        
    .Parameter TaskName    
        Name of the scheduled task that you want to query. This is a optional parameter.
        
    .Example 1
        Get-ScheduledTask.ps1 -ComputerName Comp1, Comp2
        Get the scheduled tasks information from listed computers.
    .Example 2
        Get-ScheduledTask.ps1 -ComputerName Comp1 -TaskName "Calibration Loader"
        
        Get the details of given task from Comp1.
        
    .Notes
        NAME:      Get-ScheduledTask.ps1
        AUTHOR:    Sitaram Pamarthi
        WEBSITE:   http://techibee.com

#>
[cmdletbinding()]
param (
 [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
 [string[]] $ComputerName = $env:computername,
 [string] $TaskName
)
#function to get all scheduled task folder details.
function Get-TaskSubFolders {
[cmdletbinding()]
param (
 $FolderRef
)
$ArrFolders = @()
$folders = $folderRef.getfolders(1)
if($folders) {
 foreach ($folder in $folders) {
  $ArrFolders = $ArrFolders + $folder
  if($folder.getfolders(1)) {
   Get-TaskSubFolders -FolderRef $folder
  }
 }
}
return $ArrFolders
}            

#MAIN            

foreach ($Computer in $ComputerName) {
 $SchService = New-Object -ComObject Schedule.Service
 $SchService.Connect()
 $Rootfolder = $SchService.GetFolder("\")
 $folders = Get-Tasksubfolders -FolderRef $RootFolder
 foreach($Folder in $folders) {
  $Tasks = $folder.gettasks(1)
  foreach($Task in $Tasks) {
   $OutputObj = New-Object -TypeName PSobject
   $OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer
   $OutputObj | Add-Member -MemberType NoteProperty -Name TaskName -Value $Task.Name
   $OutputObj | Add-Member -MemberType NoteProperty -Name TaskFolder -Value $Folder.path
   $OutputObj | Add-Member -MemberType NoteProperty -Name IsEnabled -Value $task.enabled
   $OutputObj | Add-Member -MemberType NoteProperty -Name LastRunTime -Value $task.LastRunTime
   $OutputObj | Add-Member -MemberType NoteProperty -Name NextRunTime -Value $task.NextRunTime
   if($TaskName) {
    if($Task.Name -eq $TaskName) {
     $OutputObj
    }
   } else {
     $OutputObj
   }
  }            

 }            

}

Output:

Feel Free to post here if you have any trouble in using this script. Happy to help!!!

 

Powershell: Split a string by white space(s)

While writing a script today, I faced a situation where I have a string like “This is my       test                string”. As you have already noticed there are more than one spaces at different places in the string. All I need to do is eliminate all spaces and fit the words alone into a array.

Since this is a split by white space operation, I tried below and got bit surprised with the output.

$string = "This is my test string"
$string.split(" ") 

Output:

The output is array which is containing the words plus some spaces in middle. This is not what I expected. After some struggle, I made it to work by using -Split.

Now the working code is…

$string = "This is my test string"
$array = $string -split "\s+"
$array

 

Output:

 

Hope this little tip helps. Visit to http://www.powershelladmin.com/wiki/Powershell_split_operator for more examples about using -Split.

[Update]:

The usage for -split is very simple and I believe this is a best suit for simple requirements like the one I showed you above. But if you have something more complex, then you may want to explore the usage of [regedit]::Split() dotnet method.

Why am I getting powershell output in @{parametername=parametervalue}.parametername

One of my friend is trying to get computers list from active directory using below code. All he want is names of the computers in a array.

$TestPcNames = Get-QAComptuer -Id TEST* | select Name
$TestPCNames | % { write-host "$_.Name" }

There is nothing really wrong with the above code. All it contains is computer names but in object format. For that reason when he is trying to print the computer name, he is getting something like @{Name=TESTPC1}.Name

There he is stuck and now don’t know how to get list of computer accounts(in string format) in a array. This is very basic problem that every system administrator will face when trying to get their hands wet with powershell. I have also gone through this a couple of years back when I am studying ABCs of powershell.

The solution for this is very easy. First get the things printed correctly. You can use either of below one liners for that.

$TestPCNames | % { write-host "$($_.Name)" }         

$TestPCNames | % { $_.Name }

Once you seen them printed as string array(you will noted there won’t be any column header with work “Name”), all you need to do is assign the output to a variable.

$CompArray = $TestPCNames | % { write-host "$($_.Name)" }
$CompArray = $TestPCNames | % { $_.Name }

Now $CompArray contains the list of computers. Hope this little tip helps…

 

Categories: PowerShell Tags: ,

Interesting Video on PowerShell V3

Here is an interesting video about PowerShell V3 which I came across through linked in

Thought of sharing with Scripting guys…

http://channel9.msdn.com/posts/PowerShell-V3-Guru-Don-Jones?goback=%2Egde_140856_member_112620896

 

Categories: PowerShell Tags:

Powershell: Script to take a screenshot of your desktop

“Could you please send me a screenshot of what you are seeing?”. This is a frequent question we system administrators ask the end users. So, I just got a thought why I can’t take a screenshot of desktop using powershell so that I can incorporate this to my other automations if needed. That is when this script born.

When searched in google for this, I found a stackoverflow thread(http://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell) where different approaches are described to take a screenshot using powershell. I could make only one method working and the other is having problems. However, the working method has a limitation as I need to explicitly pass the width and height of the screen that has to be captured. If I am interested on whole screen, from where I can get these coordinates? My previous post(Get-ScreenResolution) came handy here. I read the screen resolution details using Get-Screenresolution.ps1 script and passed the output to the function I found in stackoverflow. Now it is working exactly the way I want.

For general usage, I made few more modifications to the code to allow explicitly pass the width and height details using -Width and -Height parameters. There is also another parameter called -FileName using which you can provide the name you want for the screenshot. Don’t provide a file extension here. The script saves the output in PNG format by default. If -FileName parameter is not specified you can see the output in %temp% with Screenshot.png name.

Get-ScreenShot.ps1

[cmdletbinding()]
param(
  [string]$Width,
  [string]$Height,
  [String]$FileName = "Screenshot"            

)            

#Function to take screenshot. This function takes the width and height of the screen that has
#to be captured            

function Take-Screenshot{
[cmdletbinding()]
param(
 [Drawing.Rectangle]$bounds,
 [string]$path
)
   $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
   $graphics = [Drawing.Graphics]::FromImage($bmp)
   $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
   $bmp.Save($path)
   $graphics.Dispose()
   $bmp.Dispose()
}            

#Function to get the primary monitor resolution.
#This code is sourced from 
# http://techibee.com/powershell/powershell-script-to-get-desktop-screen-resolution/1615            

function Get-ScreenResolution {
 $Screens = [system.windows.forms.screen]::AllScreens
 foreach ($Screen in $Screens) {
  $DeviceName = $Screen.DeviceName
  $Width  = $Screen.Bounds.Width
  $Height  = $Screen.Bounds.Height
  $IsPrimary = $Screen.Primary
  $OutputObj = New-Object -TypeName PSobject
  $OutputObj | Add-Member -MemberType NoteProperty -Name DeviceName -Value $DeviceName
  $OutputObj | Add-Member -MemberType NoteProperty -Name Width -Value $Width
  $OutputObj | Add-Member -MemberType NoteProperty -Name Height -Value $Height
  $OutputObj | Add-Member -MemberType NoteProperty -Name IsPrimaryMonitor -Value $IsPrimary
  $OutputObj
 }
}            

#Main script begins            

#By default captured screenshot will be saved in %temp% folder
#You can override it here if you want
$Filepath = join-path $env:temp $FileName            

[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [Reflection.Assembly]::LoadWithPartialName("System.Drawing")            

if(!($width -and $height)) {            

 $screen = Get-ScreenResolution | ? {$_.IsPrimaryMonitor -eq $true}
 $Width = $screen.Width
 $Height = $screen.height
}            

$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, $Screen.Width, $Screen.Height)            

Take-Screenshot -Bounds $bounds -Path "$Filepath.png"
#Now you have the screenshot

Usage:

Simple, just run the script from powershell window, you will see the output in %temp%\screenshot.png

Hope this helps… feedback welcome.

 

 

Powershell: Write-EventLog Error “Write-EventLog : The source name XXX does not exist on computer

If you are using Write-EventLog to write any new events to event log, it is possible that you might see below error.

Write-EventLog : The source name “XXX” does not exist on computer “localhost”.

I am into similar situation today. What I was doing is trying to write a new event in to Application event log with a Event Source that is not already exists in the computer where I am trying. So the error message makes sense. It is saying the source I am trying to use, XXX doesn’t exists. So, how should get this added to list of available event sources in the computer so that it won’t through the error message again.

After little bit of googling, I found the below method promising.

New-EventLog -LogName Application -Source “XXX”

This command creates a new event source in Application Event log with the name XXX. All I need to do is just use this command once and try the write-EventLog cmdlet with the same source name(XXX). It worked this time.

Hope this little trick helps you…

[Update]

There are some dotnet ways available as well to see if a given source is available in EventLog and create one if needed.

To check if the source exists:

PS C:\> [system.diagnostics.eventlog]::SourceExists(“XXX”)
False
PS C:\>

To create a new source entry in event log:

[system.diagnostics.EventLog]::CreateEventSource(“XXX”, “Application”)

 

Powershell: Script to Get Desktop Screen Resolution

April 24, 2012 1 comment

The Powershell code described in this article will help you to get screen resolution details of your desktops It uses System.Drawing and System.Windows.Forms namespaces. The Screen class in System.Windows.Forms provides the data we need — that is screen resolution details. This code will also tell you which one is your primary monitor and it’s resolution details.

Code:

function Get-ScreenResolution {
[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Screens = [system.windows.forms.screen]::AllScreens            

foreach ($Screen in $Screens) {
 $DeviceName = $Screen.DeviceName
 $Width  = $Screen.Bounds.Width
 $Height  = $Screen.Bounds.Height
 $IsPrimary = $Screen.Primary            

 $OutputObj = New-Object -TypeName PSobject
 $OutputObj | Add-Member -MemberType NoteProperty -Name DeviceName -Value $DeviceName
 $OutputObj | Add-Member -MemberType NoteProperty -Name Width -Value $Width
 $OutputObj | Add-Member -MemberType NoteProperty -Name Height -Value $Height
 $OutputObj | Add-Member -MemberType NoteProperty -Name IsPrimaryMonitor -Value $IsPrimary
 $OutputObj            

}
}

 

Output:

Hope this helps…

 

Powershell: Script to enable/disable network connections in Windows

In one of my previous posts I talked about how to disable/enable LAN connections on a Windows 2008 Core server using command line. In this post, I am going to present you a much enhanced version of it using powershell. This powershell script helps you to disable or enable any network connection in either local computer or remote computer easily. You can use this script to perform this operation on multiple computers — will give usage example at the end of this post.

In this script I am using Win32_NetworkAdapter WMI class which has methods for enabling or disabling a given network connection. By default, the script looks for network connections with the name Local Area Connection to perform disable or enable operations. If you want to perform these actions against different network connections(like HP Team#1) you can specify that using -ConnectionName parameter. The -Disable or -Enable parameters are for specifying the kind of operation you want to perform. The script will fail if you don’t find either of them. Similarly, you can use -ComputerName parameter if you want to perform this operation against remote computer. You can also provide the list of computers to this argument. I want you be more conscious while using this script against remote computer. The reason behind it is, if you are attempting to disable the primary network connection in remote computer, the script may not return the success/failure status. The reason is simple, it lost the connection to remote computer because you just disabled it. You may find this script handy when you want to disable non-primary connections on remote computers. Since the primary connection is ON in this case, this can return you the status. I didn’t perform any testing against remote computers explicitly so please do testing in your test lab before trying in production.

 

Code : Set-NetworkConnection.ps1

[cmdletbinding()]
param (
 [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
    [string[]]$ComputerName = $env:computername,            

 [switch]$Enable,
 [switch]$Disable,
 [String]$ConnectionName = "Local Area Connection"
)            

begin {            

if(-not($enable -or $disable)) {
 write-Error " You should select either of -Enable or -Disable switches. Exiting"
 exit
}            

}
process {
 foreach ($Computer in $ComputerName) {
  $Computer = $Computer.ToUpper()
  if(Test-Connection -ComputerName $Computer -Count 1 -ea 0) {
   $Networks = Get-WmiObject Win32_NetworkAdapter -ComputerName $Computer | ? {$_.NetConnectionID -match $ConnectionName}
   foreach ($Network in $Networks) {
    if($Enable) {
     $retval  = $Network.Enable()
     if($retval.ReturnValue -eq 0) {
      Write-host "Successfully enabled `"$($network.NetConnectionID)`" on $Computer"
     } else {
      write-host "Failed to enable `"$($network.NetConnectionID)`" on $Computer"
     }
    } elseif($Disable) {
     $retval  = $Network.Disable()
     if($retval.returnValue -eq 0) {
      Write-host "Successfully disabled `"$($network.NetConnectionID)`" on $Computer"
     } else {
      write-host "Failed to disable `"$($network.NetConnectionID)`" on $Computer"
     }            

    }
   }
  }
 }
}            

end {}

Usage Examples:

.\Set-NetworkConnection -Enable #to enable local network connection

.\Set-NetworkConnection -Disable #to disable local network connection

.\Set-NetworkConnection -Disable -ConnectionName “My network2″ #to disable the local network connection that has the name “My Network2″

.\Set-NetworkConnection -ComputerName MyPC2 -Disable -ConnectionName “My network2″ #to disable the network connection that has the name “My Network2″ on MyPC2

Get-Content C:\mypcs.txt | Set-NetworkConnection -Disable -ConnectionName “My Network2″ #To disable the network connection name “My network2″ on list of PCs in C:\mypcs.txt file

Hope this helps… Happy learning…

Microsoft Script Explorer for Windows PowerShell (pre-release)

April 11, 2012 1 comment

Would it not be helpful if all scripts are at one place and you can navigate/browse them through single window?
Microsoft team is working on a tool called Script Explorer for Windows Powershell.

Go through below link for more details.

http://blogs.technet.com/b/exchange/archive/2012/03/14/check-out-microsoft-script-explorer-for-windows-powershell-pre-release.aspx

Powershell: Script to delete Windows User Profiles on Windows 7/Windows 2008 R2

March 24, 2012 6 comments

As promised in my previous post,I am back with a Powershell script which helps you in deleting a user’s windows profile either on local computer or on multiple remote computers. This script users Win32_UserProfile class which is available in Windows Vista, Windows 7, and Windows 2008(R2). So it will not work for Windows XP and 2003 hosts.

In this script I am making use of a method called Delete() which is available for each profile queried through Win32_UserProfile WMI class. Using this script you can delete one profile at a time on a single computer or list of remote computers. This script will also display the result of operation you are performing. That means it will tell whether it succeed in deleting the profile or failed. And it will also tell you if the script is unable to find the profile you are trying to delete.

Code: Remove-UserProfile.ps1

[cmdletbinding()]
param(
 [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
 [string[]]$ComputerName = $env:computername,
 [parameter(mandatory=$true)]
 [string]$UserName            

)            

foreach($Computer in $ComputerName) {
 Write-Verbose "Working on $Computer"
 if(Test-Connection -ComputerName $Computer -Count 1 -ea 0) {
  $Profiles = Get-WmiObject -Class Win32_UserProfile -Computer $Computer -ea 0
  foreach ($profile in $profiles) {
   $objSID = New-Object System.Security.Principal.SecurityIdentifier($profile.sid)
   $objuser = $objsid.Translate([System.Security.Principal.NTAccount])
   $profilename = $objuser.value.split("\")[1]
   if($profilename -eq $UserName) {
    $profilefound = $true
    try {
     $profile.delete()
     Write-Host "$UserName profile deleted successfully on $Computer"
    } catch {
     Write-Host "Failed to delete the profile, $UserName on $Computer"
    }
   }
  }            

  if(!$profilefound) {
   write-Warning "No profiles found on $Computer with Name $UserName"
  }
 } else {
  write-verbose "$Computer Not reachable"
 }
}

Output:

You can use this script to delete profile from list of remote computers either by providing the list via command line or using a text file. See below two cases to get more insight about how to use the script in such cases.

.\Remove-UserProfile.ps1 -ComputerName PC1, PC2, PC3 -UserName LocalUser2

Get-Content c:\temp\Computers.txt | .\Remove-UserProfile.ps1 -UserName LocalUser2

Hope this helps… Feel free to write in comments section if you have any doubts or looking for some enhancements to the script. Happy to help.