更新
以下尝试的错误消息:
我看到来自TEST.EXE的此错误输出(在CMD行中以2>检索):
ERROR: Logon failure: unknown user name or bad password.
但是没有看到来自调用EXE的进程的任何错误
根据以下建议(我认为)尝试创建一个调用我需要的流程的流程:
public static void getProc()
{
SecureString ss = CreatePW();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "\"/C cd C:\\users\\user.name\\desktop & TEST\"")
{
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = @"C:\windows\system32",
Verb = "runas",
Domain = "DOMAIN",
UserName = "zzkillcitrix",
Password = ss
};
string asd = "";
Process proc = Process.Start(startInfo);
proc.OutputDataReceived += (x, y) => asd += y.Data;
proc.BeginOutputReadLine();
proc.WaitForExit();
}
其中TEST.EXE是以下内容的构建(将参数发送给CMD):
public static void getProc()
{
SecureString ss = CreatePW();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "Command_which_requires_user_authentication_goes_here")
{
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
};
Process proc = Process.Start(startInfo);
proc.OutputDataReceived += (x, y) => asd += y.Data;
proc.BeginOutputReadLine();
proc.WaitForExit();
}
双击运行TEST.exe时,我仍然看到CMD窗口。 运行上面(顶部方法)时,TEST.exe似乎没有运行,因为我没有看到消息框窗口。
这可能是因为用户凭据未传递给EXE文件。
我有一个使用以下ProcessStartInfo详细信息调用的进程:
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C tasklist /S " + server + " /FI \"SESSION eq " + sessID + "\" /FO CSV /NH")
{
WindowStyle = ProcessWindowStyle.Minimized,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = @"C:\windows\system32",
Verb = "runas",
Domain = "DOMAIN",
UserName = "zzkillcitrix",
Password = ss,
}
从MSDN我知道当以用户身份运行此类进程时,CreateNoWindow和WindowStyle属性不起作用。这包括设置WindowStyle = ProcessWindowStyle.Hidden。
因此,我试图通过声明以下内容来实现无控制台Process.Start:
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
然后像这样调用proc:
Process proc = Process.Start(startInfo);
var handle = proc.MainWindowHandle;
ShowWindow(handle, SW_HIDE);
proc.OutputDataReceived += (x, y) => procList.Add(y.Data);
proc.BeginOutputReadLine();
proc.WaitForExit();
当进程运行时,控制台窗口仍会短暂闪烁。我是否试图隐藏一个不被识别为控制台窗口的窗口句柄?
我也尝试过调用ShowWindow方法,通常是在程序开头,但控制台窗口仍然出现。
对此有任何指导意见。
答案 0 :(得分:1)
更改
WindowStyle = ProcessWindowStyle.Minimized
到
WindowStyle = ProcessWindowStyle.Hidden;
答案 1 :(得分:0)
执行此操作的唯一方法我可以发现实际工作是通过远程PowerShell会话以具有完全域访问权限的用户身份运行命令:
static class Ps
{
private const string RemoteHost = "ADMINSERVER.DOMAIN1.co.uk";
private static string _errors;
/// <summary>
/// Executes the given command over a remote powershell session
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static Collection<PSObject> RemoteCommand(string args)
{
SupportMi.Trace = $"Remote Command({args}) {{";
var script = BuildScript(args);
var results = Execute(script);
SupportMi.Trace = $"RES: {results[0]} ERR: {_errors} }}";
return results;
}
/// <summary>
/// Takes a complete script and executes it over a powershell Runspace. In this case it is being
/// sent to the server, and the results of the execution are checked for any errors.
/// </summary>
/// <param name="script"></param>
/// <returns></returns>
private static Collection<PSObject> Execute(string script)
{
var results = new Collection<PSObject>();
// Using a runspace
using (var runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
using (var pipeline = runspace.CreatePipeline())
{
pipeline.Commands.AddScript(script);
try
{
results = pipeline.Invoke();
var errors = pipeline.Error.Read(pipeline.Error.Count);
foreach (var error in errors)
{
_errors += error;
}
}
catch (Exception ex)
{
results.Add(new PSObject(ex.Message));
SupportMi.Trace = ex.Message;
}
}
}
return results;
}
/// <summary>
/// Takes a string argument to be sent to the remote powershell session and arranges it in the correct format,
/// ready to be sent to the server.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private static string BuildScript(string args)
{
// Build the script
var script = Creds() + Environment.NewLine +
$"Invoke-Command -session $sessions -ScriptBlock {{ {args} /U DOMAIN1\\adminusername /P adminpassword }}" + Environment.NewLine +
"Remove-PSSession -Session $sessions" + Environment.NewLine +
"exit";
return script;
}
/// <summary>
/// Returns the credentials for a remote PowerShell session in the form
/// of a few lines of PowerShell script.
/// </summary>
/// <returns></returns>
private static string Creds()
{
return "$pw = convertto-securestring -AsPlainText -Force -String \"adminpassword\"" + Environment.NewLine +
"$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist \"DOMAIN1\\adminusername\",$pw" + Environment.NewLine +
$"$sessions = New-PSSession -ComputerName {RemoteHost} -credential $cred";
}
}
因此,为了维护无控制台的操作,我们可以调用RemoteCommand
方法并传入我们想要发送的命令。 RemoteCommand
将首先使用BuildScript
和Creds
(针对管理员凭据)构建我们的查询/命令。
然后将其发送到Execute
方法,该方法创建一个新的PowerShell RunSpace
,可以运行该命令。
使用此方法的一些注意事项:
ADMINSERVER
)