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:

 

Use Jobs to Run Parallel Queries with Windows PowerShell

Hey, Scripting Guy! QuestionHey, 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

 

Hey, Scripting Guy! AnswerHello 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.

 

Remove Application Objects from Active Memory

Hey, Scripting Guy! QuestionHey, 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

 

Hey, Scripting Guy! AnswerHello 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.

 

Add Information to Text Files with VBScript

Hey, Scripting Guy! QuestionHey, 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

 

Hey, Scripting Guy! AnswerHello 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.

 

Go Behind the Scenes of a PowerShell Command with Get-Member

Hey, Scripting Guy! QuestionHey, 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

 

Hey, Scripting Guy! AnswerHello 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

 

 

 

PS C:\>

 

 

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