Memory leak using Powershell remote calls in C #

I have a Windows service that makes a lot of exchange remote calls to get server information. I noticed that the time spent on memory usage starts to increase until a memory exception is thrown. I searched, and it looks like there is a known memory leak in System.Management.Automation that does not destroy all the memory created by Runspace when calling the close and / or dispose method. I looked at a post that suggested using CreateOutOfProcessRunspace for RunspaceFactory , but was not sure how to use it.

Here is how the problem can be reproduced: ( System.Management.Automation dll link)

 for (int i = 0; i < 1000; i++) { var runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); runspace.Close(); runspace.Dispose(); } 

If you run this code, you will see how the memory size increases. Due to the requirements, opening the connection as much as possible is not a good solution.

Do you know how I can fix this problem even using the CreateOutOfProcessRunspace method for RunspaceFactory or how to properly manage the memory?

Thanks in advance

EDIT

I used V3 and changed the creation of the space space to use the CreateRunspacePool method and it looks like the leak has disappeared. Many thanks for your help!

+8
c # memory memory-leaks powershell runspace
source share
2 answers

I see the problem in PS v3.0, but not in PS v2.0. Here is the code that I use to see this (all examples are in PowerShell):

 for() { $runspace = [runspacefactory]::CreateRunspace() $runspace.Open() $runspace.Close() $p = Get-Process -Id $PID '{0} {1}' -f $p.Handles, ($p.PrivateMemorySize / 1mb) } 

Pens and memory seem to leak in version 3.0 in the code above.

Since v2.0 does not have this problem, one possible workaround is to start the service using PS v2.0, i.e. PowerShell.exe -Version 2.0 .

If this is not possible, I can come up with two more workarounds. One of them is not for creating spaces directly, but use [powershell] instead. For example, this code does not show a leak in version 3.0:

 for() { $ps = [powershell]::Create() $p = $ps.AddCommand('Get-Process').AddParameter('Id', $PID).Invoke() '{0} {1}' -f $p.Handles, ($p.PrivateMemorySize / 1mb) $ps.Dispose() } 

Another workaround, if applicable, could be to use [runspacefactory]::CreateRunspacePool() . This method also does not show Leak:

 $rs = [runspacefactory]::CreateRunspacePool() $rs.Open() for() { $ps = [powershell]::Create() $ps.RunspacePool = $rs $p = $ps.AddCommand('Get-Process').AddParameter('Id', $PID).Invoke() '{0} {1}' -f $p.Handles, ($p.PrivateMemorySize / 1mb) $ps.Dispose() } #$rs.Close() # just a reminder, it not called here due to the infinite loop 

The latter also works much faster because the space bar repeats the use.

+4
source share

I also ran into the same problem when I used v1 of System.Management.Automation . But the problem was solved using v3 of System.Management.Automation and changing the code to use the CreateOutOfProcessRunspace Method

Here is the code

  using (PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(4, 0), null, null, false)) { using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance)) { runspace.Open(); using (PowerShell powerShellInstance = PowerShell.Create()) { powerShellInstance.Runspace = runspace; var filePath = GetScriptFullName(powerShellScriptType); powerShellInstance.Commands.AddScript(File.ReadAllText(filePath)); var includeScript = GetIncludeScript(); powerShellInstance.AddParameters(new List<string> { userName, plainPassword, includeScript }); Collection<PSObject> psOutput = powerShellInstance.Invoke(); // check the other output streams (for example, the error stream) if (powerShellInstance.Streams.Error.Count > 0) { // error records were written to the error stream. // do something with the items found. var exceptions = ""; foreach (var error in powerShellInstance.Streams.Error) { exceptions += error.Exception + "\n"; } throw new InvalidPowerShellStateException(exceptions); } return psOutput; } } } 
+3
source share

All Articles