Methods to start process in C# and powershell

private int StartProcess(SoftwareSvr swSvr, string workingDir)
{
    Process proc = new Process();
    proc.StartInfo.UseShellExecute = true;
    proc.StartInfo.WorkingDirectory = workingDir;
    proc.StartInfo.FileName = swSvr.Command;

    if (swSvr.Args != null && swSvr.Args.Any())
    {
        proc.StartInfo.Arguments = string.Join(' ', swSvr.Args);
    }

    bool started = proc.Start();

    if (started)
    {
        return proc.Id;
    }
    else
    {
        return -1;
    }
}
private int StartProcessByPs(SoftwareSvr swSvr, string workingDir)
{
    /*
     * 1. wmic process call create "cluster\GatewayServer.exe start -id 1", "c:\app\", 但wmic启动的进程中不使用系统的环境变量
     * 2. powershell -Command "try{$app = Start-Process -PassThru -FilePath \"cluster\GatewayServer.exe\" -WorkingDirectory \"C:\app\" -ArgumentList \"start -id 5\";echo $app.Id} catch {throw}"
     */
    Process proc = new Process();
    proc.StartInfo.WorkingDirectory = workingDir;
    proc.StartInfo.FileName = @"C:\windows\system32\cmd.exe";
    proc.StartInfo.RedirectStandardOutput = true;
    var psArgs = string.Empty;

    if (swSvr.Args != null && swSvr.Args.Any())
    {
        psArgs = " -ArgumentList \\\"{string.Join(' ', swSvr.Args)}\\\"";
    }

    var psCmd = $"/C powershell -Command \"try{{$app = Start-Process -PassThru -FilePath \\\"{swSvr.Command}\\\" -WorkingDirectory \\\"{workingDir}\\\"{psArgs};echo $app.Id}} catch {{throw}}\"";
    proc.StartInfo.Arguments = psCmd;
    proc.Start();
    proc.WaitForExit();
    var output = proc.StandardOutput.ReadToEnd();

    if (proc.ExitCode != 0)
    {
        _logger.LogWarning($"Failed to start process: {proc.StartInfo.Arguments}, output: {output}");
        return -1;
    }
    else
    {
        return int.Parse(output);
    }
}

In Powershell

$taskName = "DelayStartup";


$t = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(2);
$t.EndBoundary = (Get-Date).AddSeconds(60).ToString('s');
Register-ScheduledTask -Force -TaskName $taskName -Action (New-ScheduledTaskAction -Execute C:\test.bat) -Trigger $t -Principal (New-ScheduledTaskPrincipal -UserID \\\"NT AUTHORITY\\SYSTEM\\\" -LogonType ServiceAccount -RunLevel Highest) -Settings (New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter 00:00:01)";


$t = New-ScheduledTaskTrigger -Once -At (Get-Date).AddHours(24);
Register-ScheduledTask -Force -TaskName $taskName -Action (New-ScheduledTaskAction -Execute C:\test.bat) -Trigger $t -Principal (New-ScheduledTaskPrincipal -UserID \\\"NT AUTHORITY\\SYSTEM\\\" -LogonType ServiceAccount -RunLevel Highest);
Start-ScheduledTask -TaskName $taskName;
Start-Job -ScriptBlock { Start-Sleep -s 10; Unregister-ScheduledTask -Confirm -TaskName 'DelayStartup'";};


Register-ScheduledTask -Force -TaskName $taskName -User '\\ContainerAdmin' -Password 'AutoOps#1' -Action (New-ScheduledTaskAction -Execute C:\test.bat);
Start-ScheduledTask -TaskName $taskName";

Aggregate in Mongodb in C#

Filter record from collection “OperationSession”, sort by “WorldId” descending, then group by “WorldId”, then pick first record from each group, then sort result:

Way #1:

db.getCollection('OperationSession').aggregate(
[
  { "$match": {"ActivityId":74,"GameId":2109} },
  { "$sort":{ "CreateTime" : -1} },
  { "$group":
    { 
        _id:"$WorldId",
        SessionId:{"$first": "$_id" },
        GameId:{"$first": "$GameId" },
        WorldId:{"$first": "$WorldId" },
        ActivityId:{"$first": "$ActivityId" },
        Type:{"$first": "$Type" },
        Status:{"$first": "$Status" },
        ActivityStatus:{"$first": "$ActivityStatus" }
     }
   },
   { "$sort":{ "WorldId" : 1} },
   { "$skip": 20},
   { "$limit": 10}
  ]
)

 

Way #2:

db.OperationSession.aggregate()
      .match({"ActivityId":74,"GameId":2109})
      .sort({"CreateTime":-1})
      .group({
            "_id":"$WorldId",
            "SessionId":{"$first": "$_id" },
            "GameId":{"$first": "$GameId" },
            "WorldId":{"$first": "$WorldId" },
            "ActivityId":{"$first": "$ActivityId" },
            "Type":{"$first": "$Type" },
            "Status":{"$first": "$Status" },
            "ActivityStatus":{"$first": "$ActivityStatus" }
        })
      .sort({"WorldId":1})
      .skip(20)
      .limit(10)

 

In C#:

collection.Aggregate<DataEntity.OperationSession>()
                .Match(s => s.ActivityId == 74 && s.GameId == 2109)
                .SortByDescending(s => s.CreateTime)
                .Group(
                    s => s.WorldId,
                    s => new Interface.OperationSession
                    {
                        SessionId = s.Select(x => x.Id).First(),
                        GameId = s.Select(x => x.GameId).First(),
                        WorldId = s.Select(x => x.WorldId).First(),
                        ActivityId = s.Select(x => x.ActivityId).First(),
                        Type = s.Select(x => x.Type).First(),
                        Status = s.Select(x => x.Status).First(),
                        ActivityStatus = s.Select(x => x.ActivityStatus).First()
                    })
                .SortBy(s => s.WorldId)
                .Skip(20)
                .Limit(10).ToList();

C#中使用反射调用参数中包含Lambda表达式的方法

如下代码片断展示了怎样在C#中使用反射调用参数中包含Lambda表达式的方法: GetData(Expression<Func<ExampleEntity, bool>>), 以及根据条件动态选择无参和有参方法:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ReflectCallGenericMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Type typeService = assembly.GetTypes()
                .Where(t => t.IsClass && t.Name == "ExampleService").SingleOrDefault();
            Type typeEntity = assembly.GetTypes()
                .Where(t => t.IsClass && t.Name == "ExampleEntity").SingleOrDefault();

            ParameterExpression paramExp = Expression.Parameter(typeEntity);
            Expression expression = null;
            Type[] types = Type.EmptyTypes;
            object[] parameters = null;

            var condition = Console.ReadLine();

            if (condition.Length > 0)//如果需要过滤数据
            {
                Expression propExp = Expression.Property(paramExp, "ID");
                Expression constExp = Expression.Constant(3);
                expression = Expression.Equal(propExp, constExp);

                Type delegateType = typeof(Func<,>).MakeGenericType(typeEntity, typeof(bool));
                LambdaExpression lambda = Expression.Lambda(delegateType, expression, paramExp);
                types = new[] { lambda.GetType() };
                parameters = new[] { lambda };
            }

            MethodInfo methodGetInstance = typeService.GetMethod("GetInstance");
            MethodInfo methodGetData = typeService.GetMethod("GetData", types);
            
            var instanceService = methodGetInstance.Invoke(null, null);
            string result = methodGetData.Invoke(instanceService, parameters) as string;

            Console.WriteLine(result);
            Console.ReadLine();
        }
    }

    public class ExampleService
    {
        private static readonly Object _mutex = new Object();
        volatile static ExampleService _instance;

        public static ExampleService GetInstance()
        {
            if (_instance == null)
            {
                lock (_mutex)
                {
                    if (_instance == null)
                    {
                        _instance = new ExampleService();
                    }
                }
            }

            return _instance;
        }

        public string GetData()
        {
            return "无参方法被调用";
        }

        public string GetData(Expression<Func<ExampleEntity, bool>> lambda)
        {
            return "有参方法被调用";
        }

        public string GetGenericData<ExampleEntity>()
        {
            return "无参泛型方法被调用";
        }

        public string GetGenericData<ExampleEntity>(Expression<Func<ExampleEntity, bool>> lambda)
        {
            return "有参泛型方法被调用";
        }
    }

    public class ExampleEntity
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

但这种却不能用于有Generic Arguments的方法,如上面代码片断中的GetGenericData方法,有Generic Arguments只能通过GetMember方法迂回的解决,详细参见: https://blogs.msdn.microsoft.com/yirutang/2005/09/14/getmethod-limitation-regarding-generics/