C#创建并启动新的进程

        在C#编程中,ProcessStartInfo是一个类,用于包含有关要启动的进程的信息。 它用于Process类的Start方法,以确定如何启动新的进程。

        ProcessStartInfo类的一些重要属性包括:

  • FileName:要运行的文件的名称,可含路径(绝对路径或相对路径)。
  • Arguments:传递给文件的命令行参数。
  • WorkingDirectory:工作目录的路径。
  • UseShellExecute:一个布尔值,确定是否使用操作系统外壳程序(shell)启动进程。
  • RedirectStandardInputRedirectStandardOutputRedirectStandardError:布尔值,确定是否重定向进程的标准输入、输出和错误流。
  • StandardOutputEncodingStandardErrorEncoding:用于读取进程的标准输出和错误的编码。
  • CreateNoWindow:一个布尔值,确定是否在新窗口中启动进程。
  • WindowStyle:窗口样式(最大化、最小化、隐藏等)。
  • LoadUserProfile:一个布尔值,确定是否加载用户的配置文件。
  • EnvironmentVariables:一个字符串字典,用于设置环境变量。
  • UserNamePasswordDomain:用于身份验证的凭据。

        一、简单示例:

string arg1 = "a", arg2 = "b";
string args = $@"{arg1} {arg2}";

ProcessStartInfo info = new ProcessStartInfo();
//指定exe文件
info.FileName = "D:\Test\Test.exe";
//传入参数,多个参数用英文空格隔开
info.Arguments = args;
//已管理员身份运行,可消除打开的确认弹窗
info.Verb = "runas";
//设置不在新窗口中启动新的进程
info.CreateNoWindow = true;
//不使用操作系统使用的shell启动进程
info.UseShellExecute = false;
//将输出信息重定向
info.RedirectStandardOutput = true;

Process pro = Process.Start(info);

        关于参数Arguments的说明:传入的是字符串类型,如果需要传入多个参数,请用英文空格隔开。同时被打开的exe程序需要修改Program.cs文件中的应用程序的入口点Main函数,用于接收传入的参数,这个过程会自动解析将参数用英文空格分隔成string数组,如下:

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    //调用WinForm的窗体有参构造函数
    Application.Run(new TestFrom(args));
}

/// <summary>
/// 有参构造函数
/// </summary>
/// <param name="args">ProcessStartInfo传入的参数</param>
public TestFrom(string[] args)
{
    InitializeComponent();
}

        二、使用指定的域账号打开exe程序

        UserName:用户域账号;

        Password:用户域账号的密码;

        Domain:域名。

        需要用到ShareTool共享工具类:用来登录

using System;
using System.Runtime.InteropServices;

namespace ShareToolClass
{
    public class ShareTool : IDisposable
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
            int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        // closes open handes returned by LogonUser       
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        extern static bool CloseHandle(IntPtr handle);

        [DllImport("Advapi32.DLL")]
        static extern bool ImpersonateLoggedOnUser(IntPtr hToken);

        [DllImport("Advapi32.DLL")]
        static extern bool RevertToSelf();
        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_LOGON_NEWCREDENTIALS = 9;
        const int LOGON32_LOGON_INTERACTIVE = 2;
        private bool disposed;

        public ShareTool(string username, string password, string ip)
        {
            // initialize tokens       
            IntPtr pExistingTokenHandle = new IntPtr(0);
            IntPtr pDuplicateTokenHandle = new IntPtr(0);

            try
            {
                // get handle to token       
                bool bImpersonated = LogonUser(username, ip, password,
                    LOGON32_LOGON_NEWCREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);

                if (bImpersonated)
                {
                    if (!ImpersonateLoggedOnUser(pExistingTokenHandle))
                    {
                        int nErrorCode = Marshal.GetLastWin32Error();
                        throw new Exception("ImpersonateLoggedOnUser error;Code=" + nErrorCode);
                    }
                }
                else
                {
                    int nErrorCode = Marshal.GetLastWin32Error();
                    throw new Exception("LogonUser error;Code=" + nErrorCode);
                }
            }
            finally
            {
                // close handle(s)       
                if (pExistingTokenHandle != IntPtr.Zero)
                    CloseHandle(pExistingTokenHandle);
                if (pDuplicateTokenHandle != IntPtr.Zero)
                    CloseHandle(pDuplicateTokenHandle);
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                RevertToSelf();
                disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
    }
}

        示例:

string user = "admin";
string userpsw = "123456";
string domain = "TestDomain";

using (ShareToolClass.ShareTool tool = new ShareTool.ShareTool(user, userpsw, domain))
{
    //保密文本
    SecureString pwd = new SecureString();
    foreach (char c in userpsw)
        pwd.AppendChar(c);

    //使用线程打开
    Thread t = new Thread(new ThreadStart(delegate
    {
        try
        {
            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = "D:\Test\Test.exe";
            
            info.UserName = user;//域账号
            info.Password = pwd;//密码
            info.Domain = domain;//域名

            //设置不在新窗口中启动新的进程
            info.CreateNoWindow = true;
            //不使用操作系统使用的shell启动进程
            info.UseShellExecute = false;
            //将输出信息重定向
            //info.RedirectStandardOutput = true;
            Process pro = Process.Start(info);
        }
        catch (Exception ex)
        {
            PubLibrary.WriteErrLog("打开出错:" + ex.ToString());
        }
    }));
    t.Start();
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
    前段时间有点空闲就自学了一下c#,以前也没有学过任何编程,只是对电脑操作还是很熟,会一些应用类软件,计算机相关的英文能看懂点。     看了10多节的视频教程,因为基础太差,前面学的东西老会忘,光这样学也没有多大的意义,于是就找个程序一边练一遍学。网上一搜,不知道怎么的就找了一个进程守护的软件,别人提供的源码,好像是在pudn下的,一测试可以运行,就是觉得不太适合自己的操作习惯。于是就开始改造了。牺牲了一周的业余时间,终于完成,在这分享一下,如果有需要的可以自行再改造,版权归原作者,至于我修改的地方,可以任意改,任意传播,没有版权。附上源码,包含源程序的和我改造的部分。只是希望能给像我这样的不会编程的一类朋友一点启示,只要努力,就能达到自己想要的效果。现成的东西,不一定是适合自己的,要想拿来适合自己,也许就需要付出努力。附上修改的说明及截图。没有多大的技术含量,对于会编程的人,也许2下就搞定了,对于不会编程的人,如果刚好需要这样的软件,那就可以偷懒了。测试了win7(x86x64),win8(x86),win10(x64),其他系统没有测试,如果不能运行请自行解决,vs2010编译的,dedug和Release都有编译好的版本。     修改及使用说明 1、配置文件precesses.xml,里面的进程名不要有扩展名,一定要注意。 2、配置文件中的mutl为是否多开,linecount为多开时的限制数,jgtime为守护的周期。 3、配置文件中增linecount为相同程序限制数(如果程序本身不允许多开那就没办法),可以给每个程序配置不同限制数,但是界面上修改时,只能修改成一样。读取配置后显示最大的那个值在界面上. 4、配置文件中增jgtime为循环时间,所有程序使用相同的循环时间,配置时可以配置成不一样的,实际没有意义,因只调用了一个定时器,但默认显示并使用最大的那个时间。 5、增加托盘图标提示及菜单 6、取消任务栏图标显示 7、默认启动最小化,如果没有任务栏,只能通过进程结束,固定了窗口不能改变大小 8、主界面增加了退出按钮、清空日志按钮 9、主界面点击关闭按钮后,自动最小化 10、增加进程调用的部分日志显示框,主要是调试方便,日志超过30行自动清屏,未保存,可修改代码关掉或不显示,evertlog目录下多余的日志关掉了,仍然有小部分日志,,如有必要自行在代码中关掉即可。 11、底部增加多开线程输入框及保存按钮,多开进程数大于1小于100,100为无限制模式。增加间隔时间输入框及保存按钮,间隔时间大于等于500,小于等于1000000000之间的整数(毫秒),没有限制再配置中添加应用程序的个数。 12、开始监控及停止监控互锁显示。 13、默认优先读取配置中的最大的间隔时间,如果配置错误会自动初始化为23秒。 14、其他界面布局微调 15、代码自己随意修改太拖沓,会编程的可以进行大量优化。 16、没有做自守护,可以考虑用任务计划写个批处理,再守护它。win764位以上系统,防任务管理栏结束有难度哦。 17、我用的是系统自带的自定义shell启动它,还是很稳定,23秒是我测试的需要,自己可在代码中修改,我修改的地方还是加了不少注释的。 18、调用有些程序可能无法启动的情况,和本软件无关,可能是路径问题,有些程序不允许改变路径运行等,可自己在命令行下测试调用的软件是否运行,我遇到过类似的软件,加入环境变量也不行,只能在同一个目录下。 19、加入配置文件错误的一些纠缠机制(linecount没有会自动创建并赋值3,值为"",也会自动修复),当然错误的情况不够完善,只考虑了没有整项或者值为""的情况,其他情况没有处理,如果遇到其他情况只会导致程序停止,不能对配置的自修复而已,只针对linecout和jgtime做了处理,jgtime整项如果没有,会自动修复为23000毫秒。程序自修复配置文件后,会自动运行,如遇不能修复的问题根据catch出的问题,自行修改源码,加入到出错情况的处理。 20、只测试了win7x86x64,win8x86,win10x64,精简系统可能无法运行,自己测试了一个5年前的极度精简的win7系统,无法运行没有任何提示,也没有去验证到底是什么问题,但大多数精简系统都行。 21、增加鼠标悬停帮助提示,提示框可能有拖影的情况,自行修改源码中的时间参数,也可改用另一种呈现方式不会拖影,源码中有,就是没有那么好看,鼠标悬停提示有点耗cpu资源。 22、双击进程框列出的需要守护监控的进程,可以查看该进程更多详细信息。 23、配置文件中路径,一定要注意用\\表示,比如 d:\\bitboy\\bitboy.exe  还要有扩展名,name中的进程名不能有扩展名,否则找不到程序,不区分大小写。 24、本软件运行后,会自动启动配置程序路径下的软件,如果该软件不存在,则自动停止监控。所有多余的配置要自行删除,xml文件中不要有注释,没对注释做处理。 25、加入开机自启动选择项,保存到注册表中,加入了默认以管理员身份运行,解决配置文件不在system32下,开机启动找不到配置文件的问题。 26、没有对本程序做单一启动的限制,如果需要只运行一个实例,重编译主程序中注释掉的一部分代码。对多线程运行的程序,建议设置linecount为100,否则会杀死多余的线程,一个循环周期杀一个,线程数量固定不变的可在配置中设置相同的linecount数,这样能达到守护的目的。 27、加了开机启动参数的支持,在配置文件中路径后用英文的逗号作分隔,前面的是路径,后面的是启动参数。 28、支持对多线程运行程序的退出守护,配置文件中,将linecount设置为100,并且要启用多开。当linecount配置为100后,不允许在界面上修改,只能手动打开配置文件修改。启动后检查进程如果没有运行,就运行一次,如果已经存在了则不处理,因为有些程序,要开启很多个线程运行,只有等所有进程都退出之后,才会启动一次守护的进程,之后又会交给程序自适应。 29、增加循环启动时间次数的累计显示,和所有程序累计启动次数不一样,这个指的是定时器执行的次数,不管是否启动了守护的程序,这个周期都是累加,可能没多大意义,另外那个是程序启动一次才加一次。 30、防止任务管理栏结束,甚至采用服务方式启动等,对于我来说太难了,服务启动又带ui交互,好像涉及到session0穿透的问题,能力有限,没有精力搞了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值