Author Posts

April 21, 2014 at 8:14 am

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
				}

			}
		}

	}

April 21, 2014 at 8:36 am

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.

April 21, 2014 at 8:57 am

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