C# 在另一个用户下启动流程';国书

C# 在另一个用户下启动流程';国书,c#,windows,C#,Windows,我想用另一个用户名的凭据启动一个进程。 这就是我现在拥有的: /// <summary> /// Do actions under another username's credentials /// </summary> /// <param name="username">Username to inpersonate</param> /// <param n

我想用另一个用户名的凭据启动一个进程。 这就是我现在拥有的:

        /// <summary>
        /// Do actions under another username's credentials
        /// </summary>
        /// <param name="username">Username to inpersonate</param>
        /// <param name="domain">Domain/Machine</param>
        /// <param name="password">Password </param>
        public static void Action(string username,string domain, string password )
        {
            try
            {
                if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref hToken))
                {
                    if (DuplicateToken(hToken, 2, ref hTokenDuplicate))
                    {

                        WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);

                        WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();

                        // Check the identity but it could do any other action under given username credentials
                      try
                        {
                            ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
                            info.UseShellExecute = false;
                            info.RedirectStandardInput = true;
                            info.RedirectStandardError = true;
                            info.RedirectStandardOutput = true;
                            info.UserName = "dummy"; // see the link mentioned at the top
                            // Define the string value to assign to a new secure string.
                            char[] chars = { 'p', 'a', 's', 's','1','2','3','4','/' };
                            // Instantiate the secure string.
                            SecureString testString = new SecureString();
                            // Assign the character array to the secure string.
                            foreach (char ch in chars)
                                testString.AppendChar(ch);

                            info.Password = testString;

                            Process.Start(info);

                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Exception Occurred :{0},{1}",ex.Message, ex.StackTrace.ToString());
                        }

                        // Stop impersonating the user
                        impersonationContext.Undo();
                    }
                }
                // Free the tokens
                if (hToken != IntPtr.Zero) 
                    CloseHandle(hToken);
                if (hTokenDuplicate != IntPtr.Zero)
                    CloseHandle(hTokenDuplicate);

        }catch(Exception ex)
         {
             Console.WriteLine("Exception occurred. " + ex);
          }
答案是对的,我们得到了“哑巴”

我们可以让它变得更简单:

 public static void Run()
        {
            try
            {
                const string file = "cmd.exe";

                var sspw = new SecureString();

                foreach (var c in "pass1234/")
                    sspw.AppendChar(c);

                var proc = new Process();

                proc.StartInfo.UseShellExecute = false;

                proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(file);

                proc.StartInfo.FileName = Path.GetFileName(file);

                proc.StartInfo.Domain = "WIN08";
                proc.StartInfo.Arguments = "";
                proc.StartInfo.UserName = "dummy";
                proc.StartInfo.Password = sspw;
                proc.StartInfo.LoadUserProfile = false;
                proc.Start();
            }catch(Exception e)
            {
                Console.WriteLine(e);
             }

但是,我仍然有例外…

我认为您不需要登录用户并复制句柄。您只需在ProcessStartInfo对象中设置用户名、域和密码。如果我没记错的话,那是从.NET3.0开始提供的

编辑:


另外,有关更多信息,当您将用户名/域/密码提供给ProcessStartInfo:时,会发生以下情况:。拒绝访问的原因可能是您无权访问用户的桌面或WindowsStation。仅仅给LoginUser打电话是不够的。

对某些人来说这可能会很奇怪,我很抱歉,我是Linux开发者。。。 测试:

//
///类,该类处理另一个用户名凭据
/// 
类凭据
{
/// 
///运行方式使用的SecureString密码的构造函数
/// 
///普通密码
///SecureString密码
私有静态SecureString MakeSecureString(字符串文本)
{
SecureString secure=新的SecureString();
foreach(文本中的字符c)
{
安全的。附加字符(c);
}
安全返回;
}
/// 
///使用其他用户凭据运行应用程序。
///工作目录设置为C:\Windows\System32
/// 
///可执行文件的完整路径
///所需凭据的用户名
///所需凭据的密码
公共静态无效运行方式(字符串路径、字符串用户名、字符串密码)
{
尝试
{
ProcessStartInfo myProcess=新的ProcessStartInfo(路径);
myProcess.UserName=用户名;
myProcess.Password=MakeSecureString(密码);
myProcess.WorkingDirectory=@“C:\Windows\System32”;
myProcess.UseShellExecute=false;
Process.Start(myProcess);
}
捕获(Win32Exception w32E)
{
//这个过程没有开始。
控制台写入线(w32E);
}
}
}

您可能忘记设置只读安全字符串?我的方法很适合我:

Process proc = new Process
        {
            StartInfo =
            {
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                FileName = "cmd.exe",
                UserName = "user",
                Domain = "myDomain",
                Password = GetSecureString("Password"),
                Arguments = "/c ipconfig"                   
            }
        };
        proc.Start(); 
GetSecureString()函数:

public static SecureString GetSecureString(string str)
    {
        SecureString secureString = new SecureString();
        foreach (char ch in str)
        {
            secureString.AppendChar(ch);
        }
        secureString.MakeReadOnly();
        return secureString;
    }

您执行此应用程序的凭据是什么?管理员试图在标准用户下运行应用程序。您是否可以右键单击exe并选择“运行方式…”?是否有完整源代码示例的最终解决方案?
Process proc = new Process
        {
            StartInfo =
            {
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                FileName = "cmd.exe",
                UserName = "user",
                Domain = "myDomain",
                Password = GetSecureString("Password"),
                Arguments = "/c ipconfig"                   
            }
        };
        proc.Start(); 
public static SecureString GetSecureString(string str)
    {
        SecureString secureString = new SecureString();
        foreach (char ch in str)
        {
            secureString.AppendChar(ch);
        }
        secureString.MakeReadOnly();
        return secureString;
    }