从C#应用程序运行PowerShell脚本
我正在尝试从c#应用程序执行PowerShell脚本。脚本必须在特殊的用户上下文下执行 我尝试过不同的方案,有些有效,有些无效: 1。来自PowerShell的直接呼叫 我直接从ps控制台调用了该脚本,该控制台在正确的用户凭据下运行从C#应用程序运行PowerShell脚本,c#,c#-4.0,powershell,console-application,C#,C# 4.0,Powershell,Console Application,我正在尝试从c#应用程序执行PowerShell脚本。脚本必须在特殊的用户上下文下执行 我尝试过不同的方案,有些有效,有些无效: 1。来自PowerShell的直接呼叫 我直接从ps控制台调用了该脚本,该控制台在正确的用户凭据下运行 C:\Scripts\GroupNewGroup.ps1 1 结果:成功运行脚本 2。从c#控制台应用程序 我从一个c#控制台应用程序调用了该脚本,该应用程序是在正确的用户凭据下启动的 C:\Scripts\GroupNewGroup.ps1 1 代码: st
C:\Scripts\GroupNewGroup.ps1 1
结果:成功运行脚本
2。从c#控制台应用程序
我从一个c#控制台应用程序调用了该脚本,该应用程序是在正确的用户凭据下启动的
C:\Scripts\GroupNewGroup.ps1 1
代码:
string cmdArg = "C:\\Scripts\\GroupNewGroup.ps1 1"
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.ApartmentState = System.Threading.ApartmentState.STA;
runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
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();
runspace.Close();
if (error.Count >= 1)
{
string errors = "";
foreach (var Error in error)
{
errors = errors + " " + Error.ToString();
}
}
string cmdArg=“C:\\Scripts\\GroupNewGroup.ps1”
Runspace Runspace=RunspaceFactory.CreateRunspace();
runspace.ApartmentState=System.Threading.ApartmentState.STA;
runspace.ThreadOptions=PSThreadOptions.UseCurrentThread;
Open();
Pipeline Pipeline=runspace.CreatePipeline();
pipeline.Commands.AddScript(cmdArg);
pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error,PipelineResultTypes.Output);
收集结果=pipeline.Invoke();
var error=pipeline.error.ReadToEnd();
runspace.Close();
如果(error.Count>=1)
{
字符串错误=”;
foreach(var错误中的错误)
{
errors=errors+“”+Error.ToString();
}
}
结果:没有成功。还有很多“空数组”异常
3。从c#控制台应用程序-代码端模拟
()
我从一个c#consoleapplication调用了该脚本,该应用程序是在正确的用户凭据下启动的,代码包含模拟
代码:
使用(新的模拟程序(“管理员2”、“域”、“测试程序”))
{
使用(RunspaceInvoke invoker=new RunspaceInvoke())
{
invoker.Invoke(“设置不受限制的ExecutionPolicy”);
}
string cmdArg=“C:\\Scripts\\GroupNewGroup.ps1”;
Runspace Runspace=RunspaceFactory.CreateRunspace();
runspace.ApartmentState=System.Threading.ApartmentState.STA;
runspace.ThreadOptions=PSThreadOptions.UseCurrentThread;
Open();
Pipeline Pipeline=runspace.CreatePipeline();
pipeline.Commands.AddScript(cmdArg);
pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error,PipelineResultTypes.Output);
收集结果=pipeline.Invoke();
var error=pipeline.error.ReadToEnd();
runspace.Close();
如果(error.Count>=1)
{
字符串错误=”;
foreach(var错误中的错误)
{
errors=errors+“”+Error.ToString();
}
}
}
结果:
- 术语“Get Contact”未被识别为cmdlet的名称, 函数、脚本文件或可操作程序。检查单词的拼写 名称,或者如果包含路径,请验证该路径是否正确,并且 再试一次
- 术语“C:\Scripts\FunctionsObjects.ps1”不被识别为 cmdlet、函数、脚本文件或可操作程序的名称。检查 名称的拼写,或者如果包含路径,请验证 路径正确,请重试
- 尚未为Windows PowerShell版本2注册任何管理单元。 Microsoft.Office.Server,版本=14.0.0.0,区域性=中性, PublicKeyToken=71e9bce111e9429c
- System.DirectoryServices.AccountManagement,版本=4.0.0.0, 文化=中性,PublicKeyToken=b77a5c561934e089
- 使用“1”参数调用“.ctor”异常:“Web应用程序”
在
找不到。请确认 已正确键入URL。如果该URL应服务于现有 内容,系统管理员可能需要添加新的请求URL 映射到预期的应用程序。”http://XXXX/websites/Test4/
- 不能对空值表达式调用方法。无法索引 转换为空数组
有人知道为什么存在差异以及如何解决问题吗?您是否尝试过
将执行策略设置为不受限制的
using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
{
using (RunspaceInvoke invoker = new RunspaceInvoke())
{
invoker.Invoke("Set-ExecutionPolicy Unrestricted");
}
}
编辑:
找到这个小宝石
名称空间工具
{
#区域使用指令。
// ----------------------------------------------------------------------
使用制度;
使用System.Security.Principal;
使用System.Runtime.InteropServices;
使用系统组件模型;
// ----------------------------------------------------------------------
#端区
/////////////////////////////////////////////////////////////////////////
///
///模拟用户。允许在另一个用户下执行代码
///用户上下文。
///请注意,实例化模拟程序类的帐户
///需要设置“作为操作系统的一部分”权限。
///
///
///本课程基于Microsoft知识库中的信息
///文章http://support.microsoft.com/default.aspx?scid=kb;美国;Q306158
///
///将实例封装到using指令中,例如:
///
/// ...
///使用(新的模拟程序(“myUsername”、“myDomainname”、“myPassword”))
/// {
/// ...
///[在新上下文下执行的代码]
/// ...
/// }
/// ...
///
///请联系作者Uwe Keim(mailto:Uwe。keim@zeta-软件(de)
///关于这门课的问题。
///
公共类模拟程序:
可识别
{
#区域公共方法。
// ------------------------------------------------------------------
///
///构造函数。使用给定的凭据启动模拟。
///请注意,实例化模拟程序类的帐户
///需要设置“作为操作系统的一部分”权限。
///
///要充当的用户的名称。
///服务器的域名
namespace Tools
{
#region Using directives.
// ----------------------------------------------------------------------
using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
// ----------------------------------------------------------------------
#endregion
/////////////////////////////////////////////////////////////////////////
/// <summary>
/// Impersonation of a user. Allows to execute code under another
/// user context.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <remarks>
/// This class is based on the information in the Microsoft knowledge base
/// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
///
/// Encapsulate an instance into a using-directive like e.g.:
///
/// ...
/// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
/// {
/// ...
/// [code that executes under the new context]
/// ...
/// }
/// ...
///
/// Please contact the author Uwe Keim (mailto:uwe.keim@zeta-software.de)
/// for questions regarding this class.
/// </remarks>
public class Impersonator :
IDisposable
{
#region Public methods.
// ------------------------------------------------------------------
/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public Impersonator(
string userName,
string domainName,
string password )
{
ImpersonateValidUser( userName, domainName, password );
}
// ------------------------------------------------------------------
#endregion
#region IDisposable member.
// ------------------------------------------------------------------
public void Dispose()
{
UndoImpersonation();
}
// ------------------------------------------------------------------
#endregion
#region P/Invoke.
// ------------------------------------------------------------------
[DllImport("advapi32.dll", SetLastError=true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
// ------------------------------------------------------------------
#endregion
#region Private member.
// ------------------------------------------------------------------
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password )
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
try
{
if ( RevertToSelf() )
{
if ( LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token ) != 0 )
{
if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
{
tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
impersonationContext = tempWindowsIdentity.Impersonate();
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
finally
{
if ( token!= IntPtr.Zero )
{
CloseHandle( token );
}
if ( tokenDuplicate!=IntPtr.Zero )
{
CloseHandle( tokenDuplicate );
}
}
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if ( impersonationContext!=null )
{
impersonationContext.Undo();
}
}
private WindowsImpersonationContext impersonationContext = null;
// ------------------------------------------------------------------
#endregion
}
/////////////////////////////////////////////////////////////////////////
}
$username = 'domain\user'
$password = 'something'
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
invoker.Invoke("Set-ExecutionPolicy Unrestricted -Scope Process");