Posh-SSH
Posh-SSH copied to clipboard
The process cannot access the file .poshssh\hosts.json because it is being used by another process
When you run a lot of PowerShell objects concurrently which all use Posh-SSH to access different servers
` runThread = new Thread(() => { if (_stop) return; List<Thread> openThrs = new List<Thread>();
foreach (var psslog in PSSLogs)
{
if (_stop) break;
if (!cbOneByOne.Checked)
{
filterByLog = string.Empty;
Thread ot = new Thread(() =>
{
if (_stop) return;
PowerShell ps = PowerShell.Create();
try
{
PSCommand cmd = ps.Commands.AddScript(
scriptToRun.Script, true);
cmd.AddParameter("IP", psslog.Node.IP)
.AddParameter("Pass", psslog.Node.Password)
.AddParameter("Zip", binFile);
if (cbWithDataFile.Checked) {
cmd.AddParameter("DataZip", Path.GetFullPath($".\\GenerateData\\Data\\{psslog.Node.IP}.zip"));
}
cmd.AddParameter("ErrorAction", "Stop")
.AddParameter("Verbose");
ps.Runspace.SessionStateProxy.SetVariable("ErrorActionPreference", "stop");
psslog.Ps = ps;
ps.Streams.Error.DataAdded += Error_DataAdded;
ps.Streams.Verbose.DataAdded += Verbose_DataAdded;
ps.Streams.Progress.DataAdded += Progress_DataAdded;
ps.Streams.Warning.DataAdded += Warning_DataAdded;
ps.Streams.Information.DataAdded += Information_DataAdded;
ps.Streams.Error.EnumeratorNeverBlocks = true;
ps.Streams.Verbose.EnumeratorNeverBlocks = true;
ps.Streams.Progress.EnumeratorNeverBlocks = true;
ps.Streams.Debug.EnumeratorNeverBlocks = true;
ps.Streams.Information.EnumeratorNeverBlocks = true;
ps.Streams.Warning.EnumeratorNeverBlocks = true;
ps.Invoke(null, psslog.psObjects);
}
catch (Exception ex)
{
}
finally
{
ps.Streams.Error.DataAdded -= Error_DataAdded;
ps.Streams.Verbose.DataAdded -= Verbose_DataAdded;
ps.Streams.Progress.DataAdded -= Progress_DataAdded;
ps.Streams.Warning.DataAdded -= Warning_DataAdded;
ps.Streams.Information.DataAdded -= Information_DataAdded;
ps.Dispose();
}
});
ot.Start();
openThrs.Add(ot);
while (PSSLogs.Where(w => w.Ps != null && w.Ps.Streams.Progress.Count>0 && !w.Ps.Streams.Progress.Any(a=>a.PercentComplete>=100)).Count() >= delayMS)
{
Thread.Sleep(1000);
}
}
else
{
if (_stop) break;
PowerShell ps = PowerShell.Create();
try
{
ps.Commands.AddScript(
scriptToRun.Script, false);
ps.AddParameter("IP", psslog.Node.IP);
ps.AddParameter("Pass", psslog.Node.Password);
ps.AddParameter("Zip", binFile);
if (cbWithDataFile.Checked)
{
ps.AddParameter("DataZip", Path.GetFullPath($".\\GenerateData\\Data\\{psslog.Node.IP}.zip"));
}
ps.AddParameter("ErrorAction", "Stop");
ps.AddParameter("Verbose");
ps.Runspace.SessionStateProxy.SetVariable("ErrorActionPreference", "stop");
psslog.Ps = ps;
ps.Streams.Error.DataAdded += Error_DataAdded;
ps.Streams.Verbose.DataAdded += Verbose_DataAdded;
ps.Streams.Progress.DataAdded += Progress_DataAdded;
ps.Streams.Warning.DataAdded += Warning_DataAdded;
ps.Streams.Information.DataAdded += Information_DataAdded;
ps.Streams.Error.EnumeratorNeverBlocks = true;
ps.Streams.Verbose.EnumeratorNeverBlocks = true;
ps.Streams.Progress.EnumeratorNeverBlocks = true;
ps.Streams.Debug.EnumeratorNeverBlocks = true;
ps.Streams.Information.EnumeratorNeverBlocks = true;
ps.Streams.Warning.EnumeratorNeverBlocks = true;
ps.Invoke(null, psslog.psObjects);
}
catch (Exception ex)
{
}
finally
{
ps.Streams.Error.DataAdded -= Error_DataAdded;
ps.Streams.Verbose.DataAdded -= Verbose_DataAdded;
ps.Streams.Progress.DataAdded -= Progress_DataAdded;
ps.Streams.Warning.DataAdded -= Warning_DataAdded;
ps.Streams.Information.DataAdded -= Information_DataAdded;
ps.Dispose();
}
}
Thread.Sleep(scriptToRun.Name == "Install" ? 3000 : 250);
}
});
runThread.Start();`
System.Management.Automation.ActionPreferenceStopException: The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: The process cannot access the file 'C:\Users\user1\.poshssh\hosts.json' because it is being used by another process.
at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection1 input, PSDataCollection
1 output, PSInvocationSettings settings)
at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection
1 output, PSInvocationSettings settings)
at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, IList`1 output)
at Scripter.Form1.DownloadFile(PSSLog psslog) in E:\user1\Projects\Scripter\Form1.cs:line 906
at Scripter.Form1.<>c__DisplayClass26_1.<btnRun_Click>b__1() in E:\user1\Projects\Scripter\Form1.cs:line 480
Need more context outside of pasting an error. The file seems locked is the only thing I can tell but no clue on what version of windows, what version of PS, version of module or how the command is being ran
Seems it like a #457 problem.
Race condition still exists when writing concurrently because FileStream
with Share.Read
do not try to wait on fail.
I don't know if some work is needed or if a workaround is enough.
@darkoperator simplified version of code added to the original post. ( I thought devs know how, when and why their module uses its own .poshssh\hosts.json file and thus it would be obviouse. )
@okarpov, You, of course, also can look at issue above, the code of the module and draw conclusions :)
Hint: pre-populate hosts.json
with keys before using it so it's never written to while your code is running. Or use one-time in memory key storage if you don't care about keys.
As a dev it is the minimum I expect in a proper issue is to provide context with details on how to reproduce :)
Not part of the current problem but something you might hit is this issue with the library https://github.com/sshnet/SSH.NET/pull/844 for a very long time there has been many issues in the library with threading that have not been resolved.