Search code examples
sql-serverpowershellsmo

Multithreading Powershell Script


I'm using powershell to script out our database objects to do periodic audits. I've gotten it to a point now where I'm happy functionally... but would like it to be a bit faster. Found this on SO and have tried implementing it... however, I did not see any improvements in speed. Is it the nature of the SMO connection that making this process serial regardless? Google netted very little information... can someone chime in with some light?

Can Powershell Run Commands in Parallel?


Solution

  • The foreach -parallel construct can only be used in PowerShell Workflow definitions, not advanced functions. Here's a brief example of how you'd use it.

    workflow Audit-DB {
        $ComputerList = @('server1', 'server2', 'server3')*100;
        foreach -parallel ($Computer in $ComputerList) {
            Get-Date -Format 'hh:mm:ss';
            # Run your database audit code here.
            } 
    }
    
    Audit-DB;
    

    The Get-Date bit is just to show that it's really working in parallel.

    When you're working in PowerShell Workflow, the important thing to remember is that you are only allowed to call activities, not PowerShell functions. PowerShell automatically converts many of its core cmdlets into activities, but it's up to you to know the difference. Thankfully, there is an activity named InlineScript that allows you to call regular PowerShell script code.

    The cool thing about Workflow is that you don't even need to use the foreach -parallel construct. Instead, you automatically get the -PSComputerName parameter, which allows you to deploy the Workflow on remote computers. This requires that you configure PowerShell Remoting on all of your target systems ahead of time however, because Workflow sits on top of it.

    It gets even better, though! PowerShell Workflow also implicitly gives you the ability to execute your Workflow as a PowerShell background job! All you have to do is add the -AsJob parameter when you call your Workflow.

    Here's a sample that shows the InlineScript, -AsJob parameter, and how to deploy a Workflow to remote computers.

    workflow Audit-DBWorkflow {
        InlineScript {
            function Audit-DB {
                # Run your audit code here
            }
    
            Audit-DB;
        }
    }
    
    $ComputerList = @('localhost', 'localhost')*10; # Create an array of computers
    Audit-DBWorkflow -PSComputerName $ComputerList -AsJob;