Showing posts with label Scripting. Show all posts
Showing posts with label Scripting. Show all posts

2013/04/02

2013 Scripting Games - Competitor Guide


Don Jones just released the Competitor Guide for the 2013 Scripting Games online.

This year the Games will be hosted by PowerShell.org (Previous ones where organize by the Scripting Guy Ed Wilson). This event is scheduled to start during the PowerShell Summit in Seattle (between the 22nd and the 24th of April).

Make sure to read the Guidelines and check the different tracks available to you (Beginner or Advanced).

Download the Competitor Guide [PDF]

The Scripting Games is a great event for those who want to learn more or improve their skills with Windows PowerShell. I'm planning myself to participate to the Advanced Event. My Script will be post and explained here.


PowerShell/WinForm - Active Directory User Unlocker


An Active Directory account may be automatically locked, if the domain's security policy has been configured to lock accounts after a number of unsuccessful logon attempts.

If an account has been locked out, the lockouttime attribute will contain a Win32 time value that indicates when the account was locked.

An easy way to search for locked out accounts is an LDAP query similar to
(&(objectClass=user)(lockoutTime=>0))




You can integrate this query in the saved queries of your Active Directory Users and Computers MMC.



Description


The following script will use PowerShell to generate a WinForm and give you the ability to unlock account right from the interface. The goal is to do something simple and functional, nothing fancy.

The GUI was created using PowerShell Studio from SAPIEN. You can try this tool by going on Sapien.com

No Module Required


The beautiful part of it is that no Active Directory Module or Quest Active Directory Snapin are required
In my case I used ADSI: [ADSISearcher]

If you want to know more about ADSISearcher check this article from the Scripting Guy

Graphical User Interface



Under Windows 8

2011/08/15

Scaling and Queuing PowerShell Background Jobs


Great article from Travis Jones [Source]

 A couple of months ago I had asked the PowerShell MVPs for suggestions on blog topics. Karl Prosser, one of our awesome MVPs, brought up the topic of scaling and queuing background jobs.
The scenario is familiar: You have a file containing a bunch of input that you want to process and you don’t want to overburden your computer by starting up hundreds of instances of PowerShell at once to process them.
After playing around for about an hour on Friday afternoon, here is what I came up with… This example assumes you have a text file containing the names of many event logs and you want to get the content of each log.

# How many jobs we should run simultaneously
$maxConcurrentJobs = 3;

# Read the input and queue it up
$jobInput = get-content .\input.txt
$queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) )
foreach($item in $jobInput)
{
    $queue.Enqueue($item)
}


# Function that pops input off the queue and starts a job with it
function RunJobFromQueue
{
    if( $queue.Count -gt 0)
    {
        $j = Start-Job -ScriptBlock {param($x); Get-WinEvent -LogName $x} -ArgumentList $queue.Dequeue()
        Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { RunJobFromQueue; Unregister-Event $eventsubscriber.SourceIdentifier; Remove-Job $eventsubscriber.SourceIdentifier } | Out-Null
    }
}


# Start up to the max number of concurrent jobs
# Each job will take care of running the rest
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ )
{
    RunJobFromQueue
}

The English version of this script is:
  • Given a file input.txt containing the name of many event logs, queue up each line of input
  • Kick off a small number of jobs to process one line of input each. Each job just gets the content of a particular log.
  • When a job finishes (determined by the StateChanged Event), start a new job with the next piece of input from the queue
  • Clean up the jobs corresponding to the event subscription so at the end we only have jobs containing event data
The “Synchronized” code you see when defining the queue is just for good measure to make sure that only one job can access it at a time.
Have something you want to see on the PowerShell blog? Leave a comment… Can’t promise we’ll get to everything but it’s nice to see what everyone is interested in.

Travis Jones
Windows PowerShell PM
Microsoft Corporation

2011/06/30

Powershell - Recommended coding style

source
Here are some Recommended coding style for powershell by Richard Berg

<#
.SYNOPSIS
Cmdlet help is awesome.  Autogenerate via template so I never forget.

.DESCRIPTION
.PARAMETER
.PARAMETER
.INPUTS
.OUTPUTS
.EXAMPLE
.EXAMPLE
.LINK
#>
function Get-Widget
{
    [CmdletBinding()]
    param (
        # Think about which params users might loop over.  If there is a clear
        # favorite (80/20 rule), make it ValueFromPipeline and name it InputObject.
        [parameter(ValueFromPipeline=$True)]
        [alias("Server")]
        [string]$InputObject,

        # All other loop candidates are marked pipeline-able by property name.  Use Aliases to ensure the most 
        # common objects users want to feed in will "just work".
        [parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$True)]
        [alias("FullName")]
        [alias("Path")]
        [string[]]$Name,

        # Provide & document defaults for optional params whenever possible.
        [parameter(Position=1)]
        [int]$Minimum = 0,

        [parameter(Position=2)]
        [int]$ComputerName = "localhost",

        # Stick to standardized parameter names when possible.  *Especially* with switches.  Use Aliases to support 
        # domain-specific terminology and/or when you want to expose the parameter name of the .Net API you're wrapping.
        [parameter()]
        [Alias("IncludeFlibbles")]
        [switch]$All,
    )

    # The three main function blocks use this format if & only if they are short one-liners    
    begin { $buf = new-list string }

    # Otherwise they use spacing comparable to a C# method
    process    
    {
        # Likewise, control flow statements have a special style for one-liners
        try
        {
            # Side Note: internal variables (which may be inherited from a parent scope)  
            # are lowerCamelCase.  Direct parameters are UpperCamelCase.
            if ($All)
                { $flibbles = $Name | Get-Flibble }   
            elseif ($Minimum -eq 0)          
                { $flibbles = @() }
            else
                { return }                       

            $path = $Name |
                ? { $_.Length -gt $Minimum } |
                % { $InputObject.InvokeGetAPI($_, $flibbles) } |
                ConvertTo-FullPath
        }
        finally { Cleanup }

        # In general, though, control flow statements also stick to the C# style guidelines
        while($true)
        {
            Do-Something
            if ($true)
            {
                try
                {
                    Do-Something
                    Do-Something
                    $buf.Add("abc")
                }
                catch
                {
                    Do-Something
                    Do-Something
                }
            }            
        }    
    }    
}

<# 
Pipelines are a form of control flow, of course, and in my opinion the most important.  Let's go 
into more detail.

I find my code looks more consistent when I use the pipeline to nudge all of Powershell's supported 
language constructs (within reason) toward an "infix" style, regardless of their legacy origin.  At the 
same time, I get really strict about avoiding complexity within each line.  My style encourages a long,
consistent "flow" of command-to-command-to-command, so we can ensure ample whitespace while remaining
quite compact for a .Net language. 

Note - from here on out I use aliases for the most common pipeline-aware cmdlets in my stable of 
tools.  Quick extract from my "meta-script" module definition:
sal ?? Invoke-Coalescing
sal ?: Invoke-Ternary
sal im Invoke-Method
sal gpv Get-PropertyValue
sal spv Set-PropertyValue
sal tp Test-Path2
sal so Select-Object2        
sal eo Expand-Object        

% and ? are your familiar friends.
Anything else that begins with a ? is a pseudo-infix operator autogenerated from the Posh syntax reference.
#>        
function PipelineExamples
{
    # Only the very simplest pipes get to be one-liners:
    $profileInfo = dir $profile | so @{Path="fullname"; KBs={$_.length/1kb}}
    $notNull = $someString | ?? ""        
    $type = $InputObject -is [Type] | ?: $InputObject $InputObject.GetType()        
    $ComObject | spv Enabled $true
    $foo | im PrivateAPI($param1, $param2)
    if ($path | tp -Unc)
        { Do-Something }

    # Any time the LHS is a collection (i.e. we're going to loop), the pipe character ends the line, even 
    # when the expression looks simple.
    $verySlowConcat = ""            
    $buf |
        % { $verySlowConcat += $_ }
    # Always put a comment on pipelines that have uncaptured output [destined for the caller's pipeline]
    $buf |
        ? { $_ -like "*a*" }


    # Multi-line blocks inside a pipeline:
    $orders |
        ? { 
            $_.SaleDate -gt $thisQuarter -and
            ($_ | Get-Customer | Test-Profitable) -and
            $_.TastesGreat -and
            $_.LessFilling
        } |
        so Widgets |        
        % {                
            if ($ReviewCompetition)
            {
                $otherFirms |
                    Get-Factory |
                    Get-ManufactureHistory -Filter $_ |
                    so HistoryEntry.Items.Widgets                     
            }
            else
            {
                $_
            }
        } |            
        Publish-WidgetReport -Format HTML


    # Mix COM, reflection, native commands, etc seamlessly
    $flibble = Get-WmiObject SomethingReallyOpaque |
        spv AuthFlags 0xf -PassThru |
        im Put() -PassThru |
        gpv Flibbles |
        select -first 1

    # The coalescing operator is particularly well suited to this sort of thing
    $initializeMe = $OptionalParam |
        ?? $MandatoryParam.PropertyThatMightBeNullOrEmpty |
        ?? { pwd | Get-Something -Mode Expensive } |
        ?? { throw "Unable to determine your blahblah" }           
    $uncFolderPath = $someInput |
        Convert-Path -ea 0 |
        ?? $fallback { tp -Unc -Folder }

    # String manipulation        
    $myName = "First{0}   Last{1}   " |
        ?+ "Suffix{2}" |
        ?replace "{", ": {" |
        ?f {eo richard berg jr | im ToUpper}            

    # Math algorithms written in this style start to approach the elegance of functional languages
    $weightedAvg = $values |
        Linq-Zip $weights {$args[0] * $args[1]} |
        Linq-Sum |
        ?/ ($weights | Linq-Sum)
}

# Don't be afraid to define helper functions.  Thanks to the script:Name syntax, you don't have to cram them into 
# the begin{} block or anything like that.  Name, params, etc don't always need to follow the cmdlet guidelines.
# Note that variables from outer scopes are automatically available.  (even if we're in another file!)
function script:Cleanup { $buf.Clear() }

# In these small helpers where the logic is straightforward and the correct behavior well known, I occasionally 
# condense the indentation to something in between the "one liner" and "Microsoft C# guideline" styles
filter script:FixComputerName
{
    if ($ComputerName -and $_) {            
        # handle UNC paths 
        if ($_[1] -eq "\") {   
            $uncHost = ($_ -split "\\")[2]
            $_.Replace($uncHost, $ComputerName)
        } else {
            $drive = $_[0]
            $pathUnderDrive = $_.Remove(0,3)            
            "\\$ComputerName\$drive`$\$pathUnderDrive"
        }
    } else {
        $_
    }
}

Powershell - Get-USB

function Get-USB {
    <#
    .Synopsis
        Gets USB devices attached to the system
    .Description
        Uses WMI to get the USB Devices attached to the system
    .Example
        Get-USB
    .Example
        Get-USB | Group-Object Manufacturer  
    .Parameter ComputerName
        The name of the computer to get the USB devices from
    #>
    param($computerName = "localhost")
    Get-WmiObject Win32_USBControllerDevice -ComputerName $ComputerName `
        -Impersonation Impersonate -Authentication PacketPrivacy | 
        Foreach-Object { [Wmi]$_.Dependent }
}

Powershell - Launch/Start a process on a remote machine without powershell installed on it

How to launch/start a process on a remote machine when this one does not have Powershell ? ... WMI!

Solution 1 (Ravikanth Chaganti, see his WMI book! Must read!)
$proc = Invoke-WmiMethod `
        -ComputerName Test `
        -Class Win32_Process `
        -Name Create `
        -ArgumentList "Notepad.exe"
Register-WmiEvent `
    -ComputerName test `
    -Query "Select * from Win32_ProcessStopTrace Where ProcessID=$($proc.ProcessId)" `
    -Action { Write-Host "Process ExitCode: $($event.SourceEventArgs.NewEvent.ExitStatus)" }

Solution 2 (The Lonely Administrator)

Function New-RemoteProcess {

2011/06/25

Powershell - Exchange Environment Report

Exchange Environment Report
A quick post on Exchange fellow Steve Goodman who created a nice PowerShell script which generates a basic HTML report on your Exchange environment. When required, you can also e-mail the report, which is nice if you want to schedule the script to run on a daily basis for example.

The script is provided as-is so you can tailor it to your needs. It’s still work in progress, so if you got any requests just send Steve a message.
You can find the post and script here.

2011/06/13

Powershell and Windows updates

#
# Functions from http://richardspowershellblog.wordpress.com/
#


# --- GET-UPDATE --- #
function get-update {
    $session = New-Object -ComObject Microsoft.Update.Session
    $searcher = $session.CreateUpdateSearcher()
    $result = $searcher.Search("IsInstalled=0 and Type='Software'" )

    $result.Updates | select Title, IsHidden
}

# --- GET-UPDATE --- # (updated)
function get-update2 {
    [CmdletBinding()] 
    param ( 
         [switch]$hidden 
    ) 
    PROCESS{
        $session = New-Object -ComObject Microsoft.Update.Session
        $searcher = $session.CreateUpdateSearcher()

        # 0 = false & 1 = true
        if ($hidden){
             $result = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=1" )
        }
        else {
             $result = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=0" )
        }

        if ($result.Updates.Count -gt 0){
             $result.Updates | 
             select Title, IsHidden, IsDownloaded, IsMandatory, 
             IsUninstallable, RebootRequired, Description
        }
        else {
             Write-Host " No updates available"
        } 

    }#process

<# 
.SYNOPSIS Discovers available updates 
.DESCRIPTION Interrogates Windows updates for available software updates only. Optional parameter to display hidden updates 
.PARAMETER hidden A switch to display the hidden updates 
.EXAMPLE get-update Displays non-hidden updates 
.EXAMPLE get-update -hidden Displays hidden updates #>
}



# --- GET-INSTALLEDUPDATE --- #
function get-installedupdate {
    $session = New-Object -ComObject Microsoft.Update.Session
    $searcher = $session.CreateUpdateSearcher()
    $result = $searcher.Search("IsInstalled=1 and Type='Software'" )

    $result.Updates | select Title, LastDeploymentChangeTime
}


# --- INSTALL-UPDATE --- #
function install-update {
    $session = New-Object -ComObject Microsoft.Update.Session
    $searcher = $session.CreateUpdateSearcher()

    $result = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=0")
    
    if ($result.Updates.Count -eq 0) {
         Write-Host "No updates to install"
    }
    else {
        $result.Updates | select Title
    }

    $downloads = New-Object -ComObject Microsoft.Update.UpdateColl

    foreach ($update in $result.Updates){
         $downloads.Add($update)
    }
     
    $downloader = $session.CreateUpdateDownLoader()
    $downloader.Updates = $downloads
    $downloader.Download()

    $installs = New-Object -ComObject Microsoft.Update.UpdateColl
    foreach ($update in $result.Updates){
         if ($update.IsDownloaded){
               $installs.Add($update)
         }
    }

    $installer = $session.CreateUpdateInstaller()
    $installer.Updates = $installs
    $installresult = $installer.Install()
    $installresult

}

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
    }
  }
}

2011/02/16

Active Directory - List and Set/Fix AD users not inheriting permissions

updated: 2013/03/29

Inherited permissions are those that are propagated to an object from a parent object. Inherited permissions ease the task of managing permissions and ensure consistency of permissions among all objects within a given container.

If the Allow and Deny permission check boxes in the various parts of the access control user interface are shaded when you view the permissions of an object, the object has inherited permissions from a parent object. You can set these inherited permissions by using the Permissions tab of the Advanced Security Settings properties page.

Check Technet for more information

Here is the PowerShell way to check which users does not have Inheriting Permission and How to Enabling it for all your users. You will need to user Quest Active Directory Snapin

List Users without Inheriting Permission
# This Command will list the user not inheriting Permission
Get-QADUser -SizeLimit 0 | `
Where-Object {$_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected}


Enabling Inheriting Permission for all Users
# This Command will enable inheriting Permission for all the accounts
Get-QADUser -SizeLimit 0 | `
Where-Object {$_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected} | `
Set-QADObjectSecurity -UnLockInheritance

2011/02/15

How to find running processes and their port number


Source

The netstat command line utility displays protocol statistics and current TCP/IP network connections. If we want to display the associated process identifier (PID) of each process we add the -o parameter.

image
To filter the result we need to pipe to the Find utility and again, the result is text!. In PowerShell we can get the same information with the following command, however the process PID is missing and the connections in LISTENING state are not included by default.
PS > [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties().GetActiveTcpConnections()
With the Get-NetworkStatistics function we can get the same information but each returned connection is an objectGet-NetworkStatistics parses only TCP/UDP connections (entries that starts with '[::' are ignored). Each connection is divided into two columns. For example, if the 'Local Address' column has a value of '0.0.0.0:80' the IP address will be shown in the LocalAddress property (e.g 0.0.0.0)  and the port number in the LocalPort property (e.g 80). The name of each process is also added to the result. This should make filtering much more easier when we pipe the result to the Where-Object cmdlet, allowing us to filter on any property of a connection.
UPDATE: Added support for IPv6 connections. @xcud and surveyor, thanks for the input!


function Get-NetworkStatistics
{
    $properties = 'Protocol','LocalAddress','LocalPort'
    $properties += 'RemoteAddress','RemotePort','State','ProcessName','PID'

    netstat -ano | Select-String -Pattern '\s+(TCP|UDP)' | ForEach-Object {

        $item = $_.line.split(" ",[System.StringSplitOptions]::RemoveEmptyEntries)

        if($item[1] -notmatch '^\[::')
        {           
            if (($la = $item[1] -as [ipaddress]).AddressFamily -eq 'InterNetworkV6')
            {
               $localAddress = $la.IPAddressToString
               $localPort = $item[1].split('\]:')[-1]
            }
            else
            {
                $localAddress = $item[1].split(':')[0]
                $localPort = $item[1].split(':')[-1]
            } 

            if (($ra = $item[2] -as [ipaddress]).AddressFamily -eq 'InterNetworkV6')
            {
               $remoteAddress = $ra.IPAddressToString
               $remotePort = $item[2].split('\]:')[-1]
            }
            else
            {
               $remoteAddress = $item[2].split(':')[0]
               $remotePort = $item[2].split(':')[-1]
            } 

            New-Object PSObject -Property @{
                PID = $item[-1]
                ProcessName = (Get-Process -Id $item[-1] -ErrorAction SilentlyContinue).Name
                Protocol = $item[0]
                LocalAddress = $localAddress
                LocalPort = $localPort
                RemoteAddress =$remoteAddress
                RemotePort = $remotePort
                State = if($item[0] -eq 'tcp') {$item[3]} else {$null}
            } | Select-Object -Property $properties
        }
    }
}
Get-NetworkStatistics | Format-Table 
image
To get all processes running on a local port 80:
image
Or find a connection information by filtering on ProcessName:
image

Working with SID

technet more info

Account Name to SID

#
#Get "fabrikam, kenmyer" to SID
$objUser = New-Object System.Security.Principal.NTAccount("fabrikam", "kenmyer")
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value


SID to Account Name

#
# translate "S-1-5-21-1454471165-1004335555-1606985555-5555" to Account Name
$objSID = New-Object System.Security.Principal.SecurityIdentifier `
    ("S-1-5-21-1454471165-1004335555-1606985555-5555")
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
$objUser.Value

2011/02/02

Generating Passwords with Powershell

Source

#
#######################################################################
# FUNCTION NAME: New-Password
#   
# See USAGE() function for docs.
#
# WRITTEN BY: Derek Mangrum
#
# REVISION HISTORY:
#     2008-10-23 : Initial version
#######################################################################
function New-Password
{
    param 
    (
        [int]$length,
        [switch]$lowerCase,
        [switch]$upperCase,
        [switch]$numbers,
        [switch]$specialChars
    )

    BEGIN
    {
        # Usage Instructions
        function Usage() 
        {
            Write-Host ''
            Write-Host 'FUNCTION NAME: New-Password' -ForegroundColor White
            Write-Host ''
            Write-Host 'USAGE'
            Write-Host '    New-Password -length 10 -upperCase -lowerCase -numbers'
            Write-Host '    New-Password -length 10 -specialChars'
            Write-Host '    New-Password -le 10 -lo -u -n -s'
            Write-Host '    New-Password'
            Write-Host ''
            Write-Host 'DESCRIPTION:'
            Write-Host ' Generates a random password of a given length (-length parameter)'
            Write-Host ' comprised of at least one character from each subset provided'
            Write-Host ' as a switch parameter.'
            Write-Host ''
            Write-Host 'AVAILABLE SWITCHES:'
            Write-Host ' -lowerCase    : include all lower case letters'
            Write-Host ' -upperCase    : include all upper case letters'
            Write-Host ' -numbers      : include 0-9'
            Write-Host ' -specialChars : include the following- !@#$%^&*()_+-={}[]<>'
            Write-Host ''
            Write-Host 'REQUIREMENTS:'
            Write-Host ' You must provide the -length (four or greater) and at least one character switch'
            Write-Host ''
        }
        
        function generate_password
        {
            if ($lowerCase)    
            { 
                $charsToUse += $lCase
                $regexExp += "(?=.*[$lCase])"
            }
            if ($upperCase)        
            { 
                $charsToUse += $uCase 
                $regexExp += "(?=.*[$uCase])"
            }
            if ($numbers)
            { 
                $charsToUse += $nums 
                $regexExp += "(?=.*[$nums])"
            }
            if ($specialChars)    
            { 
                $charsToUse += $specChars
                $regexExp += "(?=.*[\W])"
            }
            
            $test = [regex]$regexExp
            $rnd = New-Object System.Random
            
            do 
            {
                $pw = $null
                for ($i = 0 ; $i -lt $length ; $i++)
                {
                    $pw += $charsToUse[($rnd.Next(0,$charsToUse.Length))]
                    Start-Sleep -milliseconds 20
                }
            }
            until ($pw -match $test)
            
            return $pw
        }

        # Displays help
        if (($Args[0] -eq "-?") -or ($Args[0] -eq "-help")) 
        {
            Usage
            break
        }
        else
        {
            $lCase = 'abcdefghijklmnopqrstuvwxyz'
            $uCase = $lCase.ToUpper()
            $nums = '1234567890'
            $specChars = '!@#$%^&*()_+-={}[]<>'
        }
    }
    
    PROCESS
    {
        if (($length -ge 4) -and ($lowerCase -or $upperCase -or $numbers -or $specialChars))
        {
            $newPassword = generate_password
        }
        else
        {
            Usage
            break
        }
        
        $newPassword
    }
    
    END
    {
    }
}




Use the script like this:

New-Password -length 7 -lowerCase -upperCase -numbers -specialChars

2011/01/31

Powershell - SYDI - Convert all my XML to DOC Files

SYDI is a script which collects information from your servers and networks, then writes the data to a report (XML, DOC or HTM File)

In my case i collected all the information into XML Files. Then i needed to convert those XML files to DOC files.

#


# ==============================================================================================
# 
# Microsoft PowerShell Source File
# 
# NAME: SYDI-Convert_XML_files_To_DOC.ps1
# 
# AUTHOR: fxavier.cat@gmail.com
# DATE  : 1/26/2011
# 
# COMMENT: Convert all the XML files in the folder XML to a DOC file and output in DOC folder
# 
# ==============================================================================================

###################
## CONFIGURATION ##
###################

$PathToSYDI = "c:\sydi"
$PathToXML = "c:\sydi\xml"
$PathToDOC = "c:\sydi\doc"
$PathToTOOLS = "c:\sydi\tools"
$WaitTimeSecs = 10

############
## SCRIPT ##
############

# Get listing of XML files
$XMLList=gci $PathToXML

# Get the count of files in $PathToXML
$count_xml = gci $PathToXML\ | measure
$TotalFilesXML=$count_xml.count

# Create a counter to show in the loop (foreach)
$counter = 0

# Show the count of files
Write-Host "Total XML Files:" $TotalFilesXML

# Start the Loop
Write-Host "Start - XML to DOC"
gci $PathToXML\|sort | `
foreach {
$counter++
$fichier = $_.name
$fichierBasename = $_.basename
$fichierCreatedOnYEAR=$_.lastwritetime.Year
$fichierCreatedOnMONTH=$_.lastwritetime.Month
$fichierCreatedOnDAY=$_.creationtime.Day

Write-Host "# $counter of $TotalFilesXML"
Write-Host "Current file: $fichier"
Write-Host "XML File Creation time of the $fichier is $fichierCreatedOnYEAR-$fichierCreatedOnMONTH-$fichierCreatedOnDAY"

# Run SYDI
cscript "$PathToTOOLS\ss-xml2word.vbs" "-d" "-x$PathToXML\$fichier" "-l$PathToTOOLS\lang_english.xml" "-o$PathToDOC\$fichierBasename-$fichierCreatedOnYEAR-$fichierCreatedOnMONTH-$fichierCreatedOnDAY.doc"

Write-Host "DOC File saved as: "+"$PathToDOC\$fichierBasename-$fichierCreatedOnYEAR-$fichierCreatedOnMONTH-$fichierCreatedOnDAY.doc"

# Show again the counter
Write-Host "#$counter of $TotalFilesXML"

# Timeout to make sure the sydi is done.
Write-Host "Next in $WaitTimeSecs secs..."
Start-Sleep $WaitTimeSecs

# Kill winword to make sure the script dont launch multiple process
Write-Host "Killing process winword.exe"
Stop-Process -Name "winword" -Force

}

# Count DOC Files
$count_DOC = gci $PathToDOC\ | measure
$TotalFilesDOC=$count_DOC.count

# Get listing of DOC Files
$DOCList=gci $PathToDOC

Write-Host "Total DOC Files:"$TotalFilesDOC
Write-Host "Total XML Files:"$TotalFilesXML



2011/01/28

Use PowerShell to enumerate info from your Certificate Server

Source

#
#

Function Get-CertInfo($server) {
 $CA=$Server
$CaView = New-Object -Com CertificateAuthority.View.1
$CaView.OpenConnection($CA)
$NumberOfColumns=8
$CaView.SetResultColumnCount($NumberOfColumns)
$Index0 = $CAView.GetColumnIndex($False, "CommonName")
$Index1 = $CAView.GetColumnIndex($False, "Email")
$Index2 = $CAView.GetColumnIndex($False, "NotAfter")
$Index3 = $CAView.GetColumnIndex($False, "Country")
$Index4 = $CAView.GetColumnIndex($False, "Organization")
$Index5 = $CAView.GetColumnIndex($False, "OrgUnit")
$Index6 = $CAView.GetColumnIndex($False, "DistinguishedName")
$Index7 = $CAView.GetColumnIndex($False, "Disposition")
 
$CAView.SetResultColumn($Index0)
$CAView.SetResultColumn($Index1)
$CAView.SetResultColumn($Index2)
$CAView.SetResultColumn($Index3)
$CAView.SetResultColumn($Index4)
$CAView.SetResultColumn($Index5)
$CAView.SetResultColumn($Index6)
$CAView.SetResultColumn($Index7)
 
 
$RowObj= $CAView.OpenView()
[void]$RowObj.Next()
$Cert="IssuingCA,CommonName,Email,NotAfter,Country,Organization,OrgUnit,DistinghuishedName,Disposition`n"
 
Do
{
$Cert= $Cert + $srv + ","
$ColObj = $RowObj.EnumCertViewColumn()
[void]$ColObj.Next()
 
Do {
$Cert = $Cert + $ColObj.GetValue(1) + ","
 
} Until ($ColObj.Next() -eq -1)
 
Clear-Variable ColObj
$Cert=$Cert+"`n"
 
} Until ($Rowobj.Next() -eq -1 )
  
 
Return $Cert
}
#
#



VBSCRIPT VERSION:

Const CV_OUT_BASE64 = &H1

'THIS IS THE \CAName
CAName = "MyMachine\SpatCA" '=======>> CHANGE THIS TO THE CORRECT MACHINE\CA==


'create the CAView object
set oCAView = CreateObject("CertificateAuthority.View.1")


'open the connection to the Machine\CA
oCAView.OpenConnection (CAName)

'retrieve specific columns from DB
oCAView.SetResultColumnCount(3)
Index0 = oCAView.GetColumnIndex(False, "CommonName")
Index1 = oCAView.GetColumnIndex(False, "Email")
Index2 = oCAView.GetColumnIndex(False, "NotAfter")


oCAView.SetResultColumn (Index0)
oCAView.SetResultColumn (Index1)
oCAView.SetResultColumn (Index2)


'open the view
Set RowObj= oCAView.OpenView




Do Until RowObj.Next = -1

Set ColObj = RowObj.EnumCertViewColumn()

Do Until ColObj.Next = -1
wscript.echo ColObj.GetValue(CV_OUT_BASE64) & vbcrlf
'insert logic for checking date to
'current and if near\past send mail.
'see http://www.paulsadowski.com/WSH/cdo.htm
'for a number of examples of mail send info
'Obviously you may want to use the cert email
'attribute to send the mail
Loop

Set ColObj = Nothing

Loop

Compare two users accounts

#
Add-PSSnapin Quest.ActiveRoles.ADManagement
function Compare-ADUserGroups
{
 #requires -pssnapin Quest.ActiveRoles.ADManagement
 param (
  [string] $FirstUser = $(Throw "SAMAccountName required."),
  [string] $SecondUser = $(Throw "SAMAccountName required.")
 )

 $a = (Get-QADUser $FirstUser).MemberOf
 $b = (Get-QADUser $SecondUser).MemberOf
 $c = Compare-Object -referenceObject $a -differenceObject $b
 $c
 
}


Compare-ADUserGroups -firstuser useraccount1 -SecondUser useraccount2|fl
#
#

2010/12/23

Powershell - Using String Functions

 

Source: http://powershell.com/cs/blogs/tips/archive/2009/06/08/using-string-functions.aspx

PowerShell uses .NET objects everywhere. Anything is represented as .NET object, and .NET objects come with useful built-in methods. However, for string manipulation you do not need to look for sophisticated external commands as they are built right into strings.

Here are a couple of useful examples:

"Hello".ToLower()
"Hello".ToUpper()
"Hello".EndsWith('lo')
"Hello".StartsWith('he')
"Hello".toLower().StartsWith('he')
"Hello".Contains('l')
"Hello".LastIndexOf('l')
"Hello".IndexOf('l')
"Hello".Substring(3)
"Hello".Substring(3,1)
"Hello".Insert(3, "INSERTED")
"Hello".Length
"Hello".Replace('l', 'x')
"Server1,Server2,Server3".Split(',')
" remove space at ends ".Trim()
" remove space at ends ".Trim(' rem')