Runspace Timeout

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Joseph Monarch Joseph Monarch 1 year, 2 months ago.

  • Author
    Posts
  • #31453
    Profile photo of Joseph Monarch
    Joseph Monarch
    Participant

    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)
    		}
    	}
    }
    
  • #31454
    Profile photo of Mark
    Mark
    Participant

    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()
    
  • #31465
    Profile photo of Joseph Monarch
    Joseph Monarch
    Participant

    That worked. thank you very much.

You must be logged in to reply to this topic.