How do I use workflows in cmdlets?

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of GS GS 3 years, 2 months ago.

  • Author
    Posts
  • #14666
    Profile photo of GS
    GS
    Participant

    hello,

    I have written cmdlet which cleans up space on remote servers via WMI calls. It works fine but it obviously runs in sequence if I have to do multiple servers. My understanding I need to implement this as workflow to run in parrallel. I wrapped my entire cmdlet in workflow CleanUpSpace{} and I assumed I can just call CleanUpSpace -computers "COMP1", COMP2" from withing cmdlet but it would not work complaining that CleanUpSpace is not recognized as cmdlet. What am I doing wrong. Code is below

    function MFE-CleanUpSpace{
    
    param(
    [parameter(Mandatory=$true,ValueFromPipeline=$true)] 
    [string[]]$computerNames
    )
    process{
    CleanUpSpace $computerNames
    
    	workflow CleanUpSpace{
    	param([string[]]$computerNames)
    		ForEach -Parallel ($computerName in $computerNames)
    		{
    			sequence{
    
    				$DriveSize = gwmi -class win32_logicaldisk -PsComputerName "$computerName"
    				$a = @{}
    				$DriveSize | ? {$_.FreeSpace -gt 0}| % {$a.Add($_.DeviceID, (@{"OriginalFreeSpace"= ([Math]::Round($_.FreeSpace/1GB, 3)); "FreeSpaceNow"= 0}))}
    				$foldersToScan = "c:\Windows\$hf_mig$", "c:\windows\ie8updates", "c:\windows\ie7updates"
    				$filesToScan = "\\logs\\httperr\\", "\\logfiles\\W3SVC1395239964\\"
    				foreach ($file in $filesToScan)
    				{
    					$date = [Management.ManagementDateTimeConverter]::ToDmtfDateTime((Get-Date).AddDays(-60))
    					Write-Debug "Getting files from $file folder"
    					$wmi = Get-WmiObject -PSComputer $computerName -Query "Select * From CIM_DataFile Where Path = '$file' and (Extension = 'zip' or Extension = 'log') and CreationDate < '$date'"
    					if ($wmi -ne $null)
    					{
    						Write-Output "Found $($wmi.Count) files in $file folder"
    						[int] $i = 0
    						[int] $total = $wmi.Count
    						foreach ($myfile in $wmi)
    						{
    							$i++
    							Write-Progress -Activity "Deleting files from $file" -PercentComplete ([System.Math]::Round($i * 100 / $total)) -CurrentOperation "Deleting $myfile"
    							inlinescript{
    								$myfile.Delete()| Out-Null
    							}
    						}
    					}
    					else
    					{
    						Write-Output "No eligible files were found in $file folder to delete"
    					}
    				}
    				foreach ($folder in $foldersToScan)
    				{
    					Write-Output "Getting subfolder of $folder"
    					$wmi = Get-WmiObject -PSComputerName $computerName -Query "ASSOCIATORS of {Win32_Directory.Name='$folder'} WHERE AssocClass= Win32_Subdirectory ResultRole=PartComponent"
    					if ($wmi -ne $null) 
    					{
    						Write-Output "Found eligible subfolders under $folder"
    						[int]$i = 0
    						[int]$total = $wmi.Count
    						foreach ($subfolder in $wmi)
    						{
    							$i++
    
    							if ([Management.ManagementDateTimeConverter]::ToDateTime($subfolder.CreationDate) -le (Get-Date).AddDays(-60))
    							{
    								Write-Progress -Activity "Deleting subfolders from $folder" -PercentComplete ([System.Math]::Round($i * 100 / $total)) -CurrentOperation "Deleting $subfolder"
    								inlinescript{
    								$subfolder.Delete()| Out-Null
    								}
    							}
    						}
    
    
    					}
    					else 
    					{
    					Write-Output "No elegible subfolders found"
    					}
    				}
    				$DriveSize = gwmi -class win32_logicaldisk -PSComputerName "$computerName" 
    				$DriveSize | ? {$_.FreeSpace -gt 0}| % {$a[$_.DeviceID].FreeSpaceNow = ([Math]::Round($_.FreeSpace/1GB, 3))}
    				Write-Output "For $computerName following space was cleared`n"
    				Inlinescript{
    				$a.GetEnumerator()| select -Property @(@{n="DriveLetter"; e= {$_.Key}}, @{n="Free Space Before"; e={$_.Value['OriginalFreeSpace']}}, @{n="Free Space Now"; e= {$_.Value['FreeSpaceNow']}})| Sort-Object -Property DriveLetter| ft -AutoSize
    				}
    
    			}
    		}
    
    	}
    
  • #14668
    Profile photo of Don Jones
    Don Jones
    Keymaster

    No, you don't need to write it as a workflow just to have in run in parallel. That's one option, but just one. Workflows are a lot more complex.

    Workflows work best when you've enabled Remoting on your target computers – workflow's main intent is to push the workflow out to the targets, and have the script actually run locally on each target.

    But workflows aren't PowerShell scripts. They're run in WWF – and as you've seen, it doesn't work quite the same as PowerShell. You'd likely have to do an InlineScript() element that defines and runs your function. That can, in turn, be parallelized.

  • #14669
    Profile photo of GS
    GS
    Participant

    Remoting is not an option for us, so I have to run everything through WMI.
    So how do I do what I need to do in parrallel, then? Foreach -parallel requiring workflow

You must be logged in to reply to this topic.