最近在做一个使用powershell向SCVMM服务器发送创建虚拟机之类指令的,当出现一条指令执行失败后以后再也无法发送类似的指令。那条指令失败后Runspace关闭后,下次发送指令也还会检测Runspace的状态,如果关闭会重新打开。但SCVMM作业记录都没显示有收到这条指令。
public class PSHelper { public PowerShell ps = PowerShell.Create(); public PSCommand psc = new PSCommand(); public PSObject pss; public Runspace runspace ;//RunspaceFactory.CreateRunspace(); public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public PSHelper() { runspace = RunspaceFactory.CreateRunspace(); OpenRunspace(); } public void OpenRunspace() { if (runspace.RunspaceStateInfo.State.ToString().Equals("Closed")) { runspace = RunspaceFactory.CreateRunspace(); } if (runspace.RunspaceStateInfo.State.ToString().Equals("BeforeOpen")) { runspace.Open(); } } public void Close() { runspace.Close(); // ps.Dispose();//add by xiongww if (runspace.RunspaceStateInfo.State.ToString().Equals("Opened")) { runspace.Close(); } } public PSCredential GetPSCredential(string computername, string username, string password) { SecureString str = new SecureString(); foreach (char ch in password) { str.AppendChar(ch); } return new PSCredential(username, str); } public void InitPSSession(string computername, string username, string password) { SecureString str = new SecureString(); foreach (char ch in password) { str.AppendChar(ch); } PSCredential credential = new PSCredential(username, str); Hashtable htParameters = new Hashtable(); htParameters.Add("computername", computername); htParameters.Add("credential", credential); Collection<PSObject> collection = this.RunPowerShellLocal("new-pssession", htParameters); this.pss = collection[0]; } public Collection<PSObject> RunPowerShellRemote(string script) { Collection<PSObject> collection; (!runspace.RunspaceStateInfo.State.ToString().Equals("Closed")) //{ this.psc.Clear(); ScriptBlock block = ScriptBlock.Create(script); this.psc.AddCommand("invoke-command"); this.psc.AddParameter("scriptBlock", block); this.psc.AddParameter("session", this.pss); OpenRunspace(); this.ps.Commands = this.psc; this.ps.Runspace = runspace; collection = this.ps.Invoke(); return collection; } } }
上面是执行powershell的核心代码,失败以后再发送指令过去“collection”接受到的值都为空
我把问题再详细的说明一下:我在.net端拼成一个创建虚拟机的脚本,然后首先是要powershell注册SCVMM服务器端的凭据,再使用powershell来执行这段脚本。可能是脚本出了问题,虚拟机创建失败,powershell对象运行的RunSpace会关闭。 等重新配置脚本后,再打开Runspace,使用powershell执行脚本,这个指令就无法执行了。SCVMM端的日志也没有接受到这条指令的日志信息
建议更详细描述一下遇到的问题
已加上去了,麻烦看下
@乘热喝茶: powershell也没返回错误?
@dudu: powershell接受到返回结果,SCVMM也查不到记录
@乘热喝茶: 试试把
collection = this.ps.Invoke();
改为
try { collection = this.ps.Invoke(); } finally { Close(); }
@dudu:这算是底层的代码,他的上一层有异常处理的,如果powershell执行不成功或者异常,会关闭Runspace的
@乘热喝茶: 建议缩小一下问题的范围,究竟是PSHelper代码的问题,还是powershell脚本的问题
@dudu: 我测试这个BUG的时候,给虚拟机姓名取名如果带下划线,那么这个指令就执行不成功。第二次再改过来不带下划线,就会出现这个问题。如果第一次给虚拟机取名字不带下划线,就可以执行成功。脚本是没有问题的
@乘热喝茶: 我也帮不上忙了,祝你早日解决这个问题
@dudu: 谢谢你
用C#写PowerShell 没做过,你可以先写 PowerShell,如果成完成任务,是否可以用 C#代码直接调用 PowerShell文件呢?
那样更麻烦 我们需要执行的指令数有很多