我创建了运行" Power Shell脚本脚本的函数"

时间:2015-11-16 04:43:42

标签: pipeline runspace psobject

我创建了运行" Power Shell脚本"的脚本的函数。 我使用Pipeline和Runspace运行脚本(例如:power shell get-service)并运行1.000.000次脚本“get-service” 我知道了: - 当运行1个脚本(1个管道和1个运行空间)时,应用程序的RAM大约为300MB,当运行完成时,ram大约为70MB - ## Heading ##当运行2,3,4脚本(2,3,4管道和2,3,...)然后ram的应用程序是如此高,它是泄漏内存,ram约1GB,...和> 2gb。 我从这个位置看到问题:当事件pipelineExecutor_OnDataReady进程时,ram在调用此函数时启动:ConvertToDataTable()

DataTable dtTable
    private void ConvertToDataTable(PSObject psObject, String host)
    {
    DataRow dr = dtTable.Rows.Add();
    foreach (PSPropertyInfo item in psObject.Properties)
    {                  
    string strvalue = string.Empty;
                   if (item.TypeNameOfValue != "System.Runtime.InteropServices.SafeHandle")
                   if (item.Value != null)
                   {                   
                        if (item.Value.GetType().FullName == "System.ServiceProcess.ServiceController[]")
                        {
                            ServiceController[] sController = (ServiceController[])item.Value;
                            foreach (ServiceController sCtrler in sController)
                            {
                                if (sCtrler.MachineName != ".")
                                strvalue += sCtrler.ServiceName + ", ";
                            }
                            if (strvalue.Length > 2)
                            strvalue = strvalue.Remove(strvalue.Length - 2);
                            `enter code here`strvalue = "{ " + strvalue + " }";
                        }
                        if (item.Value.GetType().BaseType.FullName == "System.Array")
                        {
                            var result = ((System.Collections.IEnumerable)item.Value).ToString();
                            strvalue = string.Join(", ", result);
                            if (!string.IsNullOrEmpty(strvalue))
                                strvalue = "{ " + strvalue + " }";
                        }
                        else
                            strvalue = item.Value.ToString();
                        if (selectedColsList.Contains(item.Name))                       
                                dr[item.Name] = strvalue;                                           
                    }
                }                           
          }
4 pipeline run 4 script with each script will run script 1000.000 times get-service and result of script from psoject will add into table, each table 100.000. I see when access to property of psoject then ram is up, if comment call ConvertToDataTable()function, ram is ok.
Please help me.
thanks
Hoang (hoang.cntt@gmail.com)

1 个答案:

答案 0 :(得分:0)

我看到的一个问题是您创建服务名称列表的方式:

ServiceController[] sController = (ServiceController[])item.Value;
foreach (ServiceController sCtrler in sController)
{
    if (sCtrler.MachineName != ".")
        strvalue += sCtrler.ServiceName + ", ";
}
if (strvalue.Length > 2)
    strvalue = strvalue.Remove(strvalue.Length - 2);
strvalue = "{ " + strvalue + " }";

每次将服务名称连接到strvalue时,您都要为垃圾收集器创建另一个中间string以进行清理。通常这可能不是什么大问题,但是因为你运行这个代码数百万次,肯定会加起来。另一种方法是使用StringBuilder代替:

ServiceController[] sController = (ServiceController[])item.Value;

if (sController.Length < 1)
    strvalue = string.Empty;
else
{
    StringBuilder serviceNamesBuilder = new StringBuilder();
    ServiceController sCtrler = sController[0];

    if (sCtrler.MachineName != ".")
        serviceNamesBuilder.Append(sCtrler.ServiceName);
    for (int i = 1; i < sController.Length; i++)
    {
        sCtrler = sController[i];

        if (sCtrler.MachineName != ".")
            StringBuilder.Append(", ").Append(sCtrler.ServiceName);
    }

    strvalue = serviceNamesBuilder.ToString();
}

另外,我发现你的大多数循环都涉及为strvalue构建值,但最后你可能会把这项工作扔掉。我会像这样重构你的循环,以避免计算一个没有被使用的值:

foreach (PSPropertyInfo item in psObject.Properties)
{
    if (item.TypeNameOfValue != "System.Runtime.InteropServices.SafeHandle"
        && item.Value != null
        && selectedColsList.Contains(item.Name)
    )
    {
        string strvalue;

        // Build value of strvalue...

        dr[item.Name] = strvalue;
    }
}