Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
How sure are you that you're running v1? I'm pretty sure 2008 SP2 has v2 already. Try looking at $psversiontable. If it exists, you're running v2. If not you are indeed on v1.

E: \/\/ I guess I was wrong, since that is definitely what one would expect from v1.

Jethro fucked around with this message at 21:36 on Dec 2, 2011

Adbot
ADBOT LOVES YOU

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

Moey posted:


Thanks again everyone!

Edit: Just out of curiosity sake, how would I add "where-object {$_.psiscontainer -eq false}" to my last line of code there? Everything I try breaks it.

code:
#Renames file to append crap user wants
gci | where-object {$_.psiscontainer -eq $false} | rename-item -newname {$_.basename + " - Cat Picture.tif"}

#Creates folders based on first 9 chars
gci | where-object {$_.psiscontainer -eq $false} | %{new-item -name $_.tostring().substring(0,9) -type directory -path .}

#moves files into folders based on file number
gci | where-object {$_.psiscontainer -eq $false} | %{move-item -path $_.name -destination "$($_.directoryname)\$($_.tostring().substring(0,9))\$($_.name)" }
Note that it's $false not false

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

Siets posted:

Looks good, but do sub-expressions work inside of other sub-expressions? So I would ultimately have:

[regex]"(?<Amount>\d{1,3}(\,\d{3})*)"

edit: Removing instances of 134,04 and the like!
edit2: Crap, is ?<Amount> a Powershell-only syntax for use with -match, and doesn't work inside of .NET [regex]'s?
That's the standard .NET syntax for a named capture group, not just PowerShell. Is it giving you problems?

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
It seems to me that it would make a lot more sense to import this into a database of some sort (assuming it's not already in one) or Excel or something, since those tools are more or less designed to do this sort of thing.

If you really need to do this all in Powershell, I'd suggest you start by creating objects and adding properties see here.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
The Get-Date cmdlet can take a date, so something like [int](Get-Date -UFormat %V -Date $_.CreationTime) would get you what you want.

Add-Member wouldn't really help you here, because it only adds the member to a particular object instance.

Jethro fucked around with this message at 18:54 on Jan 11, 2012

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

adaz posted:

first solution

String.Split has a count parameter which you can use to limit the number of elements in the array. Also, if you use the -split operator (PS 2.0+), you can use regexes.
code:
$formatTable = @{}
foreach($line in $strlines) {
    $splitLine = $line -split "\s*:\s*", 2
    # this returns an array with a maximum of 2 elements.
    # Also, whitespace on either side of the : is discarded. 

    if($splitLine -is [system.array] -and $splitLine.Count = 2) {
       # first element is always going to be our key, I assume you don't want the white space so we trim that out and add it.
       # Still using fulltrim in case the key has leading whitespace
       $key = $splitLine[0].fulltrim
       $value = $splitLine[1]
       # make sure we aren't trying to add an empty key which will error out on us...
       if($key -ne [string]::empty) {
           $formatTable.add($key,$value)
       }
    }else {
      # Line with no : ! Unable to process, probably better write out an error or something here.
      write-host "Unable to process the line $line no : found in input string!"
    }
}

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

jonnii posted:

I added cmdletbinding, changed all the write-hosts to write-verbose, removed most of the aliases (what does mkdir alias to? is it new-item?).
Technically mkdir is not an alias, but a function that calls New-Item with -Type Directory

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
One workaround I just tested is to stick | Out-String -Stream | Select-String "." after the Format-Table. This will only print the lines that aren't blank.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

AreWeDrunkYet posted:

I'm not having any luck googling this, does anyone know how to use a substring in a get-adcomputer filter? So, for example, let's say a naming convention is STATECITY00006, and I want all of the computers in Utah, I would assume the command would be

code:
get-adcomputer -filter {name.substring(0,4) -eq "UTAH"}
Doing this returns

code:
Error parsing query ... 'Operator not supported' at position
where it is trying to use the substring function, so it appears that is not supported. Is this a syntax error on my end, or is there some sort of workaround to use substrings in these queries?

code:
get-adcomputer -filter {name -like "UTAH*"}
?

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
Maybe define $outputcsv before the loop (assuming you weren't already) just so powershell knows it's an array:
code:
$inputcsv = import-csv path\input.csv
$outputcsv = @()
foreach ($line in $inputcsv)
{
    $splitline = $line.'property'.Split(";")
    $splitline    #debug echo
    $outputcsv += $splitline
}
$outputcsv | export-csv -path path\output.csv
Or in one-line form:
code:
import-csv path\input.csv | %{$_.property -split ";" } | export-csv -path path\output.csv

Jethro fucked around with this message at 19:08 on Apr 25, 2014

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

MJP posted:

So I have to do a big broad discovery for a consultant. I need to get some hardware stats - disk space, make/model, etc. - and it looks like I can use get-wmiobject to do so. (I'm open to other methods, so long as I can gather total disk space, used disk space, etc.)

I was able to use get-adcomputer to get a list of all computer objects in AD, and I've piped it to an array. But whenever I run the command below in Powershell with Active Directory module (logged on as a domain admin, launching Powershell as administrator):
code:
get-wmiobject win32_logicaldisk -computer $computers
I get a bunch of the following:
code:
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) At line:1 char:14 + get-wmiobject <<<<win32_logicaldisk -computer $computers   
+ CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException   + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
If I try to use test-connection -computer $computers I get nothing but errors that a non-recoverable error has occurred during database lookup. I can ping any computer in $computers and get a response.

Our environment has Windows Firewall off for all connections via group policy, and we don't filter or firewall any internal traffic. I used Lansweeper Connectiontester to test connections, and it shows port 135 as open and WMI access tests OK to any computers I use.

I am running all this from one of our domain controllers.

Anyone know what else I should be trying?

Edit: I can rpcping other machines without issue from the domain controller I'm using for this.
Are you sure $computers is an array of strings, as opposed to some sort of array of ad results or something like that?

Also, what happens when you manually run Get-WmiObject for one of the computers in question?

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

MJP posted:

$computers is a list of computers. I took an export from get-adcomputer piped to CSV, removed all other columns and rows not in use, saved as CSV, and confirmed that there were no trailing spaces. So it should fit a list of string values.

If I run get-wmiobject against a remote computer manually, it runs just fine.

Get-Adcomputer returns a list of Microsoft.ActiveDirectory.Management.ADComputer objects, not a list of strings. So maybe something like
code:
$computers | %{get-wmiobject win32_logicaldisk -computer $_.name}

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
That works, though I don't see why you'd need to do that when you could just use -and.
code:
Get-Mailbox -resultsize unlimited | where {$_.ExchangeUserAccountControl -eq 'AccountDisabled' -and $_.Name -notlike '*Conference*'} | Set-Mailbox -HiddenFromAddressListsEnabled $true

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
$disconnecteds is a collection of records, so $disconnectds.Id doesn't make any sense because $disconnecteds doesn't have an Id, it has records, and those records have Ids.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

beepsandboops posted:

Trying to wrap my head around when it's appropriate to use parameters and when it's not. I have a script that onboards a new user and takes input like their name, start date, etc. using Read-Host.

For stuff like that, is it better to just wrap it all into a param block? When does it make sense to use Read-Host instead?

Not only is param more extensible, you can also just create a prompt with Read-Host in the parameter definition.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

beepsandboops posted:

Oh, interesting. I was setting them up like:
code:
[Parameter(HelpMessage="Please provide the username")]
[string]$username
But you're saying I could also do

code:
[Parameter]
[string]$username= Read-Host "Please provide the username"

Correct*. In essence, you are setting the default to be the input from Read-Host.

*: the syntax is actually [string]$username= $(Read-Host "Please provide the username")

Jethro fucked around with this message at 20:27 on Mar 8, 2016

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
Measure-Object doesn't return the sum, it returns an object that has a Count, Sum, Average, etc. properties, and the ones you specify when you call the cmdlet are the ones that are populated (Count is always populated). This means that you can get the file size and file count in one pass.
code:
$FS1Log = "c:\software\FS1Log.csv"
$root = "\\fileserver\Departments\Technology"

$FileStats = (Get-ChildItem $root -Recurse | Measure-Object -property length,PSisContainer  -sum)
$rootCount = ($FileStats | Where-Object {$_.Property -eq "PSisContainer" }).Count
$rootSize = ($FileStats | Where-Object {$_.Property -eq "length" }).Sum
Add-Content $FS1Log $root, $rootCount, $rootSize

ForEach ($Folder in $(Get-ChildItem $root | Where-Object {$_.PSisContainer -eq $True})){

    $FileStats = (Get-ChildItem $folder.FullName -Recurse | Measure-Object -property length,PSisContainer  -sum)

    $size = ($FileStats | Where-Object {$_.Property -eq "length" }).Sum

    $FileCount = ($FileStats | Where-Object {$_.Property -eq "PSisContainer" }).Count

    Add-Content $FS1Log $Folder, $FileCount, $size
}
(If it's OK for the folders to not be included in the file count, you can simplify the above a great deal)

I don't think you can recurse a set number of levels, so if you want to do all the department folders at once, you just have to put another ForEach around the existing one.

code:
$FS1Log = "c:\software\FS1Log.csv"
$base = "\\fileserver\Departments"
ForEach ($root in $(Get-ChildItem $base | Where-Object {$_.PSisContainer -eq $True})){

	$FileStats = (Get-ChildItem $root.FullName -Recurse | Measure-Object -property length,PSisContainer  -sum)
	$rootCount = ($FileStats | Where-Object {$_.Property -eq "PSisContainer" }).Count
	$rootSize = ($FileStats | Where-Object {$_.Property -eq "length" }).Sum
	Add-Content $FS1Log $root.FullName, $rootCount, $rootSize

	ForEach ($Folder in $(Get-ChildItem $root.FullName | Where-Object {$_.PSisContainer -eq $True})){

		$FileStats = (Get-ChildItem $folder.FullName -Recurse | Measure-Object -property length,PSisContainer  -sum)

		$size = ($FileStats | Where-Object {$_.Property -eq "length" }).Sum

		$FileCount = ($FileStats | Where-Object {$_.Property -eq "PSisContainer" }).Count

		Add-Content $FS1Log $Folder, $FileCount, $size
	}
}

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
$VerbosePreference = "SilentlyContinue"

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

CzarChasm posted:

[snip]
code:
$query = $url + "/" + $message.Id + "/Sender/EmailAddress/Name"
$TEMP = Invoke-RestMethod $query -Credential $cred
$SenderName = $Temp.Value
EDIT Nevermind. This was exactly it. Though there might be a more efficient way to do this. Can I do something like

code:
$query = $url + "/" + $message.Id
$TEMP = Invoke-RestMethod $query -Credential $cred
$SenderName = $Temp.sender.emailaddress.name.value
$SenderEamil = $Temp.sender.emailaddress.address.value
$DateSent = $Temp.datetimecreated.value
Looking at the O365 API Documentation, you can use $select to get only the specific properties that you want. So you'd want to do something like
code:
#untested because I don't have access to O365
$query = $url + "/" + $message.Id + "=?`$select=Sender/EmailAddress,DateTimeCreated"
$queryResponse = Invoke-RestMethod $query -Credential $cred
And then do what Pile Of Garbage said to see how the result is deserialized.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
Yes, move usually has the same effect as copy and delete original. The verbiage "This creates a new copy of the message in the destination folder." is a little ambiguous, but I take that to mean that the message in the destination folder has a new message_id and the old message_id now refers to a message that doesn't exist (or is in some deleted location or status).

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
From About Quoting Rules

quote:

When you enclose a string in double quotation marks (a double-quoted string), variable names that are preceded by a dollar sign ($) are replaced with the variable's value before the string is passed to the command for processing.
[snip]
When you enclose a string in single-quotation marks (a single-quoted string), the string is passed to the command exactly as you type it. No substitution is performed.
[snip]
Or, double the quotation marks around a double-quoted phrase.

So, if you want to substitute variables into strings while still having " in the string, use " to surround the string and use "" in it.

code:
aws workspaces create-workspaces --workspaces "DirectoryId=blahblah,UserName=$($user.SamAccountName),RootVolumeEncryptionEnabled=True,UserVolumeEncryptionEnabled=True,VolumeEncryptionKey=arn:aws:kms:stuffheretoothatdoesntmatter,WorkspaceProperties=""{RunningMode=AUTO_STOP,RunningModeAutoStopTimeoutInMinutes=60,RootVolumeSizeGib=80,UserVolumeSizeGib=50}"""
Or just do the string concat like The Fool said.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

New Yorp New Yorp posted:

I hate PowerShell sometimes.

Let's say I have this:
code:
$butts = @(
    @{ x = 'thingy' }
)
I pipe it to ConvertTo-Json.
code:
$butts | ConvertTo-Json
Expected:
code:
[
    {
        "x":  "thingy"
    }
]
Nope. I get:
code:
{
    "x":  "thingy"
}
I explicitly said it was an array because it should be an array, PowerShell.

Meanwhile, this works correctly:
code:
ConvertTo-Json -InputObject $butts
This wasted 15 minutes of my time today and I wasn't thrilled about it.

So I had a mini-rant here talking about how I somewhat agreed with you, but most of the time when you are piping stuff you want to operate on the members of the collection so we'll just have to deal... and then I discovered the unary , operator.
code:
,$butts | ConvertTo-Json

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
Edit: an explanation of the difference between unary , and @() https://blogs.msdn.microsoft.com/powershell/2007/01/23/array-literals-in-powershell/

True edit: Quote -ne edit

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
I agree it's somewhat unintuitive, but it also makes sense when we remember that Powershell is first and foremost designed to be a shell script environment. In that sort of environment, most of the time (especially when you're piping stuff around) you want to do stuff to the stuff in the collection, not to the collection itself. So to help you with this, when you ask Powershell to evaluate an array, it returns the members of the array.
@( @{ a = 'b' }, @{ c = 'd' }) as a statement all by itself essentially says "create an array with two hashtables, then return the individual hashtables."

Then there's something else that Powershell does that is usually helpful, but also may be somewhat unintuitive. When you are piping things along, the cmdlets and functions have begin, process, end blocks, so it can do something at the start (like create the object that will be converted to JSON), do something for each item in the pipeline (like add it to the object (while also being smart about adding the members of hashtables as members of the object instead of adding the hashtables themselves)), and then do something at the end when all the processing is done (like return one JSON representation).

So, if you want to have ConvertTo-Json return an array, you can either pass it an array as a parameter or put your array in an array and pipe that (which then, in effect, takes the inner array out and passes that to the cmdlet). And to put your array in an array, you need to use the , operator to create the array, because @() doesn't create arrays, it converts to arrays, which means if you are trying to put a single array inside another array, @($some_array) is a no-op because it's already an array.

Oh, or you can play around with the -AsArray switch parameter on ConvertTo-Json.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

Judge Schnoopy posted:

You're blowing my loving mind here. This is the most useful thing I think I've ever read in this thread.
I had no idea about , and the true meaning of @() until I looked it up the other day, so thank you, New Yorp New Yorp, for giving me a reason to finally learn about one of the parts of Powershell that no one gets right in posted snippets.

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

Rocko Bonaparte posted:

Just to be certain here: when talking about "ambiguity" and things like that, are we talking sometimes it does one thing and sometimes another? My situation is statistical right now and I want to know where something could be inconsistent. I'd expect these boolean conditions to work consistently. I mean, garbage-in-garbage-out in terms of the variables, but I wouldn't expect Powershell to decide to change the order of operations run-to-run. That would be a real kick in the pants.

Pile Of Garbage posted:

All operators in PowerShell behave consistently as documented which I mentioned in an earlier post.
Right, FISHMANPET was talking about ambiguity in terms of how Powershell interprets a statement versus the ways a person could interpret it. Powershell is going to do the same thing every time, but if you've got a complicated enough expression, what Powershell does may not be what the writer intended, or what the next person reading the code thinks is going to happen, unless they've got the About Operator Precedence reference open on another monitor. So liberally sprinkling parentheses in your comparisons can help signal intent and make sure what you tell Powershell to do is what you meant it to do.

I know that test-thing "parameter" -eq $false -and $vara -eq $varb means (and will always mean) the same thing as (test-thing "parameter" -eq $false) -and ($vara -eq $varb) in Powershell, but will everyone reading it (including the future me who didn't just read the help file) know that, or will someone think it could mean test-thing "parameter" -eq ($false -and $vara -eq $varb) and then do something stupid based on that (admittedly implausible in this case) incorrect reading? Whereas there's pretty much only one way for a person to interpret (!(test-thing "parameter")) -and ($vara -eq $varb), and that is also the way Powershell will interpret it.

Adbot
ADBOT LOVES YOU

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!
Does the script do something weird with scoping $DebugPreference?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply