MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.ObjectModel;7using System.ComponentModel;8using System.Diagnostics.CodeAnalysis;9using System.Globalization;10using System.Management;11using System.Management.Automation;12using System.Management.Automation.Internal;13using System.Management.Automation.Provider;14using System.Management.Automation.Remoting;15using System.Runtime.InteropServices;16using System.Security.AccessControl;17using System.Text;18using System.Threading;19 20using Microsoft.PowerShell.Commands.Internal;21 22using Dbg = System.Management.Automation;23 24namespace Microsoft.PowerShell.Commands25{26 #region Helper Classes27 28 /// <summary>29 /// Base class for all WMI helper classes. This is an abstract class30 /// and the helpers need to derive from this.31 /// </summary>32 internal abstract class AsyncCmdletHelper : IThrottleOperation33 {34 /// <summary>35 /// Exception raised internally when any method of this class36 /// is executed.37 /// </summary>38 internal Exception InternalException39 {40 get41 {42 return internalException;43 }44 }45 46 protected Exception internalException = null;47 }48 49 /// <summary>50 /// This class is responsible for creating WMI connection for getting objects and notifications51 /// from WMI asynchronously. This spawns a new thread to connect to WMI on remote machine.52 /// This allows the main thread to return faster and not blocked on network hops.53 /// </summary>54 internal class WmiAsyncCmdletHelper : AsyncCmdletHelper55 {56 /// <summary>57 /// Internal Constructor.58 /// </summary>59 /// <param name="childJob">Job associated with this operation.</param>60 /// <param name="wmiObject">Object associated with this operation.</param>61 /// <param name="computerName">Computer on which the operation is invoked.</param>62 /// <param name="results">Sink to get wmi objects.</param>63 internal WmiAsyncCmdletHelper(PSWmiChildJob childJob, Cmdlet wmiObject, string computerName, ManagementOperationObserver results)64 {65 _wmiObject = wmiObject;66 _computerName = computerName;67 _results = results;68 this.State = WmiState.NotStarted;69 _job = childJob;70 }71 72 /// <summary>73 /// Internal Constructor. This variant takes a count parameter that determines how many times74 /// the WMI command is executed.75 /// </summary>76 /// <param name="childJob">Job associated with this operation.</param>77 /// <param name="wmiObject">Object associated with this operation.</param>78 /// <param name="computerName">Computer on which the operation is invoked.</param>79 /// <param name="results">Sink to return wmi objects.</param>80 /// <param name="count">Number of times the WMI command is executed.</param>81 internal WmiAsyncCmdletHelper(PSWmiChildJob childJob, Cmdlet wmiObject, string computerName, ManagementOperationObserver results, int count)82 : this(childJob, wmiObject, computerName, results)83 {84 _cmdCount = count;85 }86 87 private string _computerName;88 internal event EventHandler<WmiJobStateEventArgs> WmiOperationState;89 internal event EventHandler<EventArgs> ShutdownComplete;90 private ManagementOperationObserver _results;91 private int _cmdCount = 1;92 private PSWmiChildJob _job;93 /// <summary>94 /// Current operation state.95 /// </summary>96 internal WmiState State97 {98 get { return _state; }99 100 set { _state = value; }101 }102 103 private WmiState _state;104 105 /// <summary>106 /// Cancel WMI connection.107 /// </summary>108 internal override void StopOperation()109 {110 _results.Cancel();111 _state = WmiState.Stopped;112 RaiseOperationCompleteEvent(null, OperationState.StopComplete);113 }114 /// <summary>115 /// Uses this.filter, this.wmiClass and this.property to retrieve the filter.116 /// </summary>117 private string GetWmiQueryString()118 {119 GetWmiObjectCommand getObject = (GetWmiObjectCommand)_wmiObject;120 StringBuilder returnValue = new StringBuilder("select ");121 returnValue.Append(string.Join(", ", getObject.Property));122 returnValue.Append(" from ");123 returnValue.Append(getObject.Class);124 if (!string.IsNullOrEmpty(getObject.Filter))125 {126 returnValue.Append(" where ");127 returnValue.Append(getObject.Filter);128 }129 130 return returnValue.ToString();131 }132 133 /// <summary>134 /// Do WMI connection by creating another thread based on type of request and return immediately.135 /// </summary>136 internal override void StartOperation()137 {138 Thread thread;139 if (_wmiObject.GetType() == typeof(GetWmiObjectCommand))140 {141 thread = new Thread(new ThreadStart(ConnectGetWMI));142 }143 else if (_wmiObject.GetType() == typeof(RemoveWmiObject))144 {145 thread = new Thread(new ThreadStart(ConnectRemoveWmi));146 }147 else if (_wmiObject is InvokeWmiMethod)148 {149 thread = new Thread(new ThreadStart(ConnectInvokeWmi));150 }151 else if (_wmiObject is SetWmiInstance)152 {153 thread = new Thread(new ThreadStart(ConnectSetWmi));154 }155 else156 {157 InvalidOperationException exception = new InvalidOperationException("This operation is not supported for this cmdlet.");158 internalException = exception;159 _state = WmiState.Failed;160 RaiseOperationCompleteEvent(null, OperationState.StopComplete);161 return;162 }163 164 thread.IsBackground = true;165 thread.SetApartmentState(ApartmentState.STA);166 thread.Start();167 }168 169 /// <summary>170 /// </summary>171 internal override event EventHandler<OperationStateEventArgs> OperationComplete;172 173 private Cmdlet _wmiObject;174 175 /// <summary>176 /// Raise operation completion event.177 /// </summary>178 internal void RaiseOperationCompleteEvent(EventArgs baseEventArgs, OperationState state)179 {180 OperationStateEventArgs operationStateEventArgs = new OperationStateEventArgs();181 operationStateEventArgs.OperationState = state;182 OperationComplete.SafeInvoke(this, operationStateEventArgs);183 }184 185 /// <summary>186 /// Raise WMI state changed event187 /// </summary>188 internal void RaiseWmiOperationState(EventArgs baseEventArgs, WmiState state)189 {190 WmiJobStateEventArgs wmiJobStateEventArgs = new WmiJobStateEventArgs();191 wmiJobStateEventArgs.WmiState = state;192 WmiOperationState.SafeInvoke(this, wmiJobStateEventArgs);193 }194 195 /// <summary>196 /// Do the actual connection to remote machine for Set-WMIInstance cmdlet and raise operation complete event.197 /// </summary>198 private void ConnectSetWmi()199 {200 SetWmiInstance setObject = (SetWmiInstance)_wmiObject;201 _state = WmiState.Running;202 RaiseWmiOperationState(null, WmiState.Running);203 if (setObject.InputObject != null)204 {205 ManagementObject mObj = null;206 try207 {208 PutOptions pOptions = new PutOptions();209 // Extra check210 if (setObject.InputObject.GetType() == typeof(ManagementClass))211 {212 // Check if Flag specified is CreateOnly or not213 if (setObject.flagSpecified && setObject.PutType != PutType.CreateOnly)214 {215 InvalidOperationException e = new InvalidOperationException("CreateOnlyFlagNotSpecifiedWithClassPath");216 internalException = e;217 _state = WmiState.Failed;218 RaiseOperationCompleteEvent(null, OperationState.StopComplete);219 return;220 }221 222 mObj = ((ManagementClass)setObject.InputObject).CreateInstance();223 setObject.PutType = PutType.CreateOnly;224 }225 else226 {227 // Check if Flag specified is Updateonly or UpdateOrCreateOnly or not228 if (setObject.flagSpecified)229 {230 if (!(setObject.PutType == PutType.UpdateOnly || setObject.PutType == PutType.UpdateOrCreate))231 {232 InvalidOperationException e = new InvalidOperationException("NonUpdateFlagSpecifiedWithInstancePath");233 internalException = e;234 _state = WmiState.Failed;235 RaiseOperationCompleteEvent(null, OperationState.StopComplete);236 return;237 }238 }239 else240 {241 setObject.PutType = PutType.UpdateOrCreate;242 }243 244 mObj = (ManagementObject)setObject.InputObject.Clone();245 }246 247 if (setObject.Arguments != null)248 {249 IDictionaryEnumerator en = setObject.Arguments.GetEnumerator();250 while (en.MoveNext())251 {252 mObj[en.Key as string] = en.Value;253 }254 }255 256 pOptions.Type = setObject.PutType;257 if (mObj != null)258 {259 mObj.Put(_results, pOptions);260 }261 else262 {263 InvalidOperationException exp = new InvalidOperationException();264 internalException = exp;265 _state = WmiState.Failed;266 RaiseOperationCompleteEvent(null, OperationState.StopComplete);267 }268 }269 catch (ManagementException e)270 {271 internalException = e;272 _state = WmiState.Failed;273 RaiseOperationCompleteEvent(null, OperationState.StopComplete);274 }275 catch (System.Runtime.InteropServices.COMException e)276 {277 internalException = e;278 _state = WmiState.Failed;279 RaiseOperationCompleteEvent(null, OperationState.StopComplete);280 }281 catch (System.UnauthorizedAccessException e)282 {283 internalException = e;284 _state = WmiState.Failed;285 RaiseOperationCompleteEvent(null, OperationState.StopComplete);286 }287 }288 else289 {290 ManagementPath mPath = null;291 // If Class is specified only CreateOnly flag is supported292 if (setObject.Class != null)293 {294 if (setObject.flagSpecified && setObject.PutType != PutType.CreateOnly)295 {296 InvalidOperationException exp = new InvalidOperationException("CreateOnlyFlagNotSpecifiedWithClassPath");297 internalException = exp;298 _state = WmiState.Failed;299 RaiseOperationCompleteEvent(null, OperationState.StopComplete);300 return;301 }302 303 setObject.PutType = PutType.CreateOnly;304 }305 else306 {307 mPath = new ManagementPath(setObject.Path);308 if (string.IsNullOrEmpty(mPath.NamespacePath))309 {310 mPath.NamespacePath = setObject.Namespace;311 }312 else if (setObject.namespaceSpecified)313 {314 InvalidOperationException exp = new InvalidOperationException("NamespaceSpecifiedWithPath");315 internalException = exp;316 _state = WmiState.Failed;317 RaiseOperationCompleteEvent(null, OperationState.StopComplete);318 return;319 }320 321 if (mPath.Server != "." && setObject.serverNameSpecified)322 {323 InvalidOperationException exp = new InvalidOperationException("ComputerNameSpecifiedWithPath");324 internalException = exp;325 _state = WmiState.Failed;326 RaiseOperationCompleteEvent(null, OperationState.StopComplete);327 return;328 }329 330 if (mPath.IsClass)331 {332 if (setObject.flagSpecified && setObject.PutType != PutType.CreateOnly)333 {334 InvalidOperationException exp = new InvalidOperationException("CreateOnlyFlagNotSpecifiedWithClassPath");335 internalException = exp;336 _state = WmiState.Failed;337 RaiseOperationCompleteEvent(null, OperationState.StopComplete);338 return;339 }340 341 setObject.PutType = PutType.CreateOnly;342 }343 else344 {345 if (setObject.flagSpecified)346 {347 if (!(setObject.PutType == PutType.UpdateOnly || setObject.PutType == PutType.UpdateOrCreate))348 {349 InvalidOperationException exp = new InvalidOperationException("NonUpdateFlagSpecifiedWithInstancePath");350 internalException = exp;351 _state = WmiState.Failed;352 RaiseOperationCompleteEvent(null, OperationState.StopComplete);353 return;354 }355 }356 else357 {358 setObject.PutType = PutType.UpdateOrCreate;359 }360 }361 }362 // If server name is specified loop through it.363 if (mPath != null)364 {365 if (!(mPath.Server == "." && setObject.serverNameSpecified))366 {367 _computerName = mPath.Server;368 }369 }370 371 ConnectionOptions options = setObject.GetConnectionOption();372 ManagementObject mObject = null;373 try374 {375 if (setObject.Path != null)376 {377 mPath.Server = _computerName;378 ManagementScope mScope = new ManagementScope(mPath, options);379 if (mPath.IsClass)380 {381 ManagementClass mClass = new ManagementClass(mPath);382 mClass.Scope = mScope;383 mObject = mClass.CreateInstance();384 }385 else386 {387 // This can throw if path does not exist caller should catch it.388 ManagementObject mInstance = new ManagementObject(mPath);389 mInstance.Scope = mScope;390 try391 {392 mInstance.Get();393 }394 catch (ManagementException e)395 {396 if (e.ErrorCode != ManagementStatus.NotFound)397 {398 internalException = e;399 _state = WmiState.Failed;400 RaiseOperationCompleteEvent(null, OperationState.StopComplete);401 return;402 }403 404 int namespaceIndex = setObject.Path.IndexOf(':');405 if (namespaceIndex == -1)406 {407 internalException = e;408 _state = WmiState.Failed;409 RaiseOperationCompleteEvent(null, OperationState.StopComplete);410 return;411 }412 413 int classIndex = (setObject.Path.Substring(namespaceIndex)).IndexOf('.');414 if (classIndex == -1)415 {416 internalException = e;417 _state = WmiState.Failed;418 RaiseOperationCompleteEvent(null, OperationState.StopComplete);419 return;420 }421 // Get class object and create instance.422 string newPath = setObject.Path.Substring(0, classIndex + namespaceIndex);423 ManagementPath classPath = new ManagementPath(newPath);424 ManagementClass mClass = new ManagementClass(classPath);425 mClass.Scope = mScope;426 mInstance = mClass.CreateInstance();427 }428 429 mObject = mInstance;430 }431 }432 else433 {434 ManagementScope scope = new ManagementScope(WMIHelper.GetScopeString(_computerName, setObject.Namespace), options);435 ManagementClass mClass = new ManagementClass(setObject.Class);436 mClass.Scope = scope;437 mObject = mClass.CreateInstance();438 }439 440 if (setObject.Arguments != null)441 {442 IDictionaryEnumerator en = setObject.Arguments.GetEnumerator();443 while (en.MoveNext())444 {445 mObject[en.Key as string] = en.Value;446 }447 }448 449 PutOptions pOptions = new PutOptions();450 pOptions.Type = setObject.PutType;451 if (mObject != null)452 {453 mObject.Put(_results, pOptions);454 }455 else456 {457 InvalidOperationException exp = new InvalidOperationException();458 internalException = exp;459 _state = WmiState.Failed;460 RaiseOperationCompleteEvent(null, OperationState.StopComplete);461 }462 }463 catch (ManagementException e)464 {465 internalException = e;466 _state = WmiState.Failed;467 RaiseOperationCompleteEvent(null, OperationState.StopComplete);468 }469 catch (System.Runtime.InteropServices.COMException e)470 {471 internalException = e;472 _state = WmiState.Failed;473 RaiseOperationCompleteEvent(null, OperationState.StopComplete);474 }475 catch (System.UnauthorizedAccessException e)476 {477 internalException = e;478 _state = WmiState.Failed;479 RaiseOperationCompleteEvent(null, OperationState.StopComplete);480 }481 }482 }483 484 /// <summary>485 /// Do the actual connection to remote machine for Invoke-WMIMethod cmdlet and raise operation complete event.486 /// </summary>487 private void ConnectInvokeWmi()488 {489 InvokeWmiMethod invokeObject = (InvokeWmiMethod)_wmiObject;490 _state = WmiState.Running;491 RaiseWmiOperationState(null, WmiState.Running);492 493 if (invokeObject.InputObject != null)494 {495 ManagementBaseObject inputParameters = null;496 try497 {498 inputParameters = invokeObject.InputObject.GetMethodParameters(invokeObject.Name);499 if (invokeObject.ArgumentList != null)500 {501 int inParamCount = invokeObject.ArgumentList.Length;502 foreach (PropertyData property in inputParameters.Properties)503 {504 if (inParamCount == 0)505 break;506 property.Value = invokeObject.ArgumentList[invokeObject.ArgumentList.Length - inParamCount];507 inParamCount--;508 }509 }510 511 invokeObject.InputObject.InvokeMethod(_results, invokeObject.Name, inputParameters, null);512 }513 catch (ManagementException e)514 {515 internalException = e;516 _state = WmiState.Failed;517 RaiseOperationCompleteEvent(null, OperationState.StopComplete);518 }519 catch (System.Runtime.InteropServices.COMException e)520 {521 internalException = e;522 _state = WmiState.Failed;523 RaiseOperationCompleteEvent(null, OperationState.StopComplete);524 }525 catch (System.UnauthorizedAccessException e)526 {527 internalException = e;528 _state = WmiState.Failed;529 RaiseOperationCompleteEvent(null, OperationState.StopComplete);530 }531 532 return;533 }534 else535 {536 ConnectionOptions options = invokeObject.GetConnectionOption();537 ManagementPath mPath = null;538 ManagementObject mObject = null;539 if (invokeObject.Path != null)540 {541 mPath = new ManagementPath(invokeObject.Path);542 if (string.IsNullOrEmpty(mPath.NamespacePath))543 {544 mPath.NamespacePath = invokeObject.Namespace;545 }546 else if (invokeObject.namespaceSpecified)547 {548 InvalidOperationException e = new InvalidOperationException("NamespaceSpecifiedWithPath");549 internalException = e;550 _state = WmiState.Failed;551 RaiseOperationCompleteEvent(null, OperationState.StopComplete);552 return;553 }554 555 if (mPath.Server != "." && invokeObject.serverNameSpecified)556 {557 InvalidOperationException e = new InvalidOperationException("ComputerNameSpecifiedWithPath");558 internalException = e;559 _state = WmiState.Failed;560 RaiseOperationCompleteEvent(null, OperationState.StopComplete);561 return;562 }563 // If server name is specified loop through it.564 if (!(mPath.Server == "." && invokeObject.serverNameSpecified))565 {566 _computerName = mPath.Server;567 }568 }569 570 bool isLocal = false, needToEnablePrivilege = false;571 PlatformInvokes.TOKEN_PRIVILEGE currentPrivilegeState = new PlatformInvokes.TOKEN_PRIVILEGE();572 try573 {574 needToEnablePrivilege = NeedToEnablePrivilege(_computerName, invokeObject.Name, ref isLocal);575 if (needToEnablePrivilege)576 {577 if (!(isLocal && PlatformInvokes.EnableTokenPrivilege(ComputerWMIHelper.SE_SHUTDOWN_NAME, ref currentPrivilegeState)) &&578 !(!isLocal && PlatformInvokes.EnableTokenPrivilege(ComputerWMIHelper.SE_REMOTE_SHUTDOWN_NAME, ref currentPrivilegeState)))579 {580 string message =581 StringUtil.Format(ComputerResources.PrivilegeNotEnabled, _computerName,582 isLocal ? ComputerWMIHelper.SE_SHUTDOWN_NAME : ComputerWMIHelper.SE_REMOTE_SHUTDOWN_NAME);583 InvalidOperationException e = new InvalidOperationException(message);584 internalException = e;585 _state = WmiState.Failed;586 RaiseOperationCompleteEvent(null, OperationState.StopComplete);587 return;588 }589 }590 591 if (invokeObject.Path != null)592 {593 mPath.Server = _computerName;594 if (mPath.IsClass)595 {596 ManagementClass mClass = new ManagementClass(mPath);597 mObject = mClass;598 }599 else600 {601 ManagementObject mInstance = new ManagementObject(mPath);602 mObject = mInstance;603 }604 605 ManagementScope mScope = new ManagementScope(mPath, options);606 mObject.Scope = mScope;607 }608 else609 {610 ManagementScope scope = new ManagementScope(WMIHelper.GetScopeString(_computerName, invokeObject.Namespace), options);611 ManagementClass mClass = new ManagementClass(invokeObject.Class);612 mObject = mClass;613 mObject.Scope = scope;614 }615 616 ManagementBaseObject inputParameters = mObject.GetMethodParameters(invokeObject.Name);617 if (invokeObject.ArgumentList != null)618 {619 int inParamCount = invokeObject.ArgumentList.Length;620 foreach (PropertyData property in inputParameters.Properties)621 {622 if (inParamCount == 0)623 break;624 property.Value = invokeObject.ArgumentList[invokeObject.ArgumentList.Length - inParamCount];625 inParamCount--;626 }627 }628 629 if (needToEnablePrivilege)630 {631 ManagementBaseObject result = mObject.InvokeMethod(invokeObject.Name, inputParameters, null);632 Dbg.Diagnostics.Assert(result != null, "result cannot be null if the Join method is invoked");633 int returnCode = Convert.ToInt32(result["ReturnValue"], CultureInfo.CurrentCulture);634 if (returnCode != 0)635 {636 var e = new Win32Exception(returnCode);637 internalException = e;638 _state = WmiState.Failed;639 RaiseOperationCompleteEvent(null, OperationState.StopComplete);640 }641 else642 {643 ShutdownComplete.SafeInvoke(this, null);644 }645 }646 else647 {648 mObject.InvokeMethod(_results, invokeObject.Name, inputParameters, null);649 }650 }651 catch (ManagementException e)652 {653 internalException = e;654 _state = WmiState.Failed;655 RaiseOperationCompleteEvent(null, OperationState.StopComplete);656 }657 catch (System.Runtime.InteropServices.COMException e)658 {659 internalException = e;660 _state = WmiState.Failed;661 RaiseOperationCompleteEvent(null, OperationState.StopComplete);662 }663 catch (System.UnauthorizedAccessException e)664 {665 internalException = e;666 _state = WmiState.Failed;667 RaiseOperationCompleteEvent(null, OperationState.StopComplete);668 }669 finally670 {671 // Restore the previous privilege state if something unexpected happened672 if (needToEnablePrivilege)673 {674 PlatformInvokes.RestoreTokenPrivilege(675 isLocal ? ComputerWMIHelper.SE_SHUTDOWN_NAME : ComputerWMIHelper.SE_REMOTE_SHUTDOWN_NAME, ref currentPrivilegeState);676 }677 }678 }679 }680 681 /// <summary>682 /// Check if we need to enable the shutdown privilege.683 /// </summary>684 /// <param name="computer"></param>685 /// <param name="methodName"></param>686 /// <param name="isLocal"></param>687 /// <returns></returns>688 private bool NeedToEnablePrivilege(string computer, string methodName, ref bool isLocal)689 {690 bool result = false;691 if (methodName.Equals("Win32Shutdown", StringComparison.OrdinalIgnoreCase))692 {693 result = true;694 695 // CLR 4.0 Port note - use https://msdn.microsoft.com/library/system.net.networkinformation.ipglobalproperties.hostname(v=vs.110).aspx696 string localName = System.Net.Dns.GetHostName();697 698 // And for this, use PsUtils.GetHostname()699 string localFullName = System.Net.Dns.GetHostEntry(string.Empty).HostName;700 if (computer.Equals(".") || computer.Equals("localhost", StringComparison.OrdinalIgnoreCase) ||701 computer.Equals(localName, StringComparison.OrdinalIgnoreCase) ||702 computer.Equals(localFullName, StringComparison.OrdinalIgnoreCase))703 {704 isLocal = true;705 }706 }707 708 return result;709 }710 711 /// <summary>712 /// Do the actual connection to remote machine for Remove-WMIObject cmdlet and raise operation complete event.713 /// </summary>714 private void ConnectRemoveWmi()715 {716 RemoveWmiObject removeObject = (RemoveWmiObject)_wmiObject;717 _state = WmiState.Running;718 RaiseWmiOperationState(null, WmiState.Running);719 if (removeObject.InputObject != null)720 {721 try722 {723 removeObject.InputObject.Delete(_results);724 }725 catch (ManagementException e)726 {727 internalException = e;728 _state = WmiState.Failed;729 RaiseOperationCompleteEvent(null, OperationState.StopComplete);730 }731 catch (System.Runtime.InteropServices.COMException e)732 {733 internalException = e;734 _state = WmiState.Failed;735 RaiseOperationCompleteEvent(null, OperationState.StopComplete);736 }737 catch (System.UnauthorizedAccessException e)738 {739 internalException = e;740 _state = WmiState.Failed;741 RaiseOperationCompleteEvent(null, OperationState.StopComplete);742 }743 744 return;745 }746 else747 {748 ConnectionOptions options = removeObject.GetConnectionOption();749 ManagementPath mPath = null;750 ManagementObject mObject = null;751 if (removeObject.Path != null)752 {753 mPath = new ManagementPath(removeObject.Path);754 if (string.IsNullOrEmpty(mPath.NamespacePath))755 {756 mPath.NamespacePath = removeObject.Namespace;757 }758 else if (removeObject.namespaceSpecified)759 {760 InvalidOperationException e = new InvalidOperationException("NamespaceSpecifiedWithPath");761 internalException = e;762 _state = WmiState.Failed;763 RaiseOperationCompleteEvent(null, OperationState.StopComplete);764 return;765 }766 767 if (mPath.Server != "." && removeObject.serverNameSpecified)768 {769 InvalidOperationException e = new InvalidOperationException("ComputerNameSpecifiedWithPath");770 internalException = e;771 _state = WmiState.Failed;772 RaiseOperationCompleteEvent(null, OperationState.StopComplete);773 return;774 }775 776 if (!(mPath.Server == "." && removeObject.serverNameSpecified))777 {778 _computerName = mPath.Server;779 }780 }781 782 try783 {784 if (removeObject.Path != null)785 {786 mPath.Server = _computerName;787 if (mPath.IsClass)788 {789 ManagementClass mClass = new ManagementClass(mPath);790 mObject = mClass;791 }792 else793 {794 ManagementObject mInstance = new ManagementObject(mPath);795 mObject = mInstance;796 }797 798 ManagementScope mScope = new ManagementScope(mPath, options);799 mObject.Scope = mScope;800 }801 else802 {803 ManagementScope scope = new ManagementScope(WMIHelper.GetScopeString(_computerName, removeObject.Namespace), options);804 ManagementClass mClass = new ManagementClass(removeObject.Class);805 mObject = mClass;806 mObject.Scope = scope;807 }808 809 mObject.Delete(_results);810 }811 catch (ManagementException e)812 {813 internalException = e;814 _state = WmiState.Failed;815 RaiseOperationCompleteEvent(null, OperationState.StopComplete);816 }817 catch (System.Runtime.InteropServices.COMException e)818 {819 internalException = e;820 _state = WmiState.Failed;821 RaiseOperationCompleteEvent(null, OperationState.StopComplete);822 }823 catch (System.UnauthorizedAccessException e)824 {825 internalException = e;826 _state = WmiState.Failed;827 RaiseOperationCompleteEvent(null, OperationState.StopComplete);828 }829 }830 }831 832 /// <summary>833 /// Do the actual connection to remote machine for Get-WMIObject cmdlet and raise operation complete event.834 /// </summary>835 private void ConnectGetWMI()836 {837 GetWmiObjectCommand getObject = (GetWmiObjectCommand)_wmiObject;838 _state = WmiState.Running;839 RaiseWmiOperationState(null, WmiState.Running);840 ConnectionOptions options = getObject.GetConnectionOption();841 if (getObject.List.IsPresent)842 {843 if (!getObject.ValidateClassFormat())844 {845 ArgumentException e = new ArgumentException(846 string.Format(847 Thread.CurrentThread.CurrentCulture,848 "Class", getObject.Class));849 850 internalException = e;851 _state = WmiState.Failed;852 RaiseOperationCompleteEvent(null, OperationState.StopComplete);853 return;854 }855 856 try857 {858 if (getObject.Recurse.IsPresent)859 {860 ArrayList namespaceArray = new ArrayList();861 ArrayList sinkArray = new ArrayList();862 ArrayList connectArray = new ArrayList(); // Optimization for remote namespace863 int currentNamespaceCount = 0;864 namespaceArray.Add(getObject.Namespace);865 bool topNamespace = true;866 while (currentNamespaceCount < namespaceArray.Count)867 {868 string connectNamespace = (string)namespaceArray[currentNamespaceCount];869 ManagementScope scope = new ManagementScope(WMIHelper.GetScopeString(_computerName, connectNamespace), options);870 scope.Connect();871 ManagementClass namespaceClass = new ManagementClass(scope, new ManagementPath("__Namespace"), new ObjectGetOptions());872 foreach (ManagementBaseObject obj in namespaceClass.GetInstances())873 {874 if (!getObject.IsLocalizedNamespace((string)obj["Name"]))875 {876 namespaceArray.Add(connectNamespace + "\\" + obj["Name"]);877 }878 }879 880 if (topNamespace)881 {882 topNamespace = false;883 sinkArray.Add(_results);884 }885 else886 {887 sinkArray.Add(_job.GetNewSink());888 }889 890 connectArray.Add(scope);891 currentNamespaceCount++;892 }893 894 if ((sinkArray.Count != namespaceArray.Count) || (connectArray.Count != namespaceArray.Count)) // not expected throw exception895 {896 internalException = new InvalidOperationException();897 _state = WmiState.Failed;898 RaiseOperationCompleteEvent(null, OperationState.StopComplete);899 return;900 }901 902 currentNamespaceCount = 0;903 while (currentNamespaceCount < namespaceArray.Count)904 {905 string connectNamespace = (string)namespaceArray[currentNamespaceCount];906 ManagementObjectSearcher searcher = getObject.GetObjectList((ManagementScope)connectArray[currentNamespaceCount]);907 if (searcher == null)908 {909 currentNamespaceCount++;910 continue;911 }912 913 if (topNamespace)914 {915 topNamespace = false;916 searcher.Get(_results);917 }918 else919 {920 searcher.Get((ManagementOperationObserver)sinkArray[currentNamespaceCount]);921 }922 923 currentNamespaceCount++;924 }925 }926 else927 {928 ManagementScope scope = new ManagementScope(WMIHelper.GetScopeString(_computerName, getObject.Namespace), options);929 scope.Connect();930 ManagementObjectSearcher searcher = getObject.GetObjectList(scope);931 if (searcher == null)932 throw new ManagementException();933 searcher.Get(_results);934 }935 }936 catch (ManagementException e)937 {938 internalException = e;939 _state = WmiState.Failed;940 RaiseOperationCompleteEvent(null, OperationState.StopComplete);941 }942 catch (System.Runtime.InteropServices.COMException e)943 {944 internalException = e;945 _state = WmiState.Failed;946 RaiseOperationCompleteEvent(null, OperationState.StopComplete);947 }948 catch (System.UnauthorizedAccessException e)949 {950 internalException = e;951 _state = WmiState.Failed;952 RaiseOperationCompleteEvent(null, OperationState.StopComplete);953 }954 955 return;956 }957 958 string queryString = string.IsNullOrEmpty(getObject.Query) ? GetWmiQueryString() : getObject.Query;959 ObjectQuery query = new ObjectQuery(queryString.ToString());960 try961 {962 ManagementScope scope = new ManagementScope(WMIHelper.GetScopeString(_computerName, getObject.Namespace), options);963 EnumerationOptions enumOptions = new EnumerationOptions();964 enumOptions.UseAmendedQualifiers = getObject.Amended;965 enumOptions.DirectRead = getObject.DirectRead;966 ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query, enumOptions);967 968 // Execute the WMI command for each count value.969 for (int i = 0; i < _cmdCount; ++i)970 {971 searcher.Get(_results);972 }973 }974 catch (ManagementException e)975 {976 internalException = e;977 _state = WmiState.Failed;978 RaiseOperationCompleteEvent(null, OperationState.StopComplete);979 }980 catch (System.Runtime.InteropServices.COMException e)981 {982 internalException = e;983 _state = WmiState.Failed;984 RaiseOperationCompleteEvent(null, OperationState.StopComplete);985 }986 catch (System.UnauthorizedAccessException e)987 {988 internalException = e;989 _state = WmiState.Failed;990 RaiseOperationCompleteEvent(null, OperationState.StopComplete);991 }992 }993 }994 995 /// <summary>996 /// Event which will be triggered when WMI state is changed.997 /// Currently it is to notify Jobs that state has changed to running.998 /// Other states are notified via OperationComplete.999 /// </summary>1000 internal sealed class WmiJobStateEventArgs : EventArgs1001 {1002 /// <summary>1003 /// WMI state1004 /// </summary>1005 internal WmiState WmiState { get; set; }1006 }1007 1008 /// <summary>1009 /// Enumerated type defining the state of the WMI operation.1010 /// </summary>1011 public enum WmiState1012 {1013 /// <summary>1014 /// The operation has not been started.1015 /// </summary>1016 NotStarted = 0,1017 /// <summary>1018 /// The operation is executing.1019 /// </summary>1020 Running = 1,1021 /// <summary>1022 /// The operation is stoping execution.1023 /// </summary>1024 Stopping = 2,1025 /// <summary>1026 /// The operation is completed due to a stop request.1027 /// </summary>1028 Stopped = 3,1029 /// <summary>1030 /// The operation has completed.1031 /// </summary>1032 Completed = 4,1033 /// <summary>1034 /// The operation completed abnormally due to an error.1035 /// </summary>1036 Failed = 5,1037 }1038 1039 internal static class WMIHelper1040 {1041 internal static string GetScopeString(string computer, string namespaceParameter)1042 {1043 StringBuilder returnValue = new StringBuilder("\\\\");1044 returnValue.Append(computer);1045 returnValue.Append('\\');1046 returnValue.Append(namespaceParameter);1047 return returnValue.ToString();1048 }1049 }1050 #endregion Helper Classes1051 1052 /// <summary>1053 /// A class to set WMI connection options.1054 /// </summary>1055 public class WmiBaseCmdlet : Cmdlet1056 {1057 #region Parameters1058 1059 /// <summary>1060 /// Perform Async operation.1061 /// </summary>1062 [Parameter]1063 public SwitchParameter AsJob { get; set; } = false;1064 1065 /// <summary>1066 /// The Impersonation level to use.1067 /// </summary>1068 [Parameter(ParameterSetName = "path")]1069 [Parameter(ParameterSetName = "class")]1070 [Parameter(ParameterSetName = "WQLQuery")]1071 [Parameter(ParameterSetName = "query")]1072 [Parameter(ParameterSetName = "list")]1073 public ImpersonationLevel Impersonation { get; set; } = ImpersonationLevel.Impersonate;1074 1075 /// <summary>1076 /// The Authentication level to use.1077 /// </summary>1078 [Parameter(ParameterSetName = "path")]1079 [Parameter(ParameterSetName = "class")]1080 [Parameter(ParameterSetName = "WQLQuery")]1081 [Parameter(ParameterSetName = "query")]1082 [Parameter(ParameterSetName = "list")]1083 public AuthenticationLevel Authentication { get; set; } = AuthenticationLevel.PacketPrivacy;1084 1085 /// <summary>1086 /// The Locale to use.1087 /// </summary>1088 [Parameter(ParameterSetName = "path")]1089 [Parameter(ParameterSetName = "class")]1090 [Parameter(ParameterSetName = "WQLQuery")]1091 [Parameter(ParameterSetName = "query")]1092 [Parameter(ParameterSetName = "list")]1093 public string Locale { get; set; } = null;1094 1095 /// <summary>1096 /// If all Privileges are enabled.1097 /// </summary>1098 [Parameter(ParameterSetName = "path")]1099 [Parameter(ParameterSetName = "class")]1100 [Parameter(ParameterSetName = "WQLQuery")]1101 [Parameter(ParameterSetName = "query")]1102 [Parameter(ParameterSetName = "list")]1103 public SwitchParameter EnableAllPrivileges { get; set; }1104 1105 /// <summary>1106 /// The Authority to use.1107 /// </summary>1108 [Parameter(ParameterSetName = "path")]1109 [Parameter(ParameterSetName = "class")]1110 [Parameter(ParameterSetName = "WQLQuery")]1111 [Parameter(ParameterSetName = "query")]1112 [Parameter(ParameterSetName = "list")]1113 public string Authority { get; set; } = null;1114 1115 /// <summary>1116 /// The credential to use.1117 /// </summary>1118 [Parameter(ParameterSetName = "path")]1119 [Parameter(ParameterSetName = "class")]1120 [Parameter(ParameterSetName = "WQLQuery")]1121 [Parameter(ParameterSetName = "query")]1122 [Parameter(ParameterSetName = "list")]1123 [Credential]1124 public PSCredential Credential { get; set; }1125 1126 /// <summary>1127 /// The credential to use.1128 /// </summary>1129 [Parameter]1130 public Int32 ThrottleLimit { get; set; } = s_DEFAULT_THROTTLE_LIMIT;1131 1132 /// <summary>1133 /// The ComputerName in which to query.1134 /// </summary>1135 [Parameter(ParameterSetName = "path")]1136 [Parameter(ParameterSetName = "class")]1137 [Parameter(ParameterSetName = "WQLQuery")]1138 [Parameter(ParameterSetName = "query")]1139 [Parameter(ParameterSetName = "list")]1140 [ValidateNotNullOrEmpty]1141 [Alias("Cn")]1142 [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]1143 public string[] ComputerName1144 {1145 get { return _computerName; }1146 1147 set { _computerName = value; serverNameSpecified = true; }1148 }1149 /// <summary>1150 /// The WMI namespace to use.1151 /// </summary>1152 [Parameter(ParameterSetName = "path")]1153 [Parameter(ParameterSetName = "class")]1154 [Parameter(ParameterSetName = "WQLQuery")]1155 [Parameter(ParameterSetName = "query")]1156 [Parameter(ParameterSetName = "list")]1157 [Alias("NS")]1158 public string Namespace1159 {1160 get { return _nameSpace; }1161 1162 set { _nameSpace = value; namespaceSpecified = true; }1163 }1164 #endregion Parameters1165 1166 #region parameter data1167 /// <summary>1168 /// The computer to query.1169 /// </summary>1170 private string[] _computerName = new string[] { "localhost" };1171 /// <summary>1172 /// WMI namespace.1173 /// </summary>1174 private string _nameSpace = "root\\cimv2";1175 /// <summary>1176 /// Specify if namespace was specified or not.1177 /// </summary>1178 internal bool namespaceSpecified = false;1179 /// <summary>1180 /// Specify if server name was specified or not.1181 /// </summary>1182 internal bool serverNameSpecified = false;1183 1184 private static int s_DEFAULT_THROTTLE_LIMIT = 32; // maximum number of items to be processed at a time1185 1186 #endregion parameter data1187 1188 #region Command code1189 /// <summary>1190 /// Get connection options.1191 /// </summary>1192 internal ConnectionOptions GetConnectionOption()1193 {1194 ConnectionOptions options;1195 options = new ConnectionOptions();1196 options.Authentication = this.Authentication;1197 options.Locale = this.Locale;1198 options.Authority = this.Authority;1199 options.EnablePrivileges = this.EnableAllPrivileges;1200 options.Impersonation = this.Impersonation;