簡體   English   中英

使用 PSCommands 獲取進程 ID psexec

[英]Get process Id psexec using PSCommands

啟動 psexec 后獲取進程 ID 的后續操作

我想知道如何使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM