get the whole value of powershell objects - string

I am executing a Get-ADDomain command
I was fetching the output given by the command
And I noticed that it is not giving the full list of objects it is just listing some of those and then end with ... have attached the image for reference
I realized it might be problem with the width of the output and it must be using the default width
So while executing the command I also set Out-Width as 1000 but it gives more values but still the same problem persists and increasing the width any further does not have any impact on the output
Is there any way by which I can capture the whole value itself. I have faced this issue with other commands as well. This is the command I executed :
Get-ADDomain | Select-Object LinkedGroupPolicyObjects| Out-String -Width 1000

You should use -ExpandProperty and work with the objects, rather then converting them to a string with out-string.
$LinkedGPOs = Get-ADDomain | Select-Object -ExpandProperty LinkedGroupPolicyObjects
foreach($LinkedGPO in $LinkedGPOs) {
}

Related

Trim powershell output after a specific line

When running the sfc /scannow command from a powershell script, how do you trim the output to only keep all the data after "Verification 100% complete."?
Simple code example:
$Result = Invoke-Command { sfc /scannow } | Out-String
A truncated version of this output is:
Verification 97% complete.
Verification 98% complete.
Verification 98% complete.
Verification 99% complete.
Verification 99% complete.
Verification 100% complete.
Windows Resource Protection found corrupt files and successfully repaired them.
For online repairs, details are included in the CBS log file located at
windir\Logs\CBS\CBS.log. For example C:\Windows\Logs\CBS\CBS.log. For offline
repairs, details are included in the log file provided by the /OFFLOGFILE flag.
I also wouldn't mind removing the extraneous line breaks so the final output when returning $Result would simply be:
Windows Resource Protection found corrupt files and successfully repaired them. For online repairs, details are included in the CBS log file located at windir\Logs\CBS\CBS.log. For example C:\Windows\Logs\CBS\CBS.log. For offline repairs, details are included in the log file provided by the /OFFLOGFILE flag.
I have a 1024 character limit for the output, and right now I'm just truncating it with the following:
if ($Result.length -gt 1024) {
$Result = $Result.Substring($Result.Length-1024)
}
But I'd like to get rid of all the "status" type messaging from the output and just retain the final result of the scan.
Thank you!
First and foremost this is an encoding issue. The sfc command outputs UTF-16, but PowerShell doesn't know that (because it's a native command), so you typically get embedded null characters between the actual characters (try sfc /? | Out-String | Format-Hex to see what I mean).
Removing the embedded null characters would only partially fix the symptoms. On non-english systems the encoding of non-ASCII characters will still be wrong.
To fix the cause, you have to tell PowerShell the output encoding used by the command (see this answer for background, albeit it focuses on UTF-8):
# Save the current encoding settings and temporarily switch to UTF-16 (aka UnicodeEncoding).
$oldOutputEncoding = $OutputEncoding; $oldConsoleEncoding = [Console]::OutputEncoding
$OutputEncoding = [console]::OutputEncoding = New-Object System.Text.UnicodeEncoding
# No need for Invoke-Command. Just call it directly.
$result = sfc /scannow | Out-String
# Restore the previous settings.
$OutputEncoding = $oldOutputEncoding; [Console]::OutputEncoding = $oldConsoleEncoding
# Encoding fixed, but duplicate newlines remain. Replace them by single newlines:
$result = $result -replace '\r?\n\r?\n', [Environment]::NewLine
#Finally strip off everything up to and including the `100%` line:
$result = ($result -replace '(?s)^.*100\s*%.*?\r?\n').Trim()
See this RegEx101 demo for an explanation of the RegEx used by the last -replace command. Note that (?s) enables single-line mode so dot . matches newlines.

Powershell: How to get the location of a file, depending on its name?

So my task is to write a PS script, that outputs the location of a database file. The location of the file is:
C:\Program Files\Microsoft\Exchange Server\V15\Mailbox\Mailbox database Name\Mailbox database Name.edb
I figured I can get the name of my Exchange database with
Get-MailboxDatabase | fl Name
which has the output:
Mailbox Database 0161713049
which is the name of the db but there is a bunch of invisible characters before and after the actual name.
So my question is, how could I get rid of these invisible characters? I want to concat a string to make it look like this:
C:\Program Files\Microsoft\Exchange Server\V15\Mailbox\Mailbox Database 0161713049\Mailbox Database 0161713049.edb
I would need this code to work on servers with completely different database names too, so simply removing the unwanted characters from the start with .Remove() may help, but since I don't know for sure the length of the name of the database, I can't remove the characters at the end.
Also I can't get rid of the feeling that there is a much simpler way to get the location of my .edb file.
Powershell treats almost all outputs as an object with properties in hashtable format like #{Name=MYEXCHDB}. When you just want a property value as a string instead, you must expand it like #AdminOfThings suggests:
Get-MailboxDatabase | Select-Object -ExpandProperty Name
To concatenate the name into a string:
$myString = "C:\path\to\$(Get-MailboxDatabase | Select-Object -ExpandProperty Name)"
And as #mathias-r-jessen suggests, the path to the database is another property you can get directly:
Get-MailboxDatabase | Select-Object -ExpandProperty EdbFilePath | Select-Object -ExpandProperty PathName

How can I convert installdate to a different format?

I am trying to run this command on cmd:
wmic:root\cli>/node:IPAddress product get name, version, vendor, installdate
IPAddress can be replaced with whatever address or hostname is desired.
The command does not give me any errors, however, it gives me installdate in MMMMYYDD form (for example, 20170801 instead of something simple like 01-Aug-2017 or 2017/08/01). I have tried to look for solutions online, but they're usually talking about system installations instead of product installations.
I know that installdate is a string, so this is more a question of how should I convert this string into a date. I tried using '+%Y%m%d' after the installdate, but it gave me an error: Invalid GET Expression.
If you can use PowerShell, it is not too difficult. You can control the format you want in the ToString method.
Get-CimInstance -ClassName CIM_Product |
Select-Object -Property #{n='Name';e={$_.Name}}, #{n='Date';e={([datetime]::ParseExact($_.InstallDate,'yyyyMMdd', $null)).ToString('dd-MMM-yyyy')}}

Find and replace a specific string within a specific file type located in wildcard path

Problem:
Update a specific string within numerous configuration files that are found within the subfolders of a partial path using PowerShell.
Expanded Details:
I have multiple configuration files that need a specific string to be updated; however, I do not know the name of these files and must begin my search from a partial path. I must scan each file for the specific string. Then I must replace the old string with the new string, but I must make sure it saves the file with its original name and in the same location it was found. I must also be able to display the results of the script (number of files affected and their names/path). Lastly, this must all be done in PowerShell.
So far I have come up with the following on my own:
$old = "string1"
$new = "string2"
$configs = Get-ChildItem -Path C:\*\foldername\*.config -Recurse
$configs | %{(Get-Content $_) -Replace $old, $new | Set-Content $_FullName
When I run this, something seems to happen.
If the files are open, they will tell me that they were modified by another program.
However, nothing seems to have changed.
I have attempted various modifications of the below code as well. To my dismay, it only seems to be opening and saving each file rather than actually making the change I want to happen.
$configFiles = GCI -Path C:\*\Somefolder\*.config -Recurse
foreach ($config in $configFiles) {
(GC $config.PSPath) | ForEach-Object {
$_ -Replace "oldString", "newString"
} | Set-Content $config.PSPath)
}
To further exasperate the issue, all of my attempts to perform a simple search against the specified string seems to be posing me issues as well.
Discussing with several others, and based on what have learned via SO... the following code SHOULD return results:
GCI -Path C:\*\Somefolder\*.config -Recurse |
Select-String -Pattern "string" |
Select Name
However, nothing seems to happen. I do not know if I am missing something or if the code itself is wrong...
Some questions I have researched and tried that are similar can be found at the below links:
UPDATE:
It is possible that I am being thwarted by special characters such as
+ and /. For example, my string might be: "s+r/ng"
I have applied the escape character that PowerShell says to use, but it seems this is not helping either.
Replacing a text at specified line number of a file using powershell
Find and replacing strings in multiple files
PowerShell Script to Find and Replace for all Files with a Specific Extension
Powershell to replace text in multiple files stored in many folders
I will continue my research and continue making modifications. I'll be sure to notate anything that get's me to my goal or even a step closer. Thank you all in advance.

Trying to Export a CSV list of users using Active Directory Module for Windows Powershell

So the below is where I'm at so far:
import-module activedirectory
$domain = "ourdomain"
Get-ADUser -Filter {enabled -eq $true} -Properties whenCreated,EmailAddress,CanonicalName |
select-object Name,EmailAddress,CanonicalName,whenCreated | export-csv C:\Data\test.csv
Unfortunately, when I run the above I get dates in two different formats in the CSV, e.g.:
01/01/2017
1/01/2017 8:35:56 PM
The issue this poses is that there isn't really a clean way to sort them. Excel's formatting doesn't change either of these formats to be more like the other, both because of the inclusion of time in one and not the other, and because the time-inclusive format doesn't use trailing zeroes in the single digit numbers, but the time-exclusive format does.
We have an existing script that captures users using the LastLogonTimestamp attribute that does this correctly by changing the bottom line to the following:
select-object Name,EmailAddress,CanonicalName,#{Name="Timestamp"; Expression={[DateTime]::FromFileTime($_.whenCreated).ToString('yyyy-MM-dd_hh:mm:ss')}}
For some reason this expression runs properly when we query the LastLogonTimestamp attribute, but when we run this version querying the whenCreated attribute, we get an entirely blank column underneath the Timestamp header.
I'm not particularly knowledgeable about PowerShell itself, and my colleague who had found the original script for the LastLogonTimestamp just found it online and adapted it as minimally as possible to have it work for us, so I don't know if something in this line would work properly with one of these attributes and not the other. It seems strange to me though that two attributes using dates in the same program would store them in different formats though, so I'm not convinced that's it.
In any case, any help anyone can offer to help us get a uniform date format in the output of this script would be greatly appreciated - it needn't have the time included if it's easier to do away with it, though if they're equally easy we may as well keep it.
whencreated is already a [DateTime]. Notice the difference between the properties when you run something like this:
Get-ADUser TestUser -Properties lastlogon,whenCreated | select lastlogon,whenCreated | fl
(Get-ADUser TestUser -Properties lastlogon).lastlogon | gm
(Get-ADUser TestUser -Properties whenCreated).whenCreated | gm
This means that you don't have to convert to a DateTime before running the toString() method.
select-object #{Name="Timestamp"; Expression={$_.whenCreated.ToString('yyyy-MM-dd_hh:mm:ss')}}

Resources