Showing posts with label Function. Show all posts
Showing posts with label Function. Show all posts

2014/10/05

PowerShell - Who Reports to Whom? (Active Directory recursive DirectReports)

I've been working in the video games industry for a bit more than 3 months now. A lot is going on, and the pace seems faster than regular corporation environment. I also notice a lot of employees movements between teams and projects.

Last week I had an interesting "Quest": To find the list of employees under a specific manager. In Active Directory you can retrieve this information under the property DirectReports.

However if this manager manage other managers... how can I do a recursive search... ?
Sounds like a mission for PowerShell :-)

2013/10/29

PowerShell - Using ADSI with alternate Credentials

The following PowerShell code will show you how to run ADSI with alternate credentials to get information from the Active Directory.

I will query Group objects in this example, my filter is define by the following line: "(objectCategory=Group)"



2013/10/16

PowerShell - Get-DomainUser

Today one of my IT coworkers, in another department, sent a couple of emails to the Ops to get the username (SamAccount) from a couple of Active Directory users accounts. This guy, which is not familiar with AD, had only the DisplayName properties information.

I wrote him back that he could just request RSAT(Remote Server Administration Tools) to be installed on his workstation or just use this small PowerShell that I just wrote in minutes. Since Active Directory does not require any specific permission to access this kind of information. Here is the code, nothing advanced, but it does the work ;-)

function Get-DomainUser {
    PARAM($DisplayName)
    $Search = [adsisearcher]"(&(objectCategory=person)(objectClass=User)(displayname=$DisplayName))"
    foreach ($user in $($Search.FindAll())){
        New-Object -TypeName PSObject -Property @{
            "DisplayName" = $user.properties.displayname
            "UserName"    = $user.properties.samaccountname
            "Description" = $user.properties.description}
    }
}

Result


PS C:\> Get-DomainUser -DisplayName "jonathan*" | Format-List
UserName    : {JonathanD}
Description : {Account of Jonathan Delpiero}
DisplayName : {Jonathan Delpiero}

UserName    : {DumoulinJ}
Description : {Account of Jonathan Dumoulin}
DisplayName : {Jonathan Dumoulin}


2013/07/02

Enabling Change Block Tracking (CBT) on a vSphere 5.1 VM with PowerShell/PowerCli

In one of my previous post, I created two PowerShell functions to enable Copy/Paste operations on VMware vSphere 5.1 between a Guest OS and the vSphere Client remote console.
Today we'll use a very similar piece of code to Enable Change Block Tracking (CBT) on one or more Virtual Machines.

I already talked about CBT in the past, but I just wanted to create re-usable PowerShell functions that will help me when I need it.

2013/07/01

How to Enable Copy/Paste Operations Between GuestOS and Remote Console on vSphere 5.1 (GUI and PowerCli)

In this blogpost I will explain how to enable Copy/Paste operations between the Guest Operating System and the Remote Console on VMware vSphere 5.1 via the GUI and PowerCli (PowerShell for VMware).

VMware does not recommend this manipulation to avoid and limit Exposure of Sensitive Data Copied to the Clipboard section.

Using the GUI this procedure requires the VM(s) to be powered off. Who wants to do that? Not me...

Check the second part of this procedure using PowerCli, this can be applied without powering off the VM. However you'll need to do a stun/unstun operation (i.e. power on/off, suspend/resume, create/delete snapshot/storage VMotion) to achieve the same thing.


Using the Graphical User Interface (GUI)

Applying advanced settings to a VM can be a daunting task.
Doing this manipulation via the GUI is pretty heavy. When dealing with even a few VMs, this can be a very time consuming task time consuming...

The "Configuration Parameters" button is not available while the VM is Powered On.

1 - Power down your VM(s)

2 - Go into Edit Setting, under the Option tab, and select General under Advanced.
You'll see the Configuration Parameters button...



3 - Click on Add Row and enter the Name and Value for each of the following items:
  • isolation.tool.copy.disable = FALSE
  • isolation.tool.paste.disable = FALSE

2013/06/13

Scripting Games 2013 - Advanced Event 5 - The Logfile Labyrinth

This is my solution for the Advanced Event 5.
I did not have much time to work on this event, but here is the script I submitted.

Instruction
Download [Skydrive]

Dr. Scripto finds himself in possession of a bunch of IIS log files, much like the one at
http://morelunches.com/files/powershell3/LogFiles.zip, if you need one to practice with. He’s keeping all of the log files in a folder, and he’s left the log files with their default filenames, which he’s given a .LOG filename extension. All of the files are for a single Web site, on a single Web server.

He’d like you to write a tool that accepts a path, and then simply scans through each file in that path somehow, generating a list of each unique client IP address that have been used to access the Web site. No IP address should appear more than once in your output, and you don’t need to sort the output in any way.

Your tool should optionally accept an IP address mask like “192.0.1.*” and only display IP addresses that match the specified pattern. If run without a pattern, display all IP addresses.

Regardless of the addresses found in the sample file linked above, you should assume that any legal IP address may appear in the files Dr. Scripto needs to scan. Your command should scan all of the files in the folder (and the folder doesn’t contain any other kind of file) and produce a single set of results. If an IP address appears in multiple log files and it’s likely that will be the case then your final output should still only list that IP address.

2013/06/10

Scripting Games 2013 - Advanced Event 4 - An Auditing Adventure

This is my solution for the Advanced Event 4 of the Scripting Games 2013.
This event was a bit challenging for me... In the past, I played with Quest Active Directory snap-in to create a bunch of Monitoring tools and some other small automation tasks, but that's about it. (Example Monitor Active Directory Groups membership change).

Let's see how I solved it.



2013/04/30

Scripting Games 2013 - Advanced Event 1 - An Archival Atrocity

Last week I was one of the lucky PowerShell Summit attendees and had the chance to assist to the official launch of the Scripting Games 2013 !! (with a special video created by Sean ;-)

Apart from the PowerShell stars like Ed Wilson, Don Jones, Bruce Payette, Alan Renouf, Lee Holmes, Richard Siddaway, Jeffery Snover.... I met some awesome people there and It was really cool to talk about our passion for PowerShell, How this amazing tool is saving our life each days!

Scripting Games 2013 - Advanced Event #1 - An Archival Atrocity

For the first time, I decided this year to participate to the Scripting Games 2013 organize and hosted by the PowerShell.org team.

I chose the Advanced Track and here is the first script I submitted yesterday.

Feel free to comment and send me your critics.

2013/02/18

Winter Scripting Games 2013 - Practice Event 2


Just a quick post on the script I submit for the second practice event of the Winter Scripting Games 2013 (last week).


Practice Event 2 - Covering Your Assets
Your organization is preparing to renew maintenance contracts on all of your server computers. You need to provide management with a report that details each inventory information for each server. Most of the servers do not have Windows PowerShell installed. None of the servers a separated from your client computer by a firewall. Computer names may be specified by a variety of means; your function must accept any collection of strings as computer names.

Minimum Requirements 
Optional Criteria 
  • Display optional verbose output showing the computer name being contacted
  • Prompt for computer names if none are specified when the function is run
  • Accept computer names as strings from the pipeline
Desired Output 
  • ComputerName Model Manufacturer LogicalProcs PhysicalRAM BIOSSerial

My Script

# NAME  : Get-ComputerInventory
# AUTHOR: Francois-Xavier Cat
# EMAIL : fxcat@LazyWinAdmin.com
# DATE  : 2013/02/10 

Function Get-ComputerInventory {
        <#
        .SYNOPSIS 
        The Get-ComputerInventory function gets information about a local or 
        Remote machine(s) specified by the parameter ComputerName.
    

2013/02/10

Winter Scripting Games 2013 - Practice Event 1

The Winter Scripting Games 2013 started last week with the first practice event.

Unfortunately for me, I was not able to post my script on time. The first Practice event was due on the Tuesday, 5th of February... 11:59 PM GMT! I assume I had until midnight my time..... (My timezone is East GMT-5) 
;-(

If you want to join the Winter Scripting Games, check the following TheScriptingGames website for more information and the The Competitor Guide.

Summary: Practice Event 1 - Sizing up the Disks
You have been asked to create a Windows PowerShell advanced function named Get-DiskSizeInfo. It must accept one or more computer names, and use WMI or CIM to query each computer. For each computer, it must display the percentage of free space, drive letter, total size in gigabytes, and free space in gigabytes. If a specified computer cannot be contacted, the function must log the computer name to C:\Errors.txt and display no error message.
Minimum Requirements 
Optional Criteria
  • Display optional verbose output showing the computer name being contacted

My Script

Function Get-DiskSizeInfo {
        <#
        .DESCRIPTION
        Check the Disk(s) Size and remaining freespace.

        .PARAMETER ComputerName
        Specify the computername(s)

        .INPUTS
        System.String

        .OUTPUTS
        System.Management.Automation.PSObject

2012/12/31

Get-LocalGroupMembership (Using ADSI/WinNT)

Updated (2013/06/03): I added some error handeling/verbose/testing. You are now able to pass multiple computers to the ComputerName parameter.

Intro

Recently I had to do an Audit at my work to find who was Local Administrators on a bunch of Servers.
That might sounds easy when you just have to check 2 or 3 servers... but what if you have to get the information for hundreds! Plus ... I know the Auditor would ask me this same question every few months to prove that the list did not change...Arghhh!

Once again PowerShell saved me so much time on that one!!

Get-LocalGroupMembership

Get the specified local group membership on a local or remote computer.
By default, if you don't specify any parameter, It will query the local group "Administrators" on the localhost.

For some reason WMI bug with some of my Windows Server 2003 and does not return some Domain Groups where Windows Server 2008/2012 work just fine.

Here is my ADSI/WinNT version, It fixed my problem.
In the next post I will go a bit further and get the membership from the domain groups ;-)

Running the Function


The Code

Function Get-LocalGroupMembership {
<#
.Synopsis
    Get the local group membership.
            
.Description
    Get the local group membership.
            
.Parameter ComputerName
    Name of the Computer to get group members. Default is "localhost".
            
.Parameter GroupName
    Name of the GroupName to get members from. Default is "Administrators".
            
.Example
    Get-LocalGroupMembership
    Description
    -----------
    Get the Administrators group membership for the localhost
            
.Example
    Get-LocalGroupMembership -ComputerName SERVER01 -GroupName "Remote Desktop Users"
    Description
    -----------
    Get the membership for the the group "Remote Desktop Users" on the computer SERVER01

.Example
    Get-LocalGroupMembership -ComputerName SERVER01,SERVER02 -GroupName "Administrators"
    Description
    -----------
    Get the membership for the the group "Administrators" on the computers SERVER01 and SERVER02

.OUTPUTS
    PSCustomObject
            
.INPUTS
    Array
            
.Link
    N/A
        
.Notes
    NAME:      Get-LocalGroupMembership
    AUTHOR:    Francois-Xavier Cat
    WEBSITE:   www.LazyWinAdmin.com
#>

 
 [Cmdletbinding()]

 PARAM (
        [alias('DnsHostName','__SERVER','Computer','IPAddress')]
  [Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
  [string[]]$ComputerName = $env:COMPUTERNAME,
  
  [string]$GroupName = "Administrators"

  )
    BEGIN{
    }#BEGIN BLOCK

    PROCESS{
        foreach ($Computer in $ComputerName){
            TRY{
                $Everything_is_OK = $true

                # Testing the connection
                Write-Verbose -Message "$Computer - Testing connection..."
                Test-Connection -ComputerName $Computer -Count 1 -ErrorAction Stop |Out-Null
                     
                # Get the members for the group and computer specified
                Write-Verbose -Message "$Computer - Querying..."
             $Group = [ADSI]"WinNT://$Computer/$GroupName,group"
             $Members = @($group.psbase.Invoke("Members"))
            }#TRY
            CATCH{
                $Everything_is_OK = $false
                Write-Warning -Message "Something went wrong on $Computer"
                Write-Verbose -Message "Error on $Computer"
                }#Catch
        
            IF($Everything_is_OK){
             # Format the Output
                Write-Verbose -Message "$Computer - Formatting Data"
             $members | ForEach-Object {
              $name = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
              $class = $_.GetType().InvokeMember("Class", 'GetProperty', $null, $_, $null)
              $path = $_.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $_, $null)
  
              # Find out if this is a local or domain object
              if ($path -like "*/$Computer/*"){
               $Type = "Local"
               }
              else {$Type = "Domain"
              }

              $Details = "" | Select-Object ComputerName,Account,Class,Group,Path,Type
              $Details.ComputerName = $Computer
              $Details.Account = $name
              $Details.Class = $class
                    $Details.Group = $GroupName
              $details.Path = $path
              $details.Type = $type
  
              # Show the Output
                    $Details
             }
            }#IF(Everything_is_OK)
        }#Foreach
    }#PROCESS BLOCK

    END{Write-Verbose -Message "Script Done"}#END BLOCK
}#Function Get-LocalGroupMembership


Thanks for Reading! If you have any questions, leave a comment or send me an email at fxcat@lazywinadmin.com. I invite you to follow me on Twitter: @lazywinadm

2012/04/02

Leveraging Proxy Functions in PowerShell

@DSotnikov just released the video recording of the session from the PowerShell Deep Dive in Frankfurt (last year). In this video, MVP Kirk Munro (poshoholic) and I demoed a project we've been working on that let's you create proxy functions. Here's a reminder of the session abstract.

In this session as they take a deep dive into proxy functions in PowerShell. Shay and Kirk have been working together on PowerShell Proxy Extensions, a powerful module that leverages proxy functions and makes it easier than ever to create these powerful extensions to PowerShell. They will demonstrate what proxy functions are and why they are important, and then show how a little scripting savvy (and a really long script) can make your life easier by allowing you to create everything from very simple proxy functions that extend PowerShell to more complex proxy functions that override existing commands, fixing bugs and adding missing features at the same time, all while leveraging inline help as much as possible.

The module we demoed is available at http://pspx.codeplex.com/. Unfortunately I won't be able to make it this year to the Deep Dive in San Diego, but if you're attending you'll get the chance to see the module in action, plus a very cool project, written on top of the PowerShell Proxy Extensions (PSPX) module.

2011/04/25

Use PowerShell to Identify Non-Standard Windows Service Accounts

Source:Expert Solution for the 2011 Scripting Games Beginner Event 4

<#

.SYNOPSIS
   Identifies services with nonstandard accounts
.DESCRIPTION
   Retrieves services that use accounts other than LocalSystem, LocalService or NetworkService
.PARAMETER computername
   one or more computernames or IP addresses
   you will need local administrator privileges, and the firewall needs to allow access
   to enable firewall access, run this command on target machines:
   netsh firewall set service type = remoteadmin mode = enable
.EXAMPLE
   Get-NonstandardService
   lists services with nonstandard accounts on local machine
.EXAMPLE
   Get-NonstandardService -computername 10.10.10.33
   lists services with nonstandard accounts on remote machine with IP 10.10.10.33
.EXAMPLE
   Get-NonstandardService -computername 10.10.10.33, 127.0.0.1, serv12-1, client3
   lists services with nonstandard accounts on four machines (including local system)
.LINK
   http://www.powershell.com
#>

 

function Get-NonstandardService {
  param(
  [String[]]
  $computername = '127.0.0.1'
  )
  # server-side WMI query to minimize network traffic and maximize performance
  $wql = 'Select Name, DisplayName, StartName, __Server From Win32_Service WHERE ((StartName != "LocalSystem") and (StartName != "NT Authority\\LocalService") and (StartName != "NT Authority\\NetworkService"))'

  # examine all computers submitted:
  $computername |
  ForEach-Object {
    Write-Progress 'examining computer:' $_

    # create new object to return information
    $rv = New-Object PSObject | Select-Object Computer, Result, Name, DisplayName
    $rv.computer = $_

    # search for nonstandard services
    try {
      # always return result as array
      $result = @(Get-WmiObject -Query $wql -ComputerName $rv.computer -ErrorAction Stop | Sort-Object DisplayName)

      # no results?
      if ($result.Count -eq 0) {
        # then all services use standard accounts, good:
        $rv.Result = 'OK'
        $rv
      } else {
        # return a result set for each nonstandard service
        $result | ForEach-Object {
          $rv.Computer = $_.__Server
          $rv.Name = $_.Name
          $rv.DisplayName = $_.DisplayName
          $rv.Result = $_.StartName
          $rv
        }
      }
    }
    catch {
      # WMI was unable to retrieve the information
      switch ($_) {
        # sort out most common errors and return qualified information
        {          $_.Exception.ErrorCode -eq 0x800706ba} { $rv.Result = 'WARN: Unavailable (offline, firewall)' }
        {          $_.CategoryInfo.Reason -eq 'UnauthorizedAccessException' } { $rv.Result = 'WARN: Access denied' }
        # return all other non-common errors
        default { $rv.Result = 'WARN: ' + $_.Exception.Message }
      }
      # return error information
      $rv
    }
  }
}