I have a script from here, this is the job :
function CaptureWeight {
Start-Job -Name WeightLog -ScriptBlock {
filter timestamp {
$sw.WriteLine("$(Get-Date -Format MM/dd/yyyy_HH:mm:ss) $_")
}
try {
$sw = [System.IO.StreamWriter]::new("$using:LogDir\$FileName$(Get-Date -f MM-dd-yyyy).txt")
& "$using:PlinkDir\plink.exe" -telnet $using:SerialIP -P $using:SerialPort | TimeStamp
}
finally {
$sw.ForEach('Flush')
$sw.ForEach('Dispose')
}
}
}
I'd like to get his to run against a list of IP addresses while also having a name associated with the IP to set the file name for each file. I was thinking something like $Name = Myfilename
and $name.IP = 1.1.1.1
and using those in place of $FileName and $SerialIP, but have yet to be able get anything close to working or find an example close enough to what I'm trying for.
Thanks
CodePudding user response:
Here is one way you could do it with a hash table as Theo mentioned in his helpful comment. Be aware that Jobs don't have a Threshold / ThrottleLimit parameter as opposed to Start-ThreadJob
or ForEach-Object -Parallel
since jobs run in a different process as you have already commented instead of instances / runspaces, there is no built-in way to control how many Jobs can run at the same time. If you wish have control over this you would need to code it yourself.
# define IPs as Key and FileName as Value
$lookup = @{
'1.2.3.4' = 'FileNameForThisIP'
'192.168.1.15' = 'AnotherFileNameForTHatIP'
}
# path to directory executable
$plink = 'path\to\plinkdirectory'
# path to log directory
$LogDir = 'path\to\logDirectory'
# serial port
$serialport = 123
$jobs = foreach($i in $lookup.GetEnumerator()) {
Start-Job -Name WeightLog -ScriptBlock {
filter timestamp {
$sw.WriteLine("$(Get-Date -Format MM/dd/yyyy_HH:mm:ss) $_")
}
try {
$path = Join-Path $using:LogDir -ChildPath ('{0}{1}.txt' -f $using:i.Value, (Get-Date -f MM-dd-yyyy))
$sw = [System.IO.StreamWriter]::new($path)
$sw.AutoFlush = $true
& "$using:plink\plink.exe" -telnet $using:i.Key -P $using:serialPort | TimeStamp
}
finally {
$sw.ForEach('Dispose')
}
}
}
$jobs | Receive-Job -AutoRemoveJob -Wait
The other alternative to the hash table could be to use a Csv (either from a file with Import-Csv
or hardcoded with ConvertFrom-Csv
).
CodePudding user response:
Adding here another alternative to my previous answer, using a RunspacePool
instance which has built-in a way of concurrency and enqueuing.
using namespace System.Management.Automation.Runspaces
try {
# define number of threads that can run at the same time
$threads = 10
# define IPs as Key and FileName as Value
$lookup = @{
'1.2.3.4' = 'FileNameForThisIP'
'192.168.1.15' = 'AnotherFileNameForTHatIP'
}
# path to directory executable
$plink = 'path\to\plinkdirectory\'
# path to log directory
$LogDir = 'path\to\logDirectory'
# serial port
$port = 123
# session variables that will be intialized with the runspaces
$ssPlink = [SessionStateVariableEntry]::new('plink', $plink, '')
$ssLogDir = [SessionStateVariableEntry]::new('logDir', $LogDir, '')
$ssPort = [SessionStateVariableEntry]::new('serialport', $port, '')
$rspool = [runspacefactory]::CreateRunspacePool([initialsessionstate]::CreateDefault2())
$rspool.ApartmentState = 'STA'
$rspool.ThreadOptions = 'ReuseThread'
$null = $rspool.SetMinRunspaces(1)
$null = $rspool.SetMaxRunspaces($threads)
$rspool.InitialSessionState.Variables.Add($ssPlink)
$rspool.InitialSessionState.Variables.Add($ssLogDir)
$rspool.InitialSessionState.Variables.Add($ssPort)
$rspool.Open()
$rs = foreach($i in $lookup.GetEnumerator()) {
$ps = [powershell]::Create().AddScript({
param($pair)
filter timestamp {
$sw.WriteLine("$(Get-Date -Format MM/dd/yyyy_HH:mm:ss) $_")
}
try {
$path = Join-Path $LogDir -ChildPath ('{0}{1}.txt' -f $pair.Value, (Get-Date -f MM-dd-yyyy))
$sw = [System.IO.StreamWriter]::new($path)
$sw.AutoFlush = $true
& "$plink\plink.exe" -telnet $pair.Key -P $serialPort | TimeStamp
}
finally {
$sw.ForEach('Dispose')
}
}).AddParameter('pair', $i)
$ps.RunspacePool = $rspool
[pscustomobject]@{
Instance = $ps
AsyncResult = $ps.BeginInvoke()
}
}
foreach($r in $rs) {
$r.Instance.EndInvoke($r.AsyncResult)
}
}
finally {
$rs.foreach('Clear')
$rspool.foreach('Dispose')
}