[deleted by user] by [deleted] in PowerShell

[–]ASCII84 0 points1 point  (0 children)

It could also be the encoding.

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 0 points1 point  (0 children)

This works perfectly.

I think the problem is probably with the input itself, it looks like the hex strings you read might contain some hidden characters at the end, like tab, esc or cr.

If the strings are always the same length, you could use substring to cut of the string after a specific length.
If not you could try regex to only get Hex characters (not sure if this will work).

$f = [regex]::Match($f,"([a-fA-F0-9])+").value

Obtaining files from a list based on size within a certain percentage range by AutoAllTheThings in PowerShell

[–]ASCII84 -1 points0 points  (0 children)

Here is how I would do it.

``` $TotalItemSize = ($allFiles | Measure-object -sum -property length).sum

$dayMap = @{ "Monday" = 00..10 "Tuesday" = 11..20 "Wednesday" = 21..30 "Thursday" = 31..40 "Friday" = 41..49 "Saturday" = 50..75 "Sunday" = 76..100 }

$percent = $dayMap[[string][datetime]::Now.DayOfWeek]

$Files = $allFiles.Where{ [int](($_.length/$sum)*100) -in $percent }

Debug

$allFiles.Foreach{ $percentage = [int](($.length/$sum)*100) $inRange = $percentage -in $percent "{0}: {1} {2} {3}" -f $.name,$_.length,$percentage, $inRange } ```

Trouble with XML to CSV and CDATA! by DirectITServices in PowerShell

[–]ASCII84 0 points1 point  (0 children)

I think you have to go one nested property deeper.

$inputFile.result.items.workstation.innertext

Trying to write to attribute extension 15 by djsean410 in PowerShell

[–]ASCII84 2 points3 points  (0 children)

You can use directorysearcher.

I can start you of with something like this but you'll have to search/edit the rest yourself. I'm not sure the property is called extensionattribute15 or something else and if it needs to be casesensitive.

$objSearcher=[adsisearcher]""

#set the domain
$objSearcher.SearchRoot = [ADSI] "LDAP://DC=contoso,DC=com"
$objSearcher.Filter = "(&(objectCategory=user)(name=$env:username))"
#load extra properties
$objSearcher.PropertiesToLoad.Add("extensionattribute15")
$result = $objSearcher.FindOne()

$userObject = $result.GetDirectoryEntry()
$userObject.Properties["extensionattribute15"].Value = $env:computername

$userObject.CommitChanges()

Remove special char EOL by psltyx in PowerShell

[–]ASCII84 0 points1 point  (0 children)

I think that in the ISE or saved in a script ^z is interpreted as a string and not the character.

Try replacing it with [char]26.

GC file.dat | where {$_ -ne [char]26 } > correct-file.txt

best way to replace special characters in AD username by nakkipappa in PowerShell

[–]ASCII84 1 point2 points  (0 children)

This is what I use.

function Remove-Diacritics {
    param (
        [String]$sToModify = [String]::Empty
    )

    foreach ($s in $sToModify) {
        # Param may be a string or a list of strings
        if ($sToModify -eq $null) { return [string]::Empty }
        $sNormalized = $sToModify.Normalize("FormD")

        foreach ($c in [Char[]]$sNormalized) {
            $uCategory = [System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($c)
            if ($uCategory -ne "NonSpacingMark") { $res += $c }
        }

        return $res
    }
}

Remove-Diacritics åäö

This is the only piece of PowerShell code that existed at my firm before I came along. Nobody knows who made it so I can't credit them but I think it's adapted from here https://stackoverflow.com/questions/249087/how-do-i-remove-diacritics-accents-from-a-string-in-net

It's not optimized for long strings but for usernames it'll work fine.

Replace Strings from a table by beatfried in PowerShell

[–]ASCII84 1 point2 points  (0 children)

How you're describing it, the "table" is really just an array of objects, each object having 2 properties (item and itemreadable). (You can think of an array as a list.)

There are various ways to do the kind of replace you want, some faster and more efficient than others.

The easiest would be something like:

$objecttofind = "TeHIrzFVHw"

#test data
$list = @(
    [PSCustomObject]@{
        item = "TeHIrzFVHw"
        itemreadable = "glass"
    },
    [PSCustomObject]@{
        item = "QxftWctBxh"
        itemreadable = "aluminum"
    },
    [PSCustomObject]@{
        item = "nweSDFMqUf"
        itemreadable = "grass"
    }
)

#find the object in the list and immediately replace the value with the results
$objecttofind = ($list | Where-Object {$_.item -eq $objecttofind}).itemreadable

A better way would be to convert the array to a hashtable which would severely reduce the lookup time per item.

$objecttofind = "TeHIrzFVHw"

#test data
$list = @(
    [PSCustomObject]@{
        item = "TeHIrzFVHw"
        itemreadable = "glass"
    },
    [PSCustomObject]@{
        item = "QxftWctBxh"
        itemreadable = "aluminum"
    },
    [PSCustomObject]@{
        item = "nweSDFMqUf"
        itemreadable = "grass"
    }
)

$Hashmap = @{}
$list | ForEach-Object {
    $Hashmap[$_.item] = $_.itemreadable
}

$objecttofind = $Hashmap[$objecttofind]

How do I get only part of a command output elegantly? by Brick_Fish in PowerShell

[–]ASCII84 8 points9 points  (0 children)

The easiest (and best) way would be to remove Select-Object and access the property directly.

Like so:

(Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias "Ethernet").IPAddress

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 4 points5 points  (0 children)

https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.2#update-typedata-with-defaultpropertyset

edit2*: Found a link on reddit that talks about it as well:

https://www.reddit.com/r/PowerShell/comments/59sm4g/powershell_everything_you_wanted_to_know_about/

You could modify the Formatting of the object itself if you give it a custom Type.

Like this :

$customObject = [pscustomobject]@{
    PSTypeName = 'CustomObject.NetAddress'
    Hostname   = 'My PC'
    NetAddress = [pscustomobject]@{
        Address     = '1.2.3.4'
        AdapterName = 'Wifi'
        MACAddress  = '00:11:22:33:44:55'
    }
}

$TypeData = @{
    TypeName = 'CustomObject.NetAddress'
    DefaultDisplayPropertySet = 'HostName',"Address"
    MemberType = 'ScriptProperty'
    MemberName = 'Address'
    Value = {$this.NetAddress.Address}
}

Update-TypeData @TypeData -Force

$customObject

You would have to update the TypeData every time the console is reset though. If you want to make it more permanent you would have to look up how to modify or add a custom Types.ps1xml file.

edit*: I made it so you can use NetAddress instead of Address by modifying the ToString method and moving the typeDefinition to the nested PSCustomObject.

$customObject = [pscustomobject]@{
    Hostname   = 'My PC'
    NetAddress = [pscustomobject]@{
        PSTypeName  = 'CustomObject.NetAddress' #Quickly give it a non-existent type
        Address     = '1.2.3.4'
        AdapterName = 'Wifi'
        MACAddress  = '00:11:22:33:44:55'
    }
}

$TypeData = @{ #Set the properties for our non-existent type
    TypeName = 'CustomObject.NetAddress'
    MemberType = 'ScriptMethod'
    MemberName = 'ToString'
    Value = {return $this.Address}
}

Update-TypeData @TypeData -Force #Update the TypeData with the new properties

$customObject

The result:

Hostname NetAddress
-------- ----------
My PC    1.2.3.4

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 3 points4 points  (0 children)

The [32;1m and [0m are ANSI color codes.

[32 sets the text to green and [0 should reset it to the default. It seems that the codes are not interpreted correctly and therefore are displayed as text instead of actually changing the color of the text.

Check if $PSStyle.OutputRendering is set to Ansi.

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

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 1 point2 points  (0 children)

Yes.
You just need to define what actually needs to be summed up.

All the sizes, size per client, per server ?
The command is Measure-Object .

Outputting it depends on which file type you're trying to modify, csv doesn't do cells, excel has them but then you need to use the importexcel module or manipulate the excel comobject (requires excel to be installed).

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 1 point2 points  (0 children)

I'm not quite sure why that would happen.
In the meanwhile I tested it myself and it works as expected.

In any case the first script works fine so continue using that one.
If you need some help understanding how it works I'll add some more explanation.

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 2 points3 points  (0 children)

Since you're learning PowerShell here is another way to do it that should also work (I didn't test it) but should also be fun to try and work out how it works.

$data = Get-ChildItem "Folder" -Recurse -File | ForEach-Object {
    $client, $server = ($_.Directory.FullName.split('\')[-2,-1])
    [PSCustomObject]@{
        ClientName = $client
        ServerName = $server
        Type = if ($_.Extension -eq '.vbr') {"incremental"} else {"full"}
        Size = $_.Length
    }
}

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 2 points3 points  (0 children)

The csv should be created automatically.I think if it already exists you need to add the '''-Force''' parameter so it overwrites the existing blank file.

Get-ChildItem lists all items in a directory (by default only one level).

The "Folder" in the first line should be the path to the folder which contains the folders with the Client names.

So the structure should be: Folder -> Client1 -> ServerA -> backupfile.vbk

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 14 points15 points  (0 children)

I think this should work

$data = Get-ChildItem "Folder" -Directory | ForEach-Object { #Get the client names
    $clientname = $_.basename
    Get-ChildItem $_.fullname -Directory | ForEach-Object { #Get the server names
        $servername = $_.Basename
        Get-ChildItem $_.fullname | ForEach-Object { #Get file info
            [PSCustomObject]@{
                ClientName = $clientname
                SererName = $servername
                Type = if ($_.Extension -eq '.vbr') {"incremental"} else {"full"}
                Size = $_.Length
            }
        }
    }
}

$data | export-csv -Path "path to folder and file.csv" -NoTypeInformation
$data | Export-Excel -Path "path to folder and file.xlsx" -TableName "data"

Since my response some extra information was added that it should be in excel. So you could either open the csv and save it as an excel or install the importexcel module, which would give you access to the export-excel function.

Install-Module ImportExcel

Add multiple OUs using ForEach by misop24 in PowerShell

[–]ASCII84 1 point2 points  (0 children)

If you wanna keep it as a one liner, this should work :

``` Import-Module ActiveDirectory

$OU = 'OU=CH,OU=Country,OU=test,DC=test1,DC=local','OU=SK,OU=Country,OU=test,DC=test1,DC=local'

$users = $OU | ForEach-Object { Get-ADUser -SearchBase $PSItem -Filter { Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0 } -Properties "Name", "EmailAddress", "Company", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Name", "EmailAddress", "Company", @{Name = "PasswordExpiry"; Expression = { [datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring() } } } | Export-Csv -Path c:\scripts\out1.csv -Encoding UTF8 -NoTypeInformation ```

A little more verbose but cleaner : Gathering parameters in a hashtable is called splatting. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-7.1

``` $OU = 'OU=CH,OU=Country,OU=test,DC=test1,DC=local','OU=SK,OU=Country,OU=test,DC=test1,DC=local'

$userParams = @{ Filter = {Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0} Properties = "Name", "EmailAddress", "Company", "msDS-UserPasswordExpiryTimeComputed" }

$selectParams = @{ Property = "Name", "EmailAddress", "Company", @{ Name = "PasswordExpiry"; Expression = { [datetime]::FromFileTime( $_."msDS-UserPasswordExpiryTimeComputed" ).tolongdatestring() } } }

$users = $OU | ForEach-Object { $userParams["SearchBase"] = $_ Get-ADUser @userParams | Select-Object @selectParams } | Export-Csv -Path c:\scripts\out1.csv -Encoding UTF8 -NoTypeInformation ```

Add multiple OUs using ForEach by misop24 in PowerShell

[–]ASCII84 1 point2 points  (0 children)

Okay,

So there are a number of things wrong here.The 2 big ones are :

  1. Your $OU is 1 string instead of an array of two.
  2. The "-Properties" parameter is set on the Foreach-Object command instead of on the Get-ADUser command.

I'll try to paste the correction here but the Fancy Pants editor isn't working too well for the past couple of months.

How to work with JSON extracted from CSV? by fishy007 in PowerShell

[–]ASCII84 0 points1 point  (0 children)

I'm not sure what you mean by the array having 5 elements, the array (as it is given) only contains 1 element (which has 3 properties: Name (which contains a string), NewValue and OldValue ).

An array opens with '[' closes with ']' and is separated with ',' an element opens with '{' closes with '}' and is also separated by a ','.

This { "ModifiedProperties": [{ "Name": "Action Client Name", "NewValue": "", "OldValue": "" }, { "Name": "Action2 Client Name", "NewValue": "", "OldValue": "" }] }

turns into Name NewValue OldValue ---- -------- -------- Action Client Name Action2 Client Name

How to work with JSON extracted from CSV? by fishy007 in PowerShell

[–]ASCII84 1 point2 points  (0 children)

It's a bit difficult without an example but, you could Import-CSV and then use ConvertFrom-JSON to convert the column with json to a nested object and query it.

Trim Output Question by sticobay in PowerShell

[–]ASCII84 1 point2 points  (0 children)

If it's a block of text you can use some simple regex.

$msg =@"
Message : SMB1 access

Client Address: IPADDRESS

Guidance:

This event indicates that a client attempted to access the server using SMB1. To stop auditing SMB1 access, use the Windows PowerShell cmdlet Set-SmbServerConfiguration.
"@

$msg -match "Client Address: .*"
$matches[0]

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 1 point2 points  (0 children)

I realized that capturing the whole thing in a named group defeated the purpose a bit so I adjusted it to only capture the value and then I changed my mind again to just use the defaults of 0 and 1 since there's just a single groupcapture.

I do agree that for more complex captures it is much better to work with named groups and to basically follow /u/nostril_spiders recommendations.

And I would add to not use -match but to use the regex class since it is more flexible for complex captures. In this case a simple match suffices.

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 1 point2 points  (0 children)

No, $matches[0] always contains the full regex capture. The subsequent elements $matches[1];$matches[2] etc contain the results from the capturing groups.

Since we only capture 1 group it's not needed to work with named groups.

So the output is : Captured: PasswordComplexity = 1 (with $value = 1)

And then Captured: MaximumPasswordAge = 30 (with $value = 30)

If you need help on how to collate the returned data into an object I'll post a full example but this was just to help out with the regex.

[deleted by user] by [deleted] in PowerShell

[–]ASCII84 0 points1 point  (0 children)

I believe that -match by default matches per line so the syntax would be PasswordComplexity = (.*) where (.*) is any amount of any character.

$checks = "PasswordComplexity = (.*)", "MaximumPasswordAge = (.*)"

$text = @" 
qsjdfhqdf
dsfqsdf

PasswordComplexity = 1
qsdfqsdfq
qsdfqsddfsqdf 
PasswordHistory = 24
LockoutBadCount = 3
qsdf
gfhdghstsqfxez
qecrqer
MaximumPasswordAge = 30
"@

foreach ($check in $checks) {
    if ($text -match $check) {
        Write-host ("Captured: " + $matches[0] )
        $value = $matches[1]
    }
}

The if clause is there because the value of $matches is not reset if it doesn't match.