Author Posts

October 28, 2015 at 11:26 am

I have recreated a script that uses Runspaces and it runs great until the end of the script. I am assuming I have some Runspaces that are hanging and won't allow the script to finish. Is there a way to add a time out to the script. I have tried searching Google for the answer with no success.

$user = "*********"
$pwd = Get-Content "$dir\cred.txt" | ConvertTo-SecureString
#Read-Host "What is $user password" -AsSecureString | ConvertFrom-SecureString | Out-File "$dir\cred.txt"
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pwd

Import-Module ActiveDirectory

$var1 = Get-ADComputer -SearchBase '****************-SearchScope 2 -Filter * | Select -ExpandProperty Name | Sort
$var2 = Get-ADComputer -SearchBase '****************--SearchScope 2 -Filter { (Name -notlike "MBV*") } | Select -ExpandProperty Name | Sort
$var3 = Get-ADComputer -SearchBase '****************- -SearchScope 2 -Filter * | Select -ExpandProperty Name | Sort

$computers = $var1 + $var2 + $var3

[Void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data")

#region MySQL Database Connection Variables
$dbserver = "******"
$dbuserid = "******"
$dbpwd = "******"
$db = "******"
#endregion

# Create RunSpace Collection
$RunspaceCollection = @()

# Open RunSpace
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1,50)
$RunspacePool.Open()

$ScriptBlock = {
	# Code to execute per runspace
	Param($pc,$credentials,$dbserver,$dbuserid,$dbpwd,$db)
	
	if (Test-Connection $pc -Count 2 -Quiet) {
		$sys = Get-WmiObject Win32_ComputerSystem -ComputerName $pc -Credential $credentials -ErrorAction SilentlyContinue
		$sysmanuf = $sys.Manufacturer
		$sysmodel = $sys.Model
		
#		$dc = Get-ADComputer $pc -Properties *
#		$dc = $dc.LastLogonTimeStamp
#		$dc = [datetime]::FromFileTime($dc).ToString('yyyy-MM-dd')
		
		$os = Get-WmiObject Win32_OperatingSystem -ComputerName $pc -Credential $credentials -ErrorAction SilentlyContinue
		$oscap = $os.Caption
		
		$instally = $os.InstallDate.Substring(0, 4)
		$installm = $os.InstallDate.Substring(4, 2)
		$installd = $os.InstallDate.Substring(6, 2)
		$installdate = "$instally-$installm-$installd"
		
		$rebooty = $os.LastBootUpTime.Substring(0, 4)
		$rebootm = $os.LastBootUpTime.Substring(4, 2)
		$rebootd = $os.LastBootUpTime.Substring(6, 2)
		$reboot = "$rebooty-$rebootm-$rebootd"
		
		$serial = Get-WmiObject Win32_Bios -ComputerName $pc -Credential $credentials -ErrorAction SilentlyContinue
		$serial = $serial.SerialNumber
		
		$systemSKU = Get-WmiObject -Namespace root\wmi -Class MS_SystemInformation -ComputerName $pc -Credential $credentials -ErrorAction SilentlyContinue
		$systemSKU = $systemSKU.SystemSKU.Substring(0, 7)
		
		$connStr = "server=$dbserver;userid=$dbuserid;password=$dbpwd;database=$db"
		$conn = New-Object Mysql.Data.MySqlClient.MySqlConnection($connStr)
		$conn.Open()
		$cmd = $conn.CreateCommand()
		
		$cmd.CommandText = "INSERT INTO TestDB (pcid,serial,manuf,model,product,os,install,reboot,billable,lastscan) VALUES ('$pc','$serial','$sysmanuf','$sysmodel','$systemSKU','$oscap','$installdate','$reboot','1','$time')"
		$cmd.ExecuteReader() | Out-Null
		$cmd.Dispose()
		$conn.Close()
		Return "$pc scanned"
	}
	else {
		$connStr = "server=$dbserver;userid=$dbuserid;password=$dbpwd;database=$db"
		$conn = New-Object Mysql.Data.MySqlClient.MySqlConnection($connStr)
		$conn.Open()
		$cmd = $conn.CreateCommand()
		
		$cmd.CommandText = "INSERT INTO TestDB (pcid,billable) VALUES ('$pc','1')"
		$cmd.ExecuteReader() | Out-Null
		$cmd.Dispose()
		$conn.Close()
		Return "$pc Billable"
	}
	# Any output needs to be done as 'Return'
}

foreach($pc in $computers){
	$Powershell = [PowerShell]::Create().AddScript($ScriptBlock).AddArgument($pc).AddArgument($credentials).AddArgument($dbserver).AddArgument($dbuserid).AddArgument($dbpwd).AddArgument($db)
																
	$Powershell.RunspacePool = $RunspacePool
	[Collections.Arraylist]$RunspaceCollection += New-Object -TypeName PSObject -Property @{
		Runspace = $PowerShell.BeginInvoke()
		PowerShell = $PowerShell
	}
	
}

While ($RunspaceCollection) {
	Foreach ($Runspace in $RunspaceCollection.ToArray()) {
		if ($Runspace.Runspace.IsCompleted) {
			$Runspace.PowerShell.EndInvoke($Runspace.Runspace)
			$Runspace.PowerShell.Dispose()
			$RunspaceCollection.Remove($Runspace)
		}
	}
}

October 28, 2015 at 12:34 pm

Try using a StopWatch:

$sw = [system.diagnostics.stopwatch]::startNew()
While ($RunspaceCollection) {
	Foreach ($Runspace in $RunspaceCollection.ToArray()) {
		if ($Runspace.Runspace.IsCompleted) {
			$Runspace.PowerShell.EndInvoke($Runspace.Runspace)
			$Runspace.PowerShell.Dispose()
			$RunspaceCollection.Remove($Runspace)
		}
	}
	Start-Sleep -Milliseconds 1000
	If ($sw.Elapsed.TotalMinutes -gt 30) {break}
}
$sw.Stop()

October 29, 2015 at 4:01 am

That worked. thank you very much.