none
Powershell Workflow. Test-Connect error: Error due to lack of resources RRS feed

  • Question

  • Hi!

    I use Test-Connection Cmdlet to ping a lot of PCs with workflow script (throttlelimit 5).

    Sometimes I get error message:

    Test-Connect error: Error due to lack of resources.

    When I use same script without workflow (10 copies of ps1-file) at the same PC, I don't get error message.

    Powershell 4.0

    Windows 7 SP1 Enterprise, installed all updates.

    Intel Pentium Dual CPU E2180 @ 2.00 GHz

    Memory - 4 GB

    Pagefile is enabled.

    Monday, March 2, 2015 11:34 AM

Answers

  • Start like this and return all data then insert into database.

    workflow PrinterBase{
    	
        $Computerlist = Get-Content C:\Powershell\PrinterBase\ComputerList.txt
        foreach -parallel -throttlelimit 10 ($Computer in $Computerlist){
        	inlinescript{
    			$props=@{
    				Status='Unavailablle'
    				HostName=$Using:Computer
    				HostIp=$null
    				HostPrefix=$null
    				HostUserName=$null
    				Printers=@()
    				CurrentTime= Get-Date
                }
            	if (test-connection -ComputerName $Using:Computer -count 1 -quiet){
    				$props.Status='Connected'
                	Try{
    					
                		$PrinterHost = Get-WMIObject -ComputerName $Using:Computer -class Win32_ComputerSystem -ErrorAction stop
    		            $props.HostUserName = $PrinterHost.UserName
    		            $NetworkInfo = Get-WmiObject -ComputerName $Using:Computer -Class Win32_NetworkAdapterConfiguration -Filter 'IPEnabled=True' -ErrorAction stop
    		            Foreach ($NetworkAdapter in $NetworkInfo){
    		                $NetworkAdapterCaption = $NetworkAdapter.Caption
    		            }
    
    			    $printers = Get-WmiObject -ComputerName $Using:Computer -class Win32_Printer -ErrorAction stop
                		    $props.Printers=foreach ($printer in $Printers){
    			        [pscustomobject]@{
    		                    PrinterCaption = $Printer.Name
    		                    PrinterDriverName = $Printer.DriverName
                    		}
                		    }
                    }
            	Catch{
    				$props.Status="$_"
            	}
            }
    		New-Object PsObject -Property $props
    	}
    }

    This will reduce resource usage on the local system dramatically and will be much faster.


    ¯\_(ツ)_/¯




    • Edited by jrv Monday, March 2, 2015 8:02 PM
    • Marked as answer by Sergey Vasiltsov Tuesday, March 3, 2015 6:31 AM
    Monday, March 2, 2015 8:00 PM

All replies

  • Without  your WorkFlow script we cannot possible be of any help.

    ¯\_(ツ)_/¯

    Monday, March 2, 2015 5:39 PM
  • Ok, Thanks.

    workflow PrinterBase
    {
        $Computerlist = Get-Content C:\Powershell\PrinterBase\ComputerList.txt
        foreach -parallel -throttlelimit 10 ($Computer in $Computerlist)
        {
        inlinescript
        {
            $CurrentTime = Get-Date
            if (test-connection -ComputerName $Using:Computer -count 1 -quiet)
                {
                Try
                {
                $PrinterHost = Get-WMIObject -ComputerName $Using:Computer -class Win32_ComputerSystem -ErrorAction stop
                $PrinterHostName = $PrinterHost.Name
                $HostUserName = $PrinterHost.UserName
                $PrinterName = Get-WmiObject -ComputerName $Using:Computer -class Win32_Printer -ErrorAction stop
                $PingInfo = Test-Connection -ComputerName $Using:Computer -Count 1
                $HostIp = $PingInfo.IPV4Address.IPAddressToString
                $NetworkInfo = Get-WmiObject -ComputerName $Using:Computer -Class Win32_NetworkAdapterConfiguration -ErrorAction stop
                Foreach ($NetworkAdapter in $NetworkInfo)
                    {
                    If ($NetworkAdapter.IPAddress -eq $PingInfo.IPV4Address.IPAddressToString)
                        {
                        $NetworkAdapterCaption = $NetworkAdapter.Caption
                        }
                    }
                $ActiveNetInfo = Get-WmiObject -ComputerName $Using:Computer -Class Win32_NetworkAdapterConfiguration -Filter "Caption='$NetworkAdapterCaption'" -ErrorAction stop
                [IPAddress]$IPprefix = (([IPAddress] $PingInfo.IPV4Address).Address -band ([IPAddress] $ActiveNetInfo.IPSubNet[0]).Address)
                $HostPrefix = $IPprefix.IPAddressToString
                foreach ($printer in $Using:PrinterName)
                    {
                    $PrinterCaption = $Printer.Name
                    $PrinterDriverName = $Printer.DriverName
                    $SQLServer = "localhost\SQLExpress"
                    $SQLDBName = "Printers"
                    $SQLTable = "MainPrinterLog"
                    $SqlQuery = "INSERT INTO [$SQLDBName].[dbo].[$SQLTable] VALUES ('$PrinterHostName','$HostIp','$HostPrefix','$HostUserName','$PrinterCaption','$PrinterDriverName','$CurrentTime')"
                    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
                    $SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
                    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
                    $SqlCmd.CommandText = $SqlQuery
                    $SqlCmd.Connection = $SqlConnection
                    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
                    $SqlAdapter.SelectCommand = $SqlCmd
                    $DataSet = New-Object System.Data.DataSet
                    $SqlAdapter.Fill($DataSet)
                    }
                }
            Catch
                {
                $SQLServer = "localhost\SQLExpress"
                $SQLDBName = "Printers"
                $SQLTable = "WMIErrorLog"
                $SqlQuery = "INSERT INTO [$SQLDBName].[dbo].[$SQLTable] VALUES ('$Using:Computer','$CurrentTime')"
                $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
                $SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
                $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
                $SqlCmd.CommandText = $SqlQuery
                $SqlCmd.Connection = $SqlConnection
                $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
                $SqlAdapter.SelectCommand = $SqlCmd
                $DataSet = New-Object System.Data.DataSet
                $SqlAdapter.Fill($DataSet)
                }
                }
            else
                {
                $SQLServer = "localhost\SQLExpress"
                $SQLDBName = "Printers"
                $SQLTable = "PingErrorLog"
                $SqlQuery = "INSERT INTO [$SQLDBName].[dbo].[$SQLTable] VALUES ('$Using:Computer','$CurrentTime')"
                $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
                $SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
                $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
                $SqlCmd.CommandText = $SqlQuery
                $SqlCmd.Connection = $SqlConnection
                $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
                $SqlAdapter.SelectCommand = $SqlCmd
                $DataSet = New-Object System.Data.DataSet
                $SqlAdapter.Fill($DataSet)
                }
            }
    }
    }
    $SQLServer = "localhost\SQLExpress"
    $SQLDBName = "Printers"
    $ScriptStartTime = Get-Date
    $ScriptDuration = Measure-Command {PrinterBase}
    $CurrentTime = Get-Date
    $SQLTable = "DurationLog"
    $SqlQuery = "INSERT INTO [$SQLDBName].[dbo].[$SQLTable] VALUES ('$ScriptStartTime','$CurrentTime','$ScriptDuration')"
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = $SqlQuery
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)


    P.S. Sorry for my English

    Monday, March 2, 2015 7:21 PM
  • Why would you use a workflow if everything is in an inline script?

    In a workflow we would really like to return the data then stuff it in the database.  You are generating loops of local connections to a database.  This will run out of resources quite frequently with SQLExpress and it is really unnecessary.

    Since all of you data comes from WMI why not just use WMI and return objects that carry the data for the database.  You can then easily upload that to a database in one shot.

    It would be different if the databases were on the remote machines but that is not the case.


    ¯\_(ツ)_/¯

    Monday, March 2, 2015 7:39 PM
  • Start like this and return all data then insert into database.

    workflow PrinterBase{
    	
        $Computerlist = Get-Content C:\Powershell\PrinterBase\ComputerList.txt
        foreach -parallel -throttlelimit 10 ($Computer in $Computerlist){
        	inlinescript{
    			$props=@{
    				Status='Unavailablle'
    				HostName=$Using:Computer
    				HostIp=$null
    				HostPrefix=$null
    				HostUserName=$null
    				Printers=@()
    				CurrentTime= Get-Date
                }
            	if (test-connection -ComputerName $Using:Computer -count 1 -quiet){
    				$props.Status='Connected'
                	Try{
    					
                		$PrinterHost = Get-WMIObject -ComputerName $Using:Computer -class Win32_ComputerSystem -ErrorAction stop
    		            $props.HostUserName = $PrinterHost.UserName
    		            $NetworkInfo = Get-WmiObject -ComputerName $Using:Computer -Class Win32_NetworkAdapterConfiguration -Filter 'IPEnabled=True' -ErrorAction stop
    		            Foreach ($NetworkAdapter in $NetworkInfo){
    		                $NetworkAdapterCaption = $NetworkAdapter.Caption
    		            }
    
    			    $printers = Get-WmiObject -ComputerName $Using:Computer -class Win32_Printer -ErrorAction stop
                		    $props.Printers=foreach ($printer in $Printers){
    			        [pscustomobject]@{
    		                    PrinterCaption = $Printer.Name
    		                    PrinterDriverName = $Printer.DriverName
                    		}
                		    }
                    }
            	Catch{
    				$props.Status="$_"
            	}
            }
    		New-Object PsObject -Property $props
    	}
    }

    This will reduce resource usage on the local system dramatically and will be much faster.


    ¯\_(ツ)_/¯




    • Edited by jrv Monday, March 2, 2015 8:02 PM
    • Marked as answer by Sergey Vasiltsov Tuesday, March 3, 2015 6:31 AM
    Monday, March 2, 2015 8:00 PM
  • How can I add data to odject? like Add-Content? Pipeline? 

    I made previos version of this script with hashtable and Export-Csv Cmdlet

    $PrintHash = [ordered]@{ 'HostName'=$computer 'IP-address'=$PingInfo.IPV4Address.IPAddressToString 'Subnet'=$IPprefix.IPAddressToString 'UserName'=$PrinterHost.UserName 'Printer'=$Printer.Name 'Driver'=$Printer.DriverName 'DateTime'=$CurrentTime } $PrinterObj=New-Object -TypeName PSObject -Property $PrintHash

    $PrinterObj | Export-Csv C:\Printers.csv -Append

    But, It was very slow and had 1 process/flow only


    P.S. Sorry for my English

    Monday, March 2, 2015 8:51 PM