[英]Get process Id psexec using PSCommands
我想知道如何使用PSCommand 和 PowerShell獲得問題的答案。
我的深度不足,需要一些幫助。 這是我最初想到的翻譯答案,是我失敗的嘗試。
private int GetRemoteProcessId()
{
string remoteFilename = "ExampleBatfile.bat";
string remoteDirectory = "C:\\ExampleDirectory";
string remoteUsername = "ExampleUsername";
string remotePassword = "ExamplePassword";
string remoteIp = "ExampleIP";
PowerShell ps = PowerShell.Create()
.AddScript($"psexec.exe \\{remoteIp} -accepteula -u {remoteUsername} -p {remotePassword} -s -i -d - w {remoteDirectory} {remoteFilename}" )
.AddCommand( "Select-String" ).AddParameter( "process ID (\\d+)" )
.AddCommand( "ForEach-Object" ).AddParameter( "{$_.Matches.Groups[1].Value}" );
Collection<PSObject> results = ps.Invoke();
int remoteProcessId = ( int )results.First().BaseObject;
return remoteProcessId;
}
我想要的只是在啟動后使用 psexec 從遠程進程獲取進程 ID(與回答的問題相同) - 但通過 C# PSCommands。
最后,我意識到 psexec 進程將進程 id 輸出到控制台。 我最終將 psexec 進程的輸出轉儲到臨時文件並解析提到的進程 ID。
我相信有比這更好/更安全的方法,但它有效!
/// <summary>
/// Creates a path to a unqiue-guid-named .txt file under the <see cref="Path.GetTempPath"/> directory. This does not create the file.
/// </summary>
/// <returns>Path.</returns>
public static string CreateTempGuidTxtFilename()
{
return string.Format(
"{0}.txt",
Path.Combine(
Path.GetTempPath(),
Guid.NewGuid().ToString().Replace( '-', '_' ) ) );
}
/// <summary>
/// Attempt to gather the process id for from a remote process start.
/// </summary>
/// <param name="info">Process info.</param>
/// <param name="ip">Remote machine ip.</param>
/// <returns>Process ID if it was successfully found.</returns>
private int? GetRemoteProcessStartId( ProcessStartInfo info, string ip )
{
// Declare no process id.
int? processId = null;
// We are going to start the process and feed the output into a generated .txt file with the given args.
string processInfoTempGuidPath = CreateTempGuidTxtFilename();
info.Arguments = string.Format( "{0} > {1} 2>&1 &", info.Arguments, processInfoTempGuidPath );
// Right, here we go!
Process psexecProcess = null;
try
{
// Start the process and wait for it to exit!
psexecProcess = Process.Start( info );
psexecProcess?.WaitForExit();
// Now we have exited, we can safely read the generated txt file and search the output.
// We are attempting to parse the output to find the process ID which was remotely launched
// since psexec displays this as standard output.
processId = TryParsePsexecLinesForProcessId( ip, File.ReadAllLines( processInfoTempGuidPath ) );
}
catch
{
// Any exception and we will try to kill our process.
processId = null;
psexecProcess?.Kill();
}
finally
{
// We finally want to delete the generated .txt file.
// It may have been created even on a failed process, so be safe!
if ( File.Exists( processInfoTempGuidPath ) )
{
File.Delete( processInfoTempGuidPath );
}
psexecProcess?.Close();
}
// Return the process id which may or may not be found.
return processId;
}
/// <summary>
/// Attempt to retrieve the process id from an output of text.
/// </summary>
/// <param name="ip">Machine address.</param>
/// <param name="output">Output.</param>
/// <returns>Process ID if it was parsed successfully.</returns>
public static int? TryParsePsexecLinesForProcessId(string ip, params string[] output)
{
// Get the queryable string for the line of psexec stream output which contains the remotely started process id.
string queryId = string.Format( "started on {0} with process ID", ip );
// Once we have found the line containing the process id query string,
// we will reverse and clean it to read the beginning characters which should be the
// string representation of the remote process id but backwards.
string reversedQuery = string.Concat(
output.FirstOrDefault(
x => x.Contains(
queryId,
StringComparison.OrdinalIgnoreCase ) )
.TrimEnd( '.' ).Reverse() );
// Take while are parsing the integer, remeber to reverse again since we are backwards!
// On successfully reading characters, we are going to try and parse for and integer!
string idToParse = string.Concat( reversedQuery.TakeWhile( x => !char.IsWhiteSpace( x ) ).Reverse() );
if ( !string.IsNullOrEmpty( idToParse ) && int.TryParse( idToParse, out int remoteProcessId ) )
{
return remoteProcessId;
}
else
{
// Else we can't parse any informative message regarding process id.
return null;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.