Your basic ITPro blog... What's going on at work, what I'm interested in.

Thursday, October 2, 2008

Major Update to my New-SharedFolder script...

More PowerShell geekery ahead!

I've written about this before, here and here. But, I use it so often that I am constantly thinking about how to improve it. Well, today, I made what I feel is a major leap regarding the functionality of this tool.

The main goal of my efforts today was to make this tool more Powershell-y... that is, not so much a script to be run, but a function that now interacts with the pipeline and accepts parameters.

My previous version of this script was normally run dot-sourced and the session looked something like:

image

It required: 1)being run, 2)selecting <1 or 2>; 3)typing of foldername or .txt file path

It was basically a mini-app. This was OK, but not really in the spirit of Powershell. So, I re-wrote things. Actually, I re-organized things more than re-wrote them. Anyway, now the process looks like:

image

It is now a function. So, I can now perform this operation the following ways:

  • 'folderName1','folderName2' | New-SharedFolder
  • 'c:\scripts\folderList.txt' | New-SharedFolder
  • 'folderName', 'c:\scripts\folderList.txt' | New-SharedFolder
  • New-SharedFolder 'folderName'
  • etc...

The function accepts input of a folder name and/or a filename (with path). It runs a Test-Path on the input and, if it finds the file, it reads its contents. If the Test-Path fails, it assumes that a folder name was entered.

Here's the new code, in case you are interested. I am sure there are many things in this code that some PoSH gurus out there might roll their eyes at. But, for me, it is a big leap forward. I know that I am not done working on this function.

function New-SharedFolder
{
    param ( [string]$inputString )

    BEGIN
    {
        # Usage Instructions
        function Usage() 
        {
            <Code to display docs>
        }
        
        # Loads the foldernames in array for processing
        function load_folderlist_array
        {
            param ( [string]$inStr )
            
            if (Test-Path $inStr)
            {
                $fl = Get-Content $inStr
            }
            else
            {
                $fl = $inStr
            }
            return $fl
        }
        
        # Displays help
        if (($Args[0] -eq "-?") -or ($Args[0] -eq "-help")) 
        {
            Usage
            break
        }

        # This Function creates folder and groups
        function process_folders 
        {
            param([array]$allFolderNames)
                        
            foreach ($folder in $allFolderNames) 
            {
                Write-Host "************************************************" -foregroundcolor White
                Write-Host "Now processing folder name: $folder"
        
                # Defining path to folder
                $FullPath = "\\FS01\Groups\" + $folder
            
                #Does this folder already exist?
                if (Test-Path $FullPath) 
                {
                    #Folder already exists. Abort operation.
                    Write-Host -ForegroundColor Red "The folder $FullPath already exists and is being skipped. Please verify the folder name."
                }
                else 
                {
                    # Create variables holding group names and descriptions
                    # If necessary, shorten folder name to 13 characters
                    if ($folder.length -gt 13) 
                    {
                        $MODgroup = "s_$($folder.substring(0,13))_MOD"
                        $MODdesc = "$folder -- MODify security group"
                        $ROgroup  = "s_$($folder.substring(0,13))_RO"
                        $ROdesc = "$folder -- ReadOnly security group"
                    }
                    else 
                    {
                        $MODgroup = "s_$($folder)_MOD"
                        $MODdesc = "$folder -- MODify security group"
                        $ROgroup  = "s_$($folder)_RO"
                        $ROdesc = "$folder -- ReadOnly security group"
                    }
                    # Defines OU location for Security Group Creation
                    $GroupContainer = <Path to OU>
                    # Create Groups
                    Write-Host "Creating MODify security group for this folder..." -NoNewline
                    $null = New-QADGroup -ParentContainer $GroupContainer -name $MODgroup -samAccountName $MODgroup -GroupType 'security' -GroupScope 'GLOBAL' -description $MODdesc
                    Write-Host "  DONE!" -foregroundcolor Green
                    Write-Host "Creating ReadOnly security group for this folder..." -NoNewline
                    $null = New-QADGroup -ParentContainer $GroupContainer -name $ROgroup -samAccountName $ROgroup -GroupType 'security' -GroupScope 'GLOBAL' -description $ROdesc
                    Write-Host "  DONE!" -foregroundcolor Green
        
                    # Create Folder
                    Write-Host "Creating folder under \\FS01\Groups ..." -NoNewline
                    $null = New-Item -path \\FS01\Groups -name $folder -type directory
                    Write-Host "  DONE!" -foregroundcolor Green
                
                    # Check for security groups on all DCs
                    wait_for_replication
                    
                    # Assign rights to the folder for the groups
                    #   MODIFY RIGHTS
                    Write-Host "`nAssigning MODify ACL entries for this folder to the MOD group..."
                    assign_rights "Modify" $MODgroup
                                
                    #   READONLY RIGHTS
                    Write-Host "Assigning ReadOnly ACL entries for this folder to the RO group..."
                    assign_rights "Read" $ROgroup
                }
            }
        }

        # Checks all DCs for security groups, verifying replication
        function wait_for_replication 
        {
            $DCs = Get-QADComputer -ComputerRole DomainController
            
            foreach ($DC in $DCs)
            {
                $aa = $null
                $bb = $null
                Write-Host "`nChecking for Security Group on $($DC.Name)" -noNewLine
                
                do
                {
                    $null = Connect-QADService -Service $DC.Name
                    $aa = Get-QADGroup $MODgroup
                    $bb = Get-QADGroup $ROgroup
                    Disconnect-QADService 
                    Start-Sleep -Seconds 1
                    Write-Host '.' -noNewLine
                }
                until ($aa -ne $null -and $bb -ne $null)
            }
        }
    
        # Modifies ACL on folder, giving MOD and RO groups appropiate rights
        function assign_rights 
        {
            param([string]$Rights, [string]$GroupName)
            
            $acl = get-acl $FullPath
            $Inherit = [Security.AccessControl.InheritanceFlags] "ContainerInherit, ObjectInherit"
            $Prop = [Security.AccessControl.PropagationFlags] "None"
            $NewRule = new-object Security.AccessControl.FileSystemAccessRule $GroupName, $Rights, $Inherit, $Prop, Allow
            $modified = $FALSE
            $modded = $acl.ModifyAccessRule("Add", $NewRule, [ref]$modified)
            set-acl -path $FullPath -AclObject $acl
            
            if ($modded) 
            {
                Write-Host "ACL for $GroupName successfully applied." -foregroundcolor Green
            }
            else 
            {
                Write-Host "WARNING!!! ACL for $GroupName failed to apply!" -ForegroundColor Red 
            }
        }    
    }

    PROCESS
    {
        if ($inputString -and $_)
        {
            Throw 'Please use either pipeline or input parameter'
            break
        }
        elseif ($inputString)
        {
            $folderNames = load_folderlist_array $inputString
        }
        elseif ($_)
        {
            $folderNames = load_folderlist_array $_
        }
        else
        {
            Usage
            break
        }
        
        process_folders $folderNames
    }
    
    END
    {
        Write-Host "`nJob Complete." -foregroundcolor White
    }
}

No comments:

Additional Info

My photo
email: support (AT) mangrumtech (DOT) com
mobile: 480-270-4332