Learn about Windows PowerShell
Summary: Learn how to use jobs to run parallel queries, remove objects from active memory, work with text files and use the Get-Member Cmdlet to go behind the scenes of PowerShell commands in this edition of Quick Hits Friday.
In this Post:
Hey, Scripting Guy! I have a (hopefully) simple question. I’m developing a script to measure the size of user home directories on multiple servers for billing purposes. In my example below, there are only two, but later there will be more than 50 servers to challenge. Is there a way I can run the queries in parallel in order to save time? The script below only does them one after the other.
$dir = "server1.mydomain.com", "server2.mydomain.com" foreach ($server in $dir){Invoke-Command -ComputerName $server -ScriptBlock{$parent = Get-ChildItem 'e:\users' foreach ($child in $parent){ $check = "e:\users\" + $child.name $colItems = (Get-ChildItem $check -recurse | Measure-Object -property length -sum) $mem = "{0:N2}" -f ($colItems.sum / 1MB) + " MB " $check + "....." + $mem}}}
-- MH
Hello MH, Microsoft Scripting Guy Ed Wilson here. You may want to use the –asjob switch for your Invoke–Command command. It will allow your job to run in the background. Here are some Hey, Scripting Guy! posts where I talking about how to run and receive jobs. You may also consider specifying the –throttleLimit parameter. By default, the Invoke-Command cmdlet will maintain 32 concurrent connections. You may want to bump that number up , depending on the resources that are available to your machine.
Hey, Scripting Guy! You make it very clear how to create an object (such as an Excel application) within VBScript code but after that object is created and opened, it remains in memory even after the script is closed. I cannot seem to find any method of removing that created Excel application from active memory. Please help.
-- BC
Hello BC, you have to call the quit method from the application object. Here is an example of a VBScript that I wrote that creates an instance of the Excel.Application object, opens a particular Microsoft Excel spreadsheet, and reads particular information from that spreadsheet. After it is finished reading the spreadsheet, it calls the quit method.
Option Explicit
on error resume next
Dim objExcel, objWorkbook
Dim intRow
Dim strSheet
strSheet = "D:\VBSworkshop\Labs\Extras\NewUsers.xls"
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open (strSheet)
intRow = 2 'this is the row in the sheet we start reading.
Do Until objExcel.Cells(intRow,1).Value = ""
Wscript.Echo "CN: " & objExcel.Cells(intRow, 1).Value
Wscript.Echo "sAMAccountName: " & objExcel.Cells(intRow, 2).Value
Wscript.Echo "GivenName: " & objExcel.Cells(intRow, 3).Value
Wscript.Echo "LastName: " & objExcel.Cells(intRow, 4).Value
WScript.Echo ""
intRow = intRow + 1
Loop
objExcel.Quit 'closes out the excel object - YOU MUST include this or Excel.exe will keep running.
Hey, Scripting Guy! I am a VBScript lover from China. I am having problems with a script right now. I want to add some information to a specified file. I have learned some information from MSDN to realize the CIM_LogicalFile Class is not implemented by WMI so what else can I do to use it with VBScript?
-- SL
Hello SL, the best way to add information to a text file from within VBScript is to use the FileSystemObject.
I have a large number of Hey, Scripting Guy! Blog posts that talk about how to work with text files from within VBScript. In addition, there are 50 VBScripts that illustrate working with text files on the Scripting Guys Script Repository. In addition to those two resources, if you find yourself in need of assistance while you work on your script, you may want to post a question to the Official Scripting Guys Forum.
Hey, Scripting Guy! I’ve used following code so that I could ‘copy’ permissions from one folder, and assign them to another folder.
$ACL = Get-Acl “\\TESTSTO01\s$\Democorp”Set-Acl “\\TESTSTO01\$Driveletter$\$Company” $ACL
It did work correctly, but I cannot see what is happening. Can I see the script behind this? That would be very helpful to understand this process!
-- NT
Hello NT, that is the cool thing about Windows PowerShell, there is no script behind the scenes. The Windows PowerShell cmdlets interact directly with the .NET security classes to perform the commands.
If you want to see what is going on “behind the scenes” you have to use the Get-Member cmdlet. Here is an example.
Here I use the Get-Acl Windows PowerShell cmdlet to retrieve security information from a particular file on my computer. I store the security information in the $acl variable. If I examine what is contained in the $acl variable, I have an overview of the information that is contained in the variable. This is seen here.
PS C:\> $acl = Get-Acl -Path C:\fso\a.txt
PS C:\> $acl
Directory: C:\fso
Path Owner Access
---- ----- ------
a.txt NORTHAMERICA\edwils BUILTIN\Administrators Allow ...
If I want to know what is going on behind the scenes, the Get-Acl Windows PowerShell cmdlet has obtained a FileSecurity .NET Framework class. This class is located in the System.Security.AccessControl .NET Framework namespace. This particular class has a number of things it can do (methods) and several things it can describe (properties). The Get-Member Windows PowerShell cmdlet will display the members of the FileSecurity class. This is seen here.
PS C:\> $acl | get-member
TypeName: System.Security.AccessControl.FileSecurity
Name MemberType Definition
---- ---------- ----------
Access CodeProperty System.Security.AccessControl.AuthorizationRuleCo...
Group CodeProperty System.String Group{get=GetGroup;}
Owner CodeProperty System.String Owner{get=GetOwner;}
Path CodeProperty System.String Path{get=GetPath;}
Sddl CodeProperty System.String Sddl{get=GetSddl;}
AccessRuleFactory Method System.Security.AccessControl.AccessRule AccessRu...
AddAccessRule Method System.Void AddAccessRule(System.Security.AccessC...
AddAuditRule Method System.Void AddAuditRule(System.Security.AccessCo...
AuditRuleFactory Method System.Security.AccessControl.AuditRule AuditRule...
Equals Method bool Equals(System.Object obj)
GetAccessRules Method System.Security.AccessControl.AuthorizationRuleCo...
GetAuditRules Method System.Security.AccessControl.AuthorizationRuleCo...
GetGroup Method System.Security.Principal.IdentityReference GetGr...
GetHashCode Method int GetHashCode()
GetOwner Method System.Security.Principal.IdentityReference GetOw...
GetSecurityDescriptorBinaryForm Method byte[] GetSecurityDescriptorBinaryForm()
GetSecurityDescriptorSddlForm Method string GetSecurityDescriptorSddlForm(System.Secur...
GetType Method type GetType()
ModifyAccessRule Method bool ModifyAccessRule(System.Security.AccessContr...
ModifyAuditRule Method bool ModifyAuditRule(System.Security.AccessContro...
PurgeAccessRules Method System.Void PurgeAccessRules(System.Security.Prin...
PurgeAuditRules Method System.Void PurgeAuditRules(System.Security.Princ...
RemoveAccessRule Method bool RemoveAccessRule(System.Security.AccessContr...
RemoveAccessRuleAll Method System.Void RemoveAccessRuleAll(System.Security.A...
RemoveAccessRuleSpecific Method System.Void RemoveAccessRuleSpecific(System.Secur...
RemoveAuditRule Method bool RemoveAuditRule(System.Security.AccessContro...
RemoveAuditRuleAll Method System.Void RemoveAuditRuleAll(System.Security.Ac...
RemoveAuditRuleSpecific Method System.Void RemoveAuditRuleSpecific(System.Securi...
ResetAccessRule Method System.Void ResetAccessRule(System.Security.Acces...
SetAccessRule Method System.Void SetAccessRule(System.Security.AccessC...
SetAccessRuleProtection Method System.Void SetAccessRuleProtection(bool isProtec...
SetAuditRule Method System.Void SetAuditRule(System.Security.AccessCo...
SetAuditRuleProtection Method System.Void SetAuditRuleProtection(bool isProtect...
SetGroup Method System.Void SetGroup(System.Security.Principal.Id...
SetOwner Method System.Void SetOwner(System.Security.Principal.Id...
SetSecurityDescriptorBinaryForm Method System.Void SetSecurityDescriptorBinaryForm(byte[...
SetSecurityDescriptorSddlForm Method System.Void SetSecurityDescriptorSddlForm(string ...
ToString Method string ToString()
PSChildName NoteProperty System.String PSChildName=a.txt
PSDrive NoteProperty System.Management.Automation.PSDriveInfo PSDrive=C
PSParentPath NoteProperty System.String PSParentPath=Microsoft.PowerShell.C...
PSPath NoteProperty System.String PSPath=Microsoft.PowerShell.Core\Fi...
PSProvider NoteProperty System.Management.Automation.ProviderInfo PSProvi...
AccessRightType Property System.Type AccessRightType {get;}
AccessRuleType Property System.Type AccessRuleType {get;}
AreAccessRulesCanonical Property System.Boolean AreAccessRulesCanonical {get;}
AreAccessRulesProtected Property System.Boolean AreAccessRulesProtected {get;}
AreAuditRulesCanonical Property System.Boolean AreAuditRulesCanonical {get;}
AreAuditRulesProtected Property System.Boolean AreAuditRulesProtected {get;}
AuditRuleType Property System.Type AuditRuleType {get;}
AccessToString ScriptProperty System.Object AccessToString {get=$toString = "";...
AuditToString ScriptProperty System.Object AuditToString {get=$toString = "";...
PS C:\>
If I want to view more information that is contained in the $acl variable, I can pipeline the $acl variable to the Format-List Windows PowerShell cmdlet. This is shown here.
PS C:\> $acl | format-list *
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\fso\a.txt
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\fso
PSChildName : a.txt
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
AccessToString : BUILTIN\Administrators Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Users Allow ReadAndExecute, Synchronize
NT AUTHORITY\Authenticated Users Allow Modify, Synchronize
AuditToString :
Path : Microsoft.PowerShell.Core\FileSystem::C:\fso\a.txt
Owner : NORTHAMERICA\edwils
Group : NORTHAMERICA\Domain Users
Access : {System.Security.AccessControl.FileSystemAccessRule, System.Security.Acce
ssControl.FileSystemAccessRule, System.Security.AccessControl.FileSystemA
ccessRule, System.Security.AccessControl.FileSystemAccessRule}
Sddl : O:S-1-5-21-124525095-708259637-1543119021-179756G:DUD:AI(A;ID;FA;;;BA)(A;
ID;FA;;;SY)(A;ID;0x1200a9;;;BU)(A;ID;0x1301bf;;;AU)
AccessRightType : System.Security.AccessControl.FileSystemRights
AccessRuleType : System.Security.AccessControl.FileSystemAccessRule
AuditRuleType : System.Security.AccessControl.FileSystemAuditRule
AreAccessRulesProtected : False
AreAuditRulesProtected : False
AreAccessRulesCanonical : True
AreAuditRulesCanonical : True
To understand what I am looking at, I like to look up the .NET Framework classes on MSDN. The System.Security.Accesscontrol.FileSecurity class is documented in the reference section on MSDN. I have written several Hey, Scripting Guy! Blog posts that talk about how to work with SACLS and DACLS
This concludes another edition of Quick Hits Friday. Join me tomorrow for the Weekend Scripter as I delve into the mysteries of cmdlet parameter aliases.
I would love you to follow me on Twitter or Facebook. If you have any questions, send email to me at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy