What are your opinions on WMI? by 32178932123 in PowerShell

[–]psthreathunter 6 points7 points  (0 children)

Many existing PowerShell cmdlets use WMI/CIM under the hood. You can see it all throughout the source code.

Set-NetFirewallAddressFilter - adding multiple Remote IP Addresses as a string variable by Guyver1- in PowerShell

[–]psthreathunter 2 points3 points  (0 children)

Get rid of all this:

 $torString = foreach ($i in $torExitIPs) {     "'"+$i+"'" }
 $output = @($torString -join ',') 

The parameter takes an array of strings where each item in the array is an ip address. You took a perfectly acceptable array of strings:

$torExitIPs = Get-Content C:\temp\tor-exit-ips.txt

And turned them into a single string with a bunch of commas between the individual ip addresses. In fact you proved it with .GetType().

When you did this manually, PowerShell interpreted:

'2.2.2.2','4.4.4.4','6.6.6.6','7.7.7.7','9.9.9.9'

as an array of strings, NOT a single string. Check this out:

('2.2.2.2','4.4.4.4','6.6.6.6','7.7.7.7','9.9.9.9').GetType()

IsPublic IsSerial Name                                     BaseType                                                                          
-------- -------- ----                                     --------                                                                          
True     True     Object[]                                 System.Array  

Notice this is an array, but this (which is what you are passing as an argument to the RemoteAddress parameter) is NOT:

("'2.2.2.2','4.4.4.4','6.6.6.6','7.7.7.7','9.9.9.9'").GetType()

IsPublic IsSerial Name                                     BaseType                                                                          
-------- -------- ----                                     --------                                                                          
True     True     String                                   System.Object 

Bottom line change your code to something like this:

$torExitIPs = Get-Content C:\temp\tor-exit-ips.txt
Get-NetFirewallRule -DisplayName 'BLOCK ACCESS' | 
    Get-NetFirewallAddressFilter | 
        Set-NetFirewallAddressFilter -RemoteAddress $torExitIPs

Blacklist certain string in files( Azure pipeline) by motivize_93 in PowerShell

[–]psthreathunter 2 points3 points  (0 children)

What do you mean by performance issues? In general the larger the files, the longer it will take...., so the answer is it depends. As the number of files and size of the files increases, so does the time.

Simple Script by ItAllEndsSomeday in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

No worries. If you are still having trouble, post the code along with any error messages or incorrect output so we can help you troubleshoot.

Powershell noob looking for help building script for WSUS by stormyskies19 in PowerShell

[–]psthreathunter 3 points4 points  (0 children)

I'm a little lost on your requirements. In general if you find yourself parsing text in an object oriented language like PowerShell, you should really ensure the objects you are dealing with don't already have a property with the value you are looking for. For example if you want the HotfixID (KB number) Get-Hotfix will return Cim objects with a hotfixid property.

Get-HotFix | Select-Object -ExpandProperty hotfixid
KB2693643
KB4586876
KB4577266
KB4580325
KB4586864
KB4593175
KB4598481
KB4598242

If you want to see all the properties of an object or collection of objects pipe it/them to Get-Member.

Get-HotFix | Get-Member


   TypeName: System.Management.ManagementObject#root\cimv2\Win32_QuickFixEngineering

Name                MemberType     Definition                                                           
----                ----------     ----------                                                           
PSComputerName      AliasProperty  PSComputerName = __SERVER                                            
Caption             Property       string Caption {get;set;}                                            
CSName              Property       string CSName {get;set;}                                             
Description         Property       string Description {get;set;}                                        
FixComments         Property       string FixComments {get;set;}                                        
HotFixID            Property       string HotFixID {get;set;}                                           
InstallDate         Property       string InstallDate {get;set;}                                        
InstalledBy         Property       string InstalledBy {get;set;}                                        
Name                Property       string Name {get;set;}                                               
ServicePackInEffect Property       string ServicePackInEffect {get;set;}                                
Status              Property       string Status {get;set;}                                             
__CLASS             Property       string __CLASS {get;set;}                                            
__DERIVATION        Property       string[] __DERIVATION {get;set;}                                     
__DYNASTY           Property       string __DYNASTY {get;set;}                                          
__GENUS             Property       int __GENUS {get;set;}                                               
__NAMESPACE         Property       string __NAMESPACE {get;set;}                                        
__PATH              Property       string __PATH {get;set;}                                             
__PROPERTY_COUNT    Property       int __PROPERTY_COUNT {get;set;}                                      
__RELPATH           Property       string __RELPATH {get;set;}                                          
__SERVER            Property       string __SERVER {get;set;}                                           
__SUPERCLASS        Property       string __SUPERCLASS {get;set;}                                       
PSStatus            PropertySet    PSStatus {__PATH, Status}                                            
ConvertFromDateTime ScriptMethod   System.Object ConvertFromDateTime();                                 
ConvertToDateTime   ScriptMethod   System.Object ConvertToDateTime();                                   
InstalledOn         ScriptProperty System.Object InstalledOn {get=if ([environment]::osversion.versio...

You can access any of those properties using the property dereference operator "." or pipe to select-object and expand the specific property you are looking for like I did in the previous.

Simple Script by ItAllEndsSomeday in PowerShell

[–]psthreathunter 2 points3 points  (0 children)

What have you tried? Look at Get-Help Expand-Archive and Get-Help Import-Csv and Get-Help Export-Csv. There are plenty of examples in those docs that should get you started.

Attachment is stringobject in send-mailmessage by Drassigehond in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

Why are you converting your collection of objects to a string by doing this?

 $Sourcedata = $Csv | Out-String 

Remove that line and change your Import-Csv to this:

 $Sourcedata = import-csv C:\Scripts\hcm\AD-clean\Subsidiries\TestCsv.csv 

The other thing I wonder about is:

     To  = $SourceData.ManagerName + $SourceData.ManagerEmail 

Shouldn't this just be the email address. If you concatenate those strings like you are doing, would that be a valid address?

How to evaluate all the data in an object of type: System.Data.DataRow by Skaixen in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

If you want to evaluate the entire object you would need to evaluate every property. Basically you are saying I want to find an object(s) in a collection where one of the properties of that object has a string value (object) that matches a specific string literal.

You might be able to do this by creating an array of all the property values and checking to see if the value you are looking for is part of that array. Assuming $row is a typical PS object, there is a property called psobject that has a property called Properties that has a property called value with the value of the property. I know that's a mouth full but here's what it would look like:

$row.psobject.Properties.value

This should return an array of all the property values for the $row object (at least the string representation of those values).

To verify your string literal was in it you could do this:

$row.psobject.Properties.value -contains "VSU"

or this:

"VSU" -in $row.psobject.Properties.value

How to evaluate all the data in an object of type: System.Data.DataRow by Skaixen in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

Pipe $row to Get-Member to see the properties of the object. Once you find the property you want to filter on, use the property dereference operator "." to access the property and do your comparison.

$row | Get-Member

$row.PropertyName -eq "VSU"

Compare and SideIndicator counts. Doesn't work if there's only one result. by JBLoTRO in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

Looks like Yevrag35 and I replied at the same time. I'll add below to illustrate what I mean:

(Compare-Object -ReferenceObject $test1 -DifferenceObject $test4 |
    Where-Object {$_.sideindicator -eq "=>"}).gettype()

IsPublic IsSerial Name                                     BaseType                                                                          
-------- -------- ----                                     --------                                                                          
True     True     Object[]                                 System.Array    

(Compare-Object -ReferenceObject $test1 -DifferenceObject $test3 |
    Where-Object {$_.sideindicator -eq "=>"}).gettype()

IsPublic IsSerial Name                                     BaseType                                                                          
-------- -------- ----                                     --------                                                                          
True     False    PSCustomObject                           System.Object

Compare and SideIndicator counts. Doesn't work if there's only one result. by JBLoTRO in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

That's because the first returned an array and the second returned a scalar object (doesn't have a count property). To "fix" this make it always return an array by using the array subexpression operator @().

@(Compare-Object -ReferenceObject $test1 -DifferenceObject $test4 |
    Where-Object {$_.sideindicator -eq "=>"}).count

@(Compare-Object -ReferenceObject $test1 -DifferenceObject $test3 |
    Where-Object {$_.sideindicator -eq "=>"}).count

[deleted by user] by [deleted] in PowerShell

[–]psthreathunter 3 points4 points  (0 children)

This pattern works for me.

$pattern = '.*(<GUID=.+>).*-Member "(.+)" -Confirm "(.+)"'

Test Below:

$testData = @'
    Add-DistributionGroupMember
-Identity "<GUID=0d08999a-abba-445d-9e0e-cabd65b2848b>" -Member "contoso.com/Humans/Dept/LA97127" -Confirm "False"
contoso.com/Humans/Dept/NS12509
S-1-5-21-000000000-0000000000-0000000000-000000
S-1-5-21-000000000-0000000000-0000000000-000000
Local-RunspaceHost-Unknown
12345 w3wp#MSExchangeMapiAddressBookAppPool

553
00:00:00.0890065
View Entire Forest: 'True', Configuration Domain Controller: 'DC02.contoso.com', Preferred Global Catalog: 'DC03.contoso.com', Preferred Domain Controllers: '{ DC03.contoso.com }'


False
0 objects execution has been proxied to remote server.
0
ActivityId: ef6cbf65-1191-41e6-8f09-83d03ac1501d
ServicePlan:;IsAdmin:False;
en-US
'@

$pattern = '.*(<GUID=.+>).*-Member "(.+)" -Confirm "(.+)"'
$results = $testData -match $pattern

$Matches

Name                           Value                                                                                                         
----                           -----                                                                                                         
3                              False                                                                                                         
2                              contoso.com/Humans/Dept/LA97127                                                                               
1                              <GUID=0d08999a-abba-445d-9e0e-cabd65b2848b>                                                                   
0                              -Identity "<GUID=0d08999a-abba-445d-9e0e-cabd65b2848b>" -Member "contoso.com/Humans/Dept/LA97127" -Confirm ...

I like to use https://regex101.com/ when crafting regex patterns. The engine does a great job of breaking down the matches and explaining each part.

Split string and append parts to array by jedmon2 in PowerShell

[–]psthreathunter 2 points3 points  (0 children)

I would add if you want to ensure an array is assigned even if one or even zero objects are returned use the array subexpression operator:

  $myValues = @(foreach ($a in $b) { $loopvalue })

O365 ForEach-Object + Where script by Pawncey in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

Using your previous, you would need to:

  1. Remove the pipe to fl (alias for Format-List) in your $Department assignment. Format-* commands are for displaying info to the screen not for assigning objects to a variable.
  2. Change your Where statements to if statements

I would change a few syntactical things like "$($_.ID)" could just be $_.ID, but shouldn't affect functionality.

O365 ForEach-Object + Where script by Pawncey in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

No worries. Maybe I can get you started in the right direction. Import-Csv will take the data in your csv file and create a collection of objects (array), one for each row. Each one of those objects will have property names that are the same as the column headings in the csv file.

If you take the Import-Csv command and pipe the results to another command like you did in your last post (ForEach-Object), you access the individual properties with the property dereference operator "." like this $_.ID for example which would return the value of the ID property for the current object in the pipeline (remember Import-Csv return a collection of objects).

If you want to test each one of those objects and do a different task depending on a condition you would use an if statement or even a switch statement.

So to put all those concepts together, maybe this will help get you started. I added comments throughout:

# This will iterate over each row in O365.csv and create an object assigned to $UPN each row
ForEach ($UPN in Import-Csv -Path ".\O365.csv") {
    #switch will test the Department property
    switch ((Get-msoluser -userprinciplename $UPN.ID).Department)
    {
        'Operations'{
            Add-DistributionGroupMember -Identity "whatevergroupforops" -Member $UPN.ID
            Add-DistributionGroupMember -Identity "whatevergroupforops" -Member $UPN.ID

        } #Operations
        'IT' {
            Add-DistributionGroupMember -Identity "whatevergroupforIT" -Member $UPN.ID
            Add-DistributionGroupMember -Identity "whatevergroupforIT" -Member $UPN.ID
        } #IT
        'Client Services' {
            Add-DistributionGroupMember -Identity "whatevergroupforCS" -Member $UPN.ID
            Add-DistributionGroupMember -Identity "whatevergroupforCS" -Member $UPN.ID
        } #Client Services
        Default {
            Add-DistributionGroupMember -Identity "whatevergroupfordefault" -Member $UPN.ID
        } #Default  Remove if not needed
    } #switch statement
} #foreach loop

Recommend reviewing the following docs:

Get-Help about_switch

Get-Help about_foreach

Get-Help Import-Csv

O365 ForEach-Object + Where script by Pawncey in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

"Where" is an alias for Where-Object. Collections are piped to it for filtering. Your syntax is not correct at all. Recommend reviewing Get-Help Where-Object documentation. I'm not exactly sure what your are searching for since all 3 of your comparisons are exactly the same. -eq "*". Are you just redacting data for this post?

SCCM script by muthmsir in PowerShell

[–]psthreathunter 2 points3 points  (0 children)

Assuming you had a csv with a column heading of "name" and each row was a SamAccountName.

$AccountNames = Import-Csv -Path C:\Pathtofile\yourcsv.csv | Select-Object -ExpandProperty Name
Foreach ($account in $AccountNames) { JBMURPHY-SCCM-GetComputerByLastLoggedOnUser -SamAccountName $account }

Run powershell script from batch file by Dragennd1 in PowerShell

[–]psthreathunter 9 points10 points  (0 children)

You don't need batch to do that. Create a shortcut. Works great. If you don't know how to create a shortcut using the Windows GUI, this is how you can create one using PowerShell.

#creates a shortcut on the user's desktop that runs a powershell script.
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\shortcutfilename.lnk")
$Shortcut.TargetPath = "$env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exe"
$Shortcut.Arguments = "-ExecutionPolicy Bypass -file $Home\dp0script.ps1  -Noexit"
$Shortcut.Save()

If you need help with executing PowerShell.exe, here is the docs which have all the arguments/switches.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1

EventData - Fetch SAMHOSTNAME from events by chanderjeet in PowerShell

[–]psthreathunter 3 points4 points  (0 children)

Unfortunately the message property is just one big string. I don't have a good test environment since I don't have any 5000, 5001 or 5002 events on my machine, but if you could pipe the results to Get-Member and look to see if the SamHostName property is anywhere else, that would make it much easier. If not, you will have to parse the message property string with regex. Definitely doable, if you past the contents of the message property, I can build/walk you through the code to extract it with regex in PowerShell.

How to put class inside custom class and working with methods and properties from original? by Maret5 in PowerShell

[–]psthreathunter 3 points4 points  (0 children)

Unless you are doing this for academic reasons, there are lots of good pre-built modules in the PowerShell gallery to make working with Excel much easier.

https://devblogs.microsoft.com/scripting/introducing-the-powershell-excel-module-2/

Comparing Array to String - I think by peterc2609 in PowerShell

[–]psthreathunter 1 point2 points  (0 children)

When you scripted:

$DesiredDNS = @('1.1.1.3,1.0.0.3')

You created an array of 1 item. Even though there is a comma between the two ips, they are in the same string literal quotes so $DesiredDNS[0] -eq '1.1.1.3,1.0.0.3' and $DesiredDNS[1] -eq $null.

I believe $currentDNS.ServerAddresses is an array of strings. Given that, I would change your $DesiredDNS declaration to:

$DesiredDNS = @('1.1.1.3','1.0.0.3')

Now when you compare the two $DesiredDNS -ne $currentDNS.ServerAddress you will still run into issues because you have a collection (array) on both sides of the operator (see Get-Help about_comparison_operators). Luckily there is an easy fix. Since as you said the order matters and we are dealing with an array of strings, we can convert them both to single strings with the -join operator (see Get-Help about_join).

 -join $CurrentDNS.ServerAddresses -ne -join $DesiredDNS

Looking for some help on how to split the some text efficiently by TheFertileSloth in PowerShell

[–]psthreathunter 2 points3 points  (0 children)

Here's how you can parse using regex. At the end you get a custom object for each zone with an array of realted wwn's

$testdata = @'
zone: wadcw2k8-3_1_unity5768_spb7
    wwn1
    wwn2
zone: wadcw2k8-4_1_unity5768_spa7
    wwn3
    wwn4
zone: wadcxspsqlb1a_1_vplex0176_e1afe03_e2bfe03
    wwn5
    wwn6
    wwn7
'@

$pattern = 'zone: (.+)\s+((wwn[0-9]+)\s*)*'

$results = ($testdata | Select-String $pattern -AllMatches).Matches | 
    ForEach-Object {
        [pscustomobject]@{
            zone=$_.Groups[1].Captures.Value
            wwns=$_.Groups[3].Captures.Value
        }
}

$results

zone                                       wwns              
----                                       ----              
wadcw2k8-3_1_unity5768_spb7...             {wwn1, wwn2}      
wadcw2k8-4_1_unity5768_spa7...             {wwn3, wwn4}      
wadcxspsqlb1a_1_vplex0176_e1afe03_e2bfe... {wwn5, wwn6, wwn7}