在 C# 中使用不同的凭据调用远程 powershell 脚本

Posted

技术标签:

【中文标题】在 C# 中使用不同的凭据调用远程 powershell 脚本【英文标题】:calling remote powershell script with different credential in C# 【发布时间】:2013-05-08 05:12:31 【问题描述】:

我正在尝试在远程服务器中调用一个 powershell 脚本文件,该文件基本上获取一个参数并使用该参数创建一个共享驱动器。凭据都是正确的,但是每当我运行它时,它都会返回此错误:

当运行空间设置为使用当前线程时,调用设置中的单元状态必须匹配当前线程的状态

这与凭据有关,因为一旦我删除了凭据,它就可以在我的本地计算机上正常运行。 任何人都可以阐明这一点吗?谢谢,

以下是我的 C# 脚本:

PSCredential credential = new PSCredential(_exchangeUsername, password);

// Set exchange connection details
WSManConnectionInfo connectionInfo = new WSManConnectionInfo((new Uri(_exchangeConnectionUri)), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);

connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Default;
string cmdArg = @"\\servername\\c$\\scripts\\HomeDrive.ps1 "+userID;

using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))

    try
    
        runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
        runspace.ApartmentState = System.Threading.ApartmentState.STA;
        runspace.Open();

        Pipeline pipeline = runspace.CreatePipeline();
        pipeline.Commands.AddScript(cmdArg);
        pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
        Collection<PSObject> results = pipeline.Invoke();
        var error = pipeline.Error.ReadToEnd();
        // Check for powershell command errors
        if (error.Count > 0)
        
            throw new Exception(errorMessage.ToString());
        

        // Check for powershell command results
        if (results.Count <= 0)
        
            throw new Exception(String.Format("Error. No results after command invoked.", userID));
        
        runspace.Close();
    
    catch (Exception ex)
    
        runspace.Close();
        throw new ApplicationException(String.Format("Error ", userID), ex);
    

【问题讨论】:

它不喜欢runspace.ApartmentState = System.Threading.ApartmentState.STA,因为当前线程不是STA线程。您需要删除此行或删除其上方的行... 如果我删除任何一行,它会抛出错误“不支持指定方法” 它说不支持哪种方法? Collection 结果 = pipeline.Invoke(); 这条线似乎不被支持。如果我删除 connectionInfo 凭据,它似乎在我的本地机器上工作正常 【参考方案1】:

我认为您使用了错误的构造函数重载 WSManConnectionInfo。您可以在创建对象之后检查对象的 Credential 属性,但在传递它以创建运行空间之前。

这是我自己的代码中的一个 sn-p,它工作正常,我正在使用最冗长的构造函数(我认为)

#region create WSmanconnection
//Create the PowerShell Remoting WinRM WSMan connection object so we can connect to the remote machine, only using credentials if Not Implicitly negotiated.
var ci = new WSManConnectionInfo(
    useSSL, trueFQDN , port, appName, shellUri,
    (authenticationMechanism == AuthenticationMechanism.NegotiateWithImplicitCredential) ? null : credential)
    
        AuthenticationMechanism = authenticationMechanism,
        OpenTimeout = openTimeoutMinutes * 60 * 1000,
        OperationTimeout = operationTimeoutMinutes * 60 * 1000,
        IdleTimeout = idleTimeOut * 60 * 1000
    ;
#endregion

【讨论】:

以上是关于在 C# 中使用不同的凭据调用远程 powershell 脚本的主要内容,如果未能解决你的问题,请参考以下文章

Laravel:针对远程检查凭据的系统进行身份验证

将凭据添加到与本地系统帐户不同的帐户

使用安全凭据调用 SQL 命令

将 NTLM 凭据传递给远程 Web 服务

如何在 c# 应用程序中正确保护 api 凭据

从 C# 访问 Sharepoint 远程文件夹