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
TITTIEKISSER69
Mar 19, 2005

SAVE THE BEES
PLANT MORE TREES
CLEAN THE SEAS
KISS TITTIESS




Thanks, I ended up doing it like this:

code:
Get-ADUser -filter * -properties extensionAttribute7 | where-object {$_ -like  "*OU=SubOUname*" } | Select-Object name, extensionAttribute7 | export-csv $dir$\ExAt7.csv -Encoding "Unicode"
EDIT: Crap, that just gave me everyone in the OU regardless of whether EA 7 is populated or not. Gonna try your way.

TITTIEKISSER69 fucked around with this message at 19:32 on Jan 22, 2019

Adbot
ADBOT LOVES YOU

The Fool
Oct 16, 2003


Instead of
code:
Get-ADUser -Filter *
Use

code:
Get-AdUser -Filter {extensionAttribute7 -like "*"}
And you will have your results filtered for you.

edit; the full command:
code:
Get-ADUser -filter -Filter {extensionAttribute7 -like "*"} -SearchBase "OU=SomeOU,DC=contoso,DC=com" -properties extensionAttribute7 | Select-Object name, extensionAttribute7 | export-csv $dir$\ExAt7.csv -Encoding "Unicode" -NoTypeInformation

Inspector_666
Oct 7, 2003

benny with the good hair

The Fool posted:

Instead of
code:
Get-ADUser -Filter *
Use

code:
Get-AdUser -Filter {extensionAttribute7 -like "*"}
And you will have your results filtered for you.

I always forget the correct syntax for -Filter, thanks for this. I was trying to concoct a much more complicated loop to check the values and make an array, etc.

Inspector_666 fucked around with this message at 19:39 on Jan 22, 2019

TITTIEKISSER69
Mar 19, 2005

SAVE THE BEES
PLANT MORE TREES
CLEAN THE SEAS
KISS TITTIESS




Tried the full command and got "Missing an argument for parameter 'Filter'"

The Fool
Oct 16, 2003


Because I was a dummy testing you and put -filter in there twice.

TITTIEKISSER69
Mar 19, 2005

SAVE THE BEES
PLANT MORE TREES
CLEAN THE SEAS
KISS TITTIESS




Yeah, I tried removing one then the other but still got errors.

The Fool
Oct 16, 2003


Removing the first -Filter works for me.

Are you changing the searchbase to match your domain and OU structure?

What is the error you are getting?

TITTIEKISSER69
Mar 19, 2005

SAVE THE BEES
PLANT MORE TREES
CLEAN THE SEAS
KISS TITTIESS




code:
PS C:\Users\TK69> Get-ADUser -Filter {extensionAttribute7 -like "*"} -SearchBase "OU=Consultants,DC=redacted,DC=net" -properties extensionAttribute7 | Select-Object name, extensionAttribute7 | export-csv $redacted$\ExAt7.csv -Encoding "Unicode" -NoTypeInformation
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Filter {extensionAttribute7 -like "*"} -SearchBase "OU=Consultants,D ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (:) [Get-ADUser], ADIdentityNotFoundException
    + FullyQualifiedErrorId : Directory object not found,Microsoft.ActiveDirectory.Management.Commands.GetADUser

The Fool
Oct 16, 2003


I can all but guarantee that your searchbase value is wrong somehow.

TITTIEKISSER69
Mar 19, 2005

SAVE THE BEES
PLANT MORE TREES
CLEAN THE SEAS
KISS TITTIESS




That was it, I had to change it to "OU=SubOU,OU=TopOU,DC=etc..."

Thanks!

bru
May 7, 2006

pampering lifes complexity

Inspector_666 posted:

code:
Get-ADUser -Filter * -Properties extensionAttribute7 | Select Name,SamAccountName,extensionAttribute7 | Export-CSV -Path <WHEREVER YOU WANT TO PUT THE CSV> -NoTypeInformation
should get you the CSV showing the user's name, AD login, and the value of extensionAttribute7. This'll pull everybody in AD, you can then filter in Excel to not see any of the empty ones. That's the simplest way to do it.


EDIT: to answer the question of how to search in a specific OU, use the -SearchBase flag in Get-ADUser with the distinguished name of the OU.

And if you _just_ wanted the number as you originally asked wrap the query in count:

(Get-ADUser -Filter yadayada). count

TITTIEKISSER69
Mar 19, 2005

SAVE THE BEES
PLANT MORE TREES
CLEAN THE SEAS
KISS TITTIESS




Thanks all!

Pile Of Garbage
May 28, 2007



On the subject of AD cmdlets it's worth noting that Get-ADObject is always faster than the other Get- cmdlets like Get-ADUser, Get-ADComputer or Get-ADGroup. The only downside with Get-ADObject is that you have to include filters to only return the objects you want whereas it's implied with the other cmdlets.

Still, even with the filters Get-ADObject is faster. This doesn't mean much for small stuff but it really adds up when you're dealing with huge directories.

code:
PS C:\> Get-ADUser -SearchBase 'CN=Users,DC=darkstar1,DC=net' -SearchScope Subtree -Filter * | Format-Table -Property Name

Name
----
Guest
DefaultAccount
krbtgt
Administrator


PS C:\> (Measure-Command -Expression {Get-ADUser -SearchBase 'CN=Users,DC=darkstar1,DC=net' -SearchScope Subtree -Filter * | Format-Table -Property Name}).TotalMilliseconds
15.7459
code:
PS C:\> Get-ADObject -SearchBase 'CN=Users,DC=darkstar1,DC=net' -SearchScope Subtree -Filter { objectCategory -eq 'CN=Person,CN=Schema,CN=Configuration,DC=darkstar1,DC=net' } | Format-Table -Property Name

Name
----
Guest
DefaultAccount
krbtgt
Administrator


PS C:\> (Measure-Command -Expression {Get-ADObject -SearchBase 'CN=Users,DC=darkstar1,DC=net' -SearchScope Subtree -Filter { objectCategory -eq 'CN=Person,CN=Schema,CN=Configuration,DC=darkstar1,DC=net' } | Format-Table -Property Name}).TotalMilliseconds
13.4802
Note that there is a query caching mechanism in AD so you may get inconsistent results but in the event of a cache miss Get-ADObject is quicker.

CzarChasm
Mar 14, 2009

I don't like it when you're watching me eat.
I'm a complete idiot when it comes to PS. I downloaded a module to get access to a gmail account, and I can't even get the first step to go because I don't understand the syntax.

code:
New-GmailSession [[-Credential] <PSCredential>] [<CommonParameters>]
I'm not sure how to pass it the user ID and password. I've tried to enter the values under PSCredentail, but I just can't get the items correct. Can you please help me?

The Fool
Oct 16, 2003


CzarChasm posted:

I'm a complete idiot when it comes to PS. I downloaded a module to get access to a gmail account, and I can't even get the first step to go because I don't understand the syntax.

code:
New-GmailSession [[-Credential] <PSCredential>] [<CommonParameters>]
I'm not sure how to pass it the user ID and password. I've tried to enter the values under PSCredentail, but I just can't get the items correct. Can you please help me?

PSCredential is expecting a credential object.

The easiest way to get one is to type the following before your cmdlet.


code:

$cred = Get-Credential

Then use the variable $cred as the value for the -Credential flag.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord
If you need it in an automated way, you can pass your user password into the following to generate a credential object, assuming you can access it locally:

code:
$CredentialObject = New-Object System.Management.Automation.PSCredential("USER",(ConvertTo-SecureString "PASSWORD" -AsPlainText -Force))

CzarChasm
Mar 14, 2009

I don't like it when you're watching me eat.
OK, that's what I'm looking for is the automated bit. Thank you.

Also, on the off chance that anyone is looking for using the gmail plugin for PS, you need to get a 16 character security code from the google account, not your standard password.

The Fool
Oct 16, 2003


PierreTheMime posted:

If you need it in an automated way, you can pass your user password into the following to generate a credential object, assuming you can access it locally:

code:
$CredentialObject = New-Object System.Management.Automation.PSCredential("USER",(ConvertTo-SecureString "PASSWORD" -AsPlainText -Force))

Depending on security concerns, you probably don't want to actually do this in a script since you will be saving your password in plain text.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

The Fool posted:

Depending on security concerns, you probably don't want to actually do this in a script since you will be saving your password in plain text.

Absolutely don't hardcode your passwords in plaintext, I didn't mean to imply that. If you have a method to access secured passwords, you can then pass them as shown.

FISHMANPET
Mar 3, 2007

Sweet 'N Sour
Can't
Melt
Steel Beams
Assuming you're talking about this module: https://github.com/nblagoev/Gmail.ps
It actually includes some code to read a credential from the Credential manager. It looks like if you create a "generic" type credential under the "Windows Credential" store in Credential manager, and set the address to "mail.ps:default" it'll grab that credential by default every time if you don't specify a credential on the command line. So that's a safe way to save your credentials.

Alfajor
Jun 10, 2005

The delicious snack cake.
Hey thread. Need some help escaping variables.... I'm hella confused by the quotes, single quotes, backtick, etc.

I'm running an AWS cli command for each AD group member, and stuck at making it escape $user.SamAccountName
What I have:
code:
$usersFromGroup =  Get-ADGroupMember -Identity "AD_Group_1"

foreach ($user in $usersFromGroup){
  write-host "Provisioning workspace for:" $user.name

  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}"'
}
The code runs, but the AWS cli returns with "user not found", screenshot here to make it clear:


Notes:
- the option --workspaces appears to require that the parameters get fed in quoted. If I don't use quotes, it screams about params missing
- if I use double quotes for the params for --workspaces, then I get errors about the "WorkspaceProperties" parameter list

So, the question is: how do I get the aws cli command to read in the actual $user.SamAccountName?

The Fool
Oct 16, 2003


What happens when you double quote --workspaces, but single quote WorkspaceProperties? Is that when you get the error, or were you double quoting both of them?

The Fool fucked around with this message at 19:46 on Jan 29, 2019

Alfajor
Jun 10, 2005

The delicious snack cake.
I get a
code:
 Parameter validation failed:
Invalid type for parameter Workspaces[0].WorkspaceProperties, value: {RunningMode=AUTO_STOP,RunningModeAutoStopTimeoutInMinutes=60,RootVolumeSizeGib=80,UserVolumeSizeGib=50}, type: <class 
'str'>, valid types: <class 'dict'>
:suicide:

slartibartfast
Nov 13, 2002
:toot:

Alfajor posted:

So, the question is: how do I get the aws cli command to read in the actual $user.SamAccountName?

In the WorkspaceProperties, try:
code:
UserName=$($user.SamAccountName)

Submarine Sandpaper
May 27, 2007


if it's looking for a dict @ that
@{RunningMode=AUTO_STOP,RunningModeAutoStopTimeoutInMinutes=60,RootVolumeSizeGib=80,UserVolumeSizeGib=50}


Anyone have experience using ROBO copy from SMA to remote fileshares? I'm having a bitch of a time. Looking to just get number of files in a specific user's share. Gotta use a PSSession somehow due to rights over the shares.

Alfajor
Jun 10, 2005

The delicious snack cake.

slartibartfast posted:

In the WorkspaceProperties, try:
code:
UserName=$($user.SamAccountName)

I had tried that before. Not taking a full screenshot, but this is what AWS CLI is seeing when I do that, it's still passing it literally:
code:
 UserName   =  $($user.SamAccountName)  

The Fool
Oct 16, 2003


You can try using the call operator with string concatenation:
code:
$command = 'aws'
$arguments = 'workspaces create-workspaces --workspaces'
$settings = 'DirectoryId=blahblah,UserName=' + $user.SamAccountName + ',RootVolumeEncryptionEnabled=True,UserVolumeEncryptionEnabled=True,VolumeEncryptionKey=arn:aws:kms:stuffheretoothatdoesntmatter,WorkspaceProperties="{RunningMode=AUTO_STOP,RunningModeAutoStopTimeoutInMinutes=60,RootVolumeSizeGib=80,UserVolumeSizeGib=50}"'

& $command $arguments $settings

Alfajor
Jun 10, 2005

The delicious snack cake.
Yeah, I was thinking of going down that route.... so thank you for saving me some time and effort! :)

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.

thebigcow
Jan 3, 2001

Bully!

Submarine Sandpaper posted:

if it's looking for a dict @ that
@{RunningMode=AUTO_STOP,RunningModeAutoStopTimeoutInMinutes=60,RootVolumeSizeGib=80,UserVolumeSizeGib=50}

code:
 @{'RunningMode'='AUTO_STOP';'RunningModeAutoStopTimeoutInMinutes'='60';'RootVolumeSizeGib'='8';'UserVolumeSizeGib'='50'}
Semi colons

quote:

Anyone have experience using ROBO copy from SMA to remote fileshares? I'm having a bitch of a time. Looking to just get number of files in a specific user's share. Gotta use a PSSession somehow due to rights over the shares.

I don't know what SMA is and searching was unhelpful. Are you running into problems with the powershell double hop ?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug
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.

mllaneza
Apr 28, 2007

Veteran, Bermuda Triangle Expeditionary Force, 1993-1952




I recently joined a team that's trying to remediate thousands of legacy and/or non-standard systems. Two of us are using Powershell to automate software deployments, maintenance, and updates. Thanks to the nature of the environment we have a random mix of 32- and 64-bit systems and have to push and invoke different installers for each.

This morning the other scripture asked how I was detecting processor architecture. It turns out, his way
code:
 $hello=(Get-WMIObject Win32_OperatingSystem).OSArchitecture
gave the result at the beginning followed by a '-' and mine used ProcessorArchitecture and had it as the trailing two characters.

A quick
code:
$bitness = $hello.Substring(0,$hello.Indexof('-'))
later, and our scripts are 128-bit ready !

AreWeDrunkYet
Jul 8, 2006

code:
PS > Measure-Command {gwmi win32_operatingsystem | select osarchitecture}
TotalMilliseconds : 53.0998

PS > Measure-Command {[Environment]::Is64BitOperatingSystem}
TotalMilliseconds : 5.3835
The static method seems to be substantially faster on subsequent executions, too.

Submarine Sandpaper
May 27, 2007


thebigcow posted:

code:
 @{'RunningMode'='AUTO_STOP';'RunningModeAutoStopTimeoutInMinutes'='60';'RootVolumeSizeGib'='8';'UserVolumeSizeGib'='50'}
Semi colons


I don't know what SMA is and searching was unhelpful. Are you running into problems with the powershell double hop ?

Turns out permissions are the issue.
SMA is service manager automation. To my understanding it's like in house azure.

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

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Jethro posted:

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

That's good to know. It's just unintuitive.

Like, if we're saying we want to operate on members of the array, fine.

If @( @{ a = 'b' }) gives me { "a": "b" }, I would expect @( @{ a = 'b' }, @{ c = 'd' }) to give me an array with index 0 being { "a": "b" } and index 1 being { "c": "d" }. That makes sense and logically follows with your explanation that we're operating on members of the collection, not the entire collection. But that's not what happens. The second case gives you a string with [ { "a": "b", "c": "d" } ].

That's not the only place the behavior pops up. Where-Object will also engage in shenangians where a single result is just the result, but multiple results are an array of the results. It's easy enough to deal with, but it's just a constant footgun unless you boilerplate every Where-Object by wrapping the results in @().

New Yorp New Yorp fucked around with this message at 19:19 on Jan 30, 2019

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.

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

Jethro posted:

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.

You're blowing my loving mind here. This is the most useful thing I think I've ever read in this thread.

Adbot
ADBOT LOVES YOU

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.

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