问题描述
我想从C#应用程序中执行powershellscript。该脚本以特殊的UserContext执行。
I'm trying to execute a powershellscript from a c# application. The script has to be executed under a special usercontext.
我已经尝试了不同的场景有些工作有些不是:
I've tried different scenarios some are working some not:
1。从PowerShell中直接调用
我叫从中下正确usercredentials运行PS-控制台directely脚本。
I've called the script directely from a ps-console which is running under the correct usercredentials.
C:\Scripts\GroupNewGroup.ps1 1
结果:成功运行脚本
2。从C#控制台应用程序
我叫从中下正确usercredentials开始了C#consoleapplication脚本。
I've called the script from a c# consoleapplication which is started under the correct usercredentials.
code:
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();
}
}
结果:没有成功。和很多空阵的异常。
Result: No Success. And a lot of "Null-Array" exceptions.
3。从C#控制台应用程序 - code面imapersonating
()
我叫从中下正确usercredentials和code包含模拟开始了C#consoleapplication脚本。
I've called the script from a c# consoleapplication which is started under the correct usercredentials and the code contains impersonation.
code:
using (new Impersonator("Administrator2", "domain", "testPW"))
{
using (RunspaceInvoke invoker = new RunspaceInvoke())
{
invoker.Invoke("Set-ExecutionPolicy Unrestricted");
}
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();
}
}
}
结果:
- 术语GET-联系未被识别为cmdlet的名字,
函数,脚本文件或可操作的程序。检查的拼写
名称,或者是否包含路径,验证路径是正确的,
再试一次。 - 术语C:\\脚本\\ FunctionsObjects.ps1'无法识别的
命名cmdlet,函数,脚本文件或可操作的程序的。检查
名字的拼写,或者是否包含路径,验证
路径是否正确,然后重试。 - 没有管理单元已注册的Windows PowerShell版本2。
Microsoft.Office.Server,版本= 14.0.0.0,文化=中立,
公钥= 71e9bce111e9429c - System.DirectoryServices.AccountManagement,版本= 4.0.0.0,
文化=中性公钥= b77a5c561934e089 - 异常调用.ctor和1的说法(S):Web应用程序
在的http:// XXXX /网站/ TEST4 /
找不到。确认您
正确输入了网址。如果URL应该提供现有
内容时,系统管理员可能需要添加一个新的请求URL
映射到预期的应用。 - 您不能调用一个空值前pression的方法。不能索引
成空数组。
- The term 'Get-Contact' is not recognized as the name of a cmdlet,function, script file, or operable program. Check the spelling of thename, or if a path was included, verify that the path is correct andtry again.
- The term 'C:\Scripts\FunctionsObjects.ps1' is not recognized as thename of a cmdlet, function, script file, or operable program. Checkthe spelling of the name, or if a path was included, verify that thepath is correct and try again.
- No snap-ins have been registered for Windows PowerShell version 2.Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral,PublicKeyToken=71e9bce111e9429c
- System.DirectoryServices.AccountManagement, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089
- Exception calling ".ctor" with "1" argument(s): "The Web applicationat
http://XXXX/websites/Test4/
could not be found. Verify that youhave typed the URL correctly. If the URL should be serving existingcontent, the system administrator may need to add a new request URLmapping to the intended application." - You cannot call a method on a null-valued expression. Cannot indexinto a null array.
到现在为止也没有工作答案
有谁知道为什么有差异,如何解决这个问题?
Does anyone know why there are differences and how to solve the problem?
推荐答案
你试过设置ExecutionPolicy不受限制
using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
{
using (RunspaceInvoke invoker = new RunspaceInvoke())
{
invoker.Invoke("Set-ExecutionPolicy Unrestricted");
}
}
编辑:
找到这个小宝石...的
Found this little gem... http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User
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
}
/////////////////////////////////////////////////////////////////////////
}
这篇关于运行PowerShell的脚本从C#应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!