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
Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

Dr. Arbitrary posted:

Another thing, to help you help yourself.

Create a string

$UserInput = "a,b,c,d"

Now type this:

$UserInput | Get-Member

It will give you a list of "Methods"

One of those methods will turn your string into something very useful.

For syntax, you'll type something like:
$UserInput.ToUpper()

The parentheses sometimes need stuff inside them, you can tell because the Definition for the method will have the word Params inside.
So if you use the TrimEnd method, you need to specify how many characters to trim.

You're a good teacher, this is a good lesson, and now I want to create the script just so I can see the answer you're referring to.

Adbot
ADBOT LOVES YOU

Mo_Steel
Mar 7, 2008

Let's Clock Into The Sunset Together

Fun Shoe

lol internet. posted:

So... a job I am applying for asked me to do create a script as part of the interview process. Kinda strange because what I'm doing doesn't require too much scripting but anyways I got most of it done but I'm just hoping someone can point me in the right direction for a couple things last things. Not looking for an exact answer as I am going to get questioned on the script code I write anyways but perhaps which cmdlets help files I should be looking at or pointing me in the right direction.

- Script invokes user enter 1 to 10 names separated by commas
- I put assign those names into a variable array using .split(".")

How would I check the array to make sure there is between 1-10 entries and not blank? I assume use an if statement with <=1 -And >=10 but I'm not sure how to write the syntax for it to check the actual variable?

Another thing is to test a folder path where prior to running export-csv to it, the path will be inputted by a user

and.. lastly is there anyway to export to csv in a nice table like what appears in format-table since that doesn't work with export-csv ?

Dr. A's posts on the last page are great. One other aspect that might be interesting is how you approach the prompt. Read-Host is a great, straightforward way to go about it and probably what I'd use for anything I'm one-lining, but another option to be aware of is Cmdlet Binding. It's more advanced than what is needed for what was asked, but it's drat useful if you ever wind up writing more complex scripts where you'd want to allow switching, built-in debugging, etc.

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin
If you really want to be an overachiever, play around with windows forms to create a form that will let the user enter multiple entries separated either by commas or line breaks, and then after pressing the "compute" button or whatever, place the output directly onto the clipboard in a format that will paste cleanly into excel.
I'll paste the code for that later if anyone is interested.

Sefal
Nov 8, 2011
Fun Shoe

Dr. Arbitrary posted:

If you really want to be an overachiever, play around with windows forms to create a form that will let the user enter multiple entries separated either by commas or line breaks, and then after pressing the "compute" button or whatever, place the output directly onto the clipboard in a format that will paste cleanly into excel.
I'll paste the code for that later if anyone is interested.

Please do. I was looking into adding a text box for the users enter the entries a year ago. but i never got it working right and had forgotten it until now.

Irritated Goat
Mar 12, 2005

This post is pathetic.

Dr. Arbitrary posted:

There are a few aliases and special characters in Powershell you should know.

? = Where-Object
% = ForEach-Object
| = Pipe, commandlets are like little factories and the pipe makes the object from the last command shoot into the next one.
$_ = The input I got from the pipe

Just to make sure, would this work?
code:
Get-ADUser | % {whatever for each user here} 

FISHMANPET
Mar 3, 2007

Sweet 'N Sour
Can't
Melt
Steel Beams
I would just like to chime in and say that I absolutely detest The ? and % in powershell (and similar constructs in other languages) because they help you write unreadable code. Sure it's nice to do on the command line, but if you're writing a script that any body has to look at ever (including yourself) for the love of God please use the full command name so that you can actually read the code. The pipe is forgiveable because it's a core feature of the langauge, but $_ bothers me as well (especially when you start nesting statements, it's hard to figure out what $_ will actually mean at any given point).

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin
Not much you can do with $_, but there's no reason to ever publish Powershell code using aliases. Possible exception for "foreach"/"ForEach-Object"

Edit:
Wrong command.

Dr. Arbitrary fucked around with this message at 19:38 on Jun 7, 2016

lol internet.
Sep 4, 2007
the internet makes you stupid

Dr. Arbitrary posted:

Another thing, to help you help yourself.

Create a string

$UserInput = "a,b,c,d"

Now type this:

$UserInput | Get-Member

It will give you a list of "Methods"

One of those methods will turn your string into something very useful.

For syntax, you'll type something like:
$UserInput.ToUpper()

The parentheses sometimes need stuff inside them, you can tell because the Definition for the method will have the word Params inside.
So if you use the TrimEnd method, you need to specify how many characters to trim.

Edit:

For eliminating empty elements, I don't want to give away too much, you should be able to Google this, but you might find a very good answer that looks almost as impenetrable as that goofy linux fork bomb :(){:|:&};:

There are a few aliases and special characters in Powershell you should know.

? = Where-Object
% = ForEach-Object
| = Pipe, commandlets are like little factories and the pipe makes the object from the last command shoot into the next one.
$_ = The input I got from the pipe

Thanks, the getmember was quite useful. Is there anyway to use multiple methods? Like split, Trim and ToUpper all in one line?

code:
$GroupList = $GroupList.split(",") 

lol internet. fucked around with this message at 18:51 on Jun 7, 2016

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin
Sure, but order matters.

You can either do
$userinput.ToUpper().Split(",")

Or

$Userinput.Split(",") | ForEach-Object {$_.ToUpper}

Do you know why you have to do them so differently depending on the order?

nielsm
Jun 1, 2009



Dr. Arbitrary posted:


$Userinput.Split(",") | ForEach-Object {$_.ToUpper}


If you have PS 3.0 or newer, ForEach-Object can also straight take a member name to extract or call. Like this:

$Userinput.Split(",") | ForEach-Object ToUpper

lol internet.
Sep 4, 2007
the internet makes you stupid

Dr. Arbitrary posted:

Sure, but order matters.

You can either do
$userinput.ToUpper().Split(",")

Or

$Userinput.Split(",") | ForEach-Object {$_.ToUpper}

Do you know why you have to do them so differently depending on the order?

I didn't bother with ToUpper but I used split and trim. I'm asking the user to enter names of AD group names separated by commas. So in case they put "group1, group2" instead of "group1,group2" so in this case I don't think it matters. I did do trim before split though.

Afterwards, I throw it into a string array then do a foreach to do a get-adgroupmembership.

The one other thing I wanted to do was a check to make sure the user input was not 0 groups and between 1-100 only. I tried doing this with .count but the problem is .count returns a 1 for blank values still.

I am not sure how to go about this, I was thinking a if statement to specifically check for a blank line\empty space, and if that's not there, and elseif to continue the check for 1-100 groups prior to running get-adgroupmembership

I am not sure how to write the initial if statement though, I tried
code:
if($string -eq $null)
if($string -eq "")
if($string -eq $_)
and these don't seem to return true for a blank string value.

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin
Rather than looking for empty strings, why not look for non-empty strings.

Try a few different values for $String in this command

if ($string) {Write-Host "True"}

Definitely try
$String="Test"
$String=""
$String=$null
$String=$False
$String=$True
Edit:
Oh, and
$String="$False"

I'll include a possible solution in a spoiler:


| Where-Object {$_}
or as I hinted at earlier
| ? {$_}
Don't ever use that in a script that other people will ever read.

Dr. Arbitrary fucked around with this message at 21:59 on Jun 7, 2016

sloshmonger
Mar 21, 2013

lol internet. posted:

I didn't bother with ToUpper but I used split and trim. I'm asking the user to enter names of AD group names separated by commas. So in case they put "group1, group2" instead of "group1,group2" so in this case I don't think it matters. I did do trim before split though.

Afterwards, I throw it into a string array then do a foreach to do a get-adgroupmembership.

The one other thing I wanted to do was a check to make sure the user input was not 0 groups and between 1-100 only. I tried doing this with .count but the problem is .count returns a 1 for blank values still.

I am not sure how to go about this, I was thinking a if statement to specifically check for a blank line\empty space, and if that's not there, and elseif to continue the check for 1-100 groups prior to running get-adgroupmembership

I am not sure how to write the initial if statement though, I tried
code:
if($string -eq $null)
if($string -eq "")
if($string -eq $_)
and these don't seem to return true for a blank string value.
You can do what Arbitrary did or work with the $string.Length property



#or to prompt the user until they stop being dumb
while ($string.Length -lt 1){
$string = Read-host "Enter a valid string"
While ((($string.toCharArray() | Where-Object {$_ -eq ","} | Measure-Object).Count + 1) -gt 100){ #Only need to check if greater than 100 items, as 1 item is assumed
$string = Read-Host "Enter a valid string again, this time with feeling"
}}

Vulture Culture
Jul 14, 2003

I was never enjoying it. I only eat it for the nutrients.
There's an awful lot of DSC resources for managing NTFS ACLs lying around. Anyone have a favorite?

Swink
Apr 18, 2006
Left Side <--- Many Whelps
Just pitching in to say that if you're writing scripts with % and ? or whatever the hell, you are the devil. There are no prizes for brevity here, you should be as explicit as possible.



Vulture Culture posted:

There's an awful lot of DSC resources for managing NTFS ACLs lying around. Anyone have a favorite?

I'm interested in what you're using DSC for? I am just picking it up again after a year and the community isn't anything compared to Chef, which is a bit disappointing.

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin

Swink posted:

Just pitching in to say that if you're writing scripts with % and ? or whatever the hell, you are the devil. There are no prizes for brevity here, you should be as explicit as possible.

You'll love this one I found:
code:
$ofs="";
'"$(0'+
  '..(0'+
    'xa*['+
      'Math'+
        ']::R'+
          'ound'+
            '([Ma'+
              'th]:'+
                ':Pi/'+
                  '2,1)'+
                    ')|%{'+
                      '[cha'+
                        'r][i'+
                          'nt]"'+
                            '"$($'+
                              '("""'+
                                '"0$('+
                                   '1838'+
                                   '1589'+
                                '*726'+
                              '371*'+
                            '60)$'+
                          '(877'+
                        '7365'+
                      '981*'+
                    '263*'+
                  '360)'+
                '$(22'+
              '2330'+
            '793*'+
          '1442'+
        '99)$'+
      '(310'+
    '9*37'+
  ') ""'+        '"")[' + '($_*' + '3)..' +
'($_*'+        '3+2)' + '])""' + ' })"'|iex
Edit:

or this:

code:
$s = "a*h*t*s*m*i*d*o*n*l*k*e*y*u*g*r*w*CBAC> DAE-F-AE>!<R S!><" +
    "F GH IHC> JFKL> T<<GH MHN> V+ OPLLI LOOD AIG BAE>?<" +
    "U V+ CBLE>, S.<U V X><<QHNJG MHN> V Y> BLPL HP CBLPL>?<" +
    "F QHNJG IHC> \ ]>.<^ \> AIMQBLPL>.<Z.<U \>, S.<<" +
    "[ \> FI A BHNDL>?<c+ QFCB A EHNDL>?<b d>.<b e>.<b ]>.<b a><Z.<b, S>.<"
$cur = ""
$line = ""
[char]$next = "A"
$store = @{}
foreach ($c in [char[]]$s) {
    switch -regex ($c) {
        "[\*\>]" {
            $store[$next] = $cur.TrimStart(" ")
            $next = [char]([int]$next + 1)
            if ($c -eq ">") { $line += $cur }
            $cur = ""
        }
        "\+" {
            $line += $cur
            $cur = ""
        }
        "\<" {
            $line + $cur
            $line = ""
            $cur = ""
        }
        default {
            if ($store.Contains($c)) {
                $cur += $store[$c]
            } else {
                $cur += $c
            }
        }
    }
}
Edit2:

Don't run this one, it's actually a virus:

http://www.symantec.com/connect/blogs/dark-power-windows-powershell

Dr. Arbitrary fucked around with this message at 09:55 on Jun 8, 2016

Swink
Apr 18, 2006
Left Side <--- Many Whelps
The respect I have for the author of that is matched only by my desire to punch them in the stomach.

Venusy
Feb 21, 2007

sloshmonger posted:

You can do what Arbitrary did or work with the $string.Length property



#or to prompt the user until they stop being dumb
while ($string.Length -lt 1){
$string = Read-host "Enter a valid string"
While ((($string.toCharArray() | Where-Object {$_ -eq ","} | Measure-Object).Count + 1) -gt 100){ #Only need to check if greater than 100 items, as 1 item is assumed
$string = Read-Host "Enter a valid string again, this time with feeling"
}}



Another way to do this is that the [string] type contains a handy little method called IsNullOrEmpty:


$array = foreach ($string in $array) {
$check = [string]::IsNullOrEmpty($string)
if ($check -eq $true) {$string = Read-Host "You numpty. Do this properly"}
$string
}


The way to discover these sort of things is by passing an object to Get-Member -Static .

Methanar
Sep 26, 2013

by the sex ghost
I was just in a server with RDP because I needed a jump box to another domain and from there I wanted to run do some remote powershell administration because onedrive for business has dumb file name requirements.

code:
PS C:\> Invoke-Command -computername (get-content workstations.txt) -scriptblock { 

Get-ChildItem -path "$home\desktop" -Filter "*#*" -Recurse | Rename-Item -NewName {$_.name -replace '#',' ' }

}
The instant I hit enter my RDP session died and my heart stopped for a second.

Somebody else had RDP'd into the server at that exact moment and it kicked me out and didn't actually somehow break the entire network.

Vulture Culture
Jul 14, 2003

I was never enjoying it. I only eat it for the nutrients.

Swink posted:

I'm interested in what you're using DSC for? I am just picking it up again after a year and the community isn't anything compared to Chef, which is a bit disappointing.
Nothing fancy, just automating the creation of some desktop VMs for our developers to make it easier to onboard people.

The community is definitely tiny next to Chef, and all of the documentation is terrible. But it's good enough, I guess?

Djimi
Jan 23, 2004

I like digital data
I've got a new task at work where daily we receive list of users
that log into a web app / database (that I don't control), and against
that list we have a list of possibly new users or users needed to be removed
that I need to compare and merge into a new file that is then uploaded
to the web app. So we get a download, compare with user adds and removes,
and then send an accurate new version.

The csv file we receive is like:
code:
Employee Username,Password, Employee First Name, Employee Last Name, Last Login Date, Last Updated Date
[email]kevin@bitraptor.com[/email], Unavailable ,Kevin, The Carver, Never, 5/29/2016 17:05
[email]joebob@hooli.com[/email], , Joe,  Bob, 6/11/2016 13:07, 5/29/2016 17:05
[email]mary.sue@initech.com[/email], Unavailable, Mary, Sue, Never, 5/29/2016 17:05
[email]billg@company.com[/email], Unavailable, William, Ghee, Never, 5/29/2016 17:05
[email]jp@hooli.com[/email], , Johnny, Paycheck, 6/7/2016 13:07, 6/1/2016 08:00

etc
The other requirement (as seen above) is that if a user has logged in before,
then we won't over write their password they have set, otherwise we'll write it
with whatever our default password is for a new user. The received file will have
that column as a null. Joe Bob and Johnny Paycheck have logged in before and set
their passwords. If the user is new or hasn't logged in before, the received file
shows 'Unavailable'. Another determination is that we see the timestamp of
last login or 'Never'.

I may be going about this completely wrong, or don't know about something easy (fancy)
in the CSV methods, but I am looping through the two files and finding the null value
in the download file and making the Password column blank in the upload file. If the
web app sees a row value with a blank password, it won't overwrite it on their end,
otherwise we put back in 'defaultpassword' when we send back the new file. We also don't
send the login and updated date columns. Our file overwrites their information
each time we give it back to them. If a person doesn't exist in our file to upload then
it should be reflected in the final output, effectively disabling that user (deleting them).
I haven't even got to that point because of the issues I'm having now and perhaps it would
inform how I should even build this Upload file.

code:
#Data we start with
$down = import-csv $download -Header 'Employee Username','Password','Employee First Name','Employee Last Name','Last Login Date','Last Updated Date' | sort 'Employee Username'

#Data we add/amend
$up = import-csv $upload -Header 'Employee Username','Password','Employee First Name','Employee Last Name' | sort 'Employee Username'

#Loop through to find out if user has logged in once - if so, erase Password value.
$main = foreach ($u in $up) {
    $found = $false
    foreach($d in $down)
    {
        if ($d."Employee Username" -eq $u."Employee Username") 
        {
            $found = $true

            if ($d.Password -eq "")
            {
                ($u.Password = "")
            }
        }
	}
	$u
}
$main
$main | export-csv -NoTypeInformation $mergedfile 
It's close but no cigar. A few problems: I'm ending up with multiple lines of the Header
information showing up alphabetically in the list (we sorted the list by the first column)
(Employee Username,First,Last etc) and also a blank line preceding any users that
have logged in and I also don't know how to select a 'unique' (Get-Unique?) row-value
(hopefully retaining the row that has the user logging in once from the 'download' csv,
which is what we are trying to preserve.

Here's a sample of what the merged file looks like:
code:
Employee Username	Password	Employee First Name	Employee Last Name
[email]billg@company.com[/email]	 defaultpassword	 William	 Ghee		 
Employee Username	Password	Employee First Name	Employee Last Name
Employee Username	Password	Employee First Name	Employee Last Name

[email]joebob@hooli.com[/email]		Joe	 Bob		
[email]kevin@bitraptor.com[/email]	defaultpassword	Kevin	 The Carver	
[email]mary.sue@initech.com[/email]	 defaultpassword	 Mary	 Sue

[email]jp@hooli.com[/email]	 	 Johnny	 Paycheck
Part of me feels that I need another process to just go through the lines of users that
have logged in and treat them as a separate file to work on and later inject that into
any matched line from the download file??) I am using PS version 4. Whatever is the easiest way
to achieve it, even if it's dumb-brute force as the list of users isn't that big and never
will be, so I'm not concerned with a method that takes longer or is costly. Is there some method
of Import / Export CSV that I'm not aware of? Thanks you guys.
Ignore the "[ email ]" tags - that was vB code inserting itself by finding email addresses

Djimi fucked around with this message at 20:25 on Jun 12, 2016

slightpirate
Dec 26, 2006
i am the dance commander
I know this is going to sound goofy as all hell, but none of my scripts that were exporting to CSV are working now. The file gets created fine, but no headers or data get dumped and no errors are generated in ISE.

Any ideas on what one-off command I typed into my console weeks ago that I forgot about?

nielsm
Jun 1, 2009



slightpirate posted:

I know this is going to sound goofy as all hell, but none of my scripts that were exporting to CSV are working now. The file gets created fine, but no headers or data get dumped and no errors are generated in ISE.

Any ideas on what one-off command I typed into my console weeks ago that I forgot about?

Have you checked that the variables or pipelines you send to CSV actually contains any data?

Also try piping your data to ConvertTo-CSV instead of Export-CSV, that will get you text output to view in the console instead.

slightpirate
Dec 26, 2006
i am the dance commander

nielsm posted:

Have you checked that the variables or pipelines you send to CSV actually contains any data?

Also try piping your data to ConvertTo-CSV instead of Export-CSV, that will get you text output to view in the console instead.

I appended Out-Host -paging and commented out the Export-CSV -path line and it returned nothing to console aside from a 'complete' message. Heres the script in question. obvious company stuff renamed.

code:
$path = Split-Path -parent "C:\AD Audit\*.*"
$LogDate = get-date -f yyyyMMddhhmm
$csvfile = $path + "\ADUsers_Audit_$logDate.csv"

Import-Module ActiveDirectory
$SearchBase = "OU=Testing,OU=users,DC=domain,DC=name,DC=com"

$AllADUsers |
Select-Object @{Label = "SamAccountName";Expression = {$_.SamAccountName}},
@{Label = "Account Status";Expression = {if (($_.Enabled -eq 'TRUE')  ) {'Enabled'} Else {'Disabled'}}}, # the 'if statement# replaces $_.Enabled
@{Label = "Account Created";Expression = {$_.whencreated}},
@{Label = "Last LogOn Date";Expression = {$_.lastlogondate}},
@{Label = "Group Membership";Expression = {($_.MemberOf | ForEach-Object {([regex]"CN=(.*?),").match($_).Groups[1].Value}) -join ","}} |

out-host -paging
#Export CSV report
#Export-Csv -Path $csvfile -NoTypeInformation

nielsm
Jun 1, 2009



$AllADUsers is what? Nothing gets assigned to that in what you pasted.

FISHMANPET
Mar 3, 2007

Sweet 'N Sour
Can't
Melt
Steel Beams
You need to tell it what to export. I assume you want $AllADUsers exported?
out-host -paging $AllADUsers or export-csv -path $path -NoTypeInformation $AllADUsers

Oh yeah you're not even setting your output to anything. Assuming that select line actually finds something, you'd need to pipe that into out-host or export-csv.

slightpirate
Dec 26, 2006
i am the dance commander
oh goddamnit.

code:
$AllADUsers = Get-ADUser -server $ADServer -searchbase $SearchBase -Filter * -Properties *
I must have manually mashed that in and didn't include it in the script. It's working fine now!

Thanks goons, sometimes a second set of eyes doesn't hurt.

nielsm
Jun 1, 2009



slightpirate posted:

oh goddamnit.

code:
$AllADUsers = Get-ADUser -server $ADServer -searchbase $SearchBase -Filter * -Properties *
I must have manually mashed that in and didn't include it in the script. It's working fine now!

Thanks goons, sometimes a second set of eyes doesn't hurt.

When I debug my PowerShell scripts, I usually do it by pasting each command in manually and examining the output. When something uses a variable I examine its current value, and if it looks wrong, double check how that value got there.

Just being methodical like that finds 99% of all mistakes.

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin
Trying not to reinvent the wheel, using Powershell v2, I've got a bunch of tasks I want to run on a bunch of servers. I want to do it in parallel and keep track of which steps succeed and fail so that I can assign an engineer to manually intervene.

Any good ways to keep track of this kind of thing?

Venusy
Feb 21, 2007

Djimi posted:

It's close but no cigar. A few problems: I'm ending up with multiple lines of the Header
information showing up alphabetically in the list (we sorted the list by the first column)
(Employee Username,First,Last etc) and also a blank line preceding any users that
have logged in and I also don't know how to select a 'unique' (Get-Unique?) row-value
(hopefully retaining the row that has the user logging in once from the 'download' csv,
which is what we are trying to preserve.

Here's a sample of what the merged file looks like:
Part of me feels that I need another process to just go through the lines of users that
have logged in and treat them as a separate file to work on and later inject that into
any matched line from the download file??) I am using PS version 4. Whatever is the easiest way
to achieve it, even if it's dumb-brute force as the list of users isn't that big and never
will be, so I'm not concerned with a method that takes longer or is costly. Is there some method
of Import / Export CSV that I'm not aware of? Thanks you guys.
Ignore the "[ email ]" tags - that was vB code inserting itself by finding email addresses

Using the provided sample CSV as data for both down and up, the problem appears to be with this line (and possibly the corresponding one for $down):

code:
$up = import-csv $upload -Header 'Employee Username','Password','Employee First Name','Employee Last Name' | sort 'Employee Username'
The header parameter is used when you have data without headers, though it does work in the scenario where all the headers in the file match. But after this line, this is what PowerShell has as the value of $up:

code:
Employee Username    Password     Employee First Name Employee Last Name
-----------------    --------     ------------------- ------------------
Employee Username    Password     Employee First Name Employee Last Name
[email]kevin@bitraptor.com[/email]  Unavailable  Kevin               The Carver        
...
It's adding the header as an object.
code:
$up = Import-CSV $upload
...
$main | select "Employee Username","Password","Employee First Name","Employee Last Name"
This works, but still has the issue with the whitespace. It looks like it's something in the if statements, because using where-object works:
code:
$main = foreach ($u in $up) {
    $found = $false
    $downloadusers = $down | where "Employee Username" -eq $u.'Employee Username'
    if ($downloadusers.Password -eq "") {$u.Password = ""}
    $u
}
$main | select "Employee Username","Password","Employee First Name","Employee Last Name" -Unique

Employee Username    Password     Employee First Name Employee Last Name
-----------------    --------     ------------------- ------------------
[email]kevin@bitraptor.com[/email]  Unavailable  Kevin               The Carver        
[email]joebob@hooli.com[/email]                  Joe                 Bob               
[email]mary.sue@initech.com[/email] Unavailable  Mary                Sue               
[email]billg@company.com[/email]    Unavailable  William             Ghee              
[email]jp@hooli.com[/email]                      Johnny              Paycheck          
(this may need some adjustments, since $downloadusers could have multiple entries which might cause a headache)

Djimi
Jan 23, 2004

I like digital data

Venusy posted:

Very helpful and informative information about PowerShell that I didn't know ....

I've been thinking about this problem and I believe it could (should) be done much better in a completely different way, and maybe I can pseudo code it and someone can tell me the best way (how) to do it (?)
  • The Upload list (that we have and generate or modify each day is the 'master' list. Only names in this list we care about, modify and keep.
  • The only information we care about in the Download list is if someone has already logged in once -- we preserve the password by nulling not re-writing the default in the Upload file.
  • Looping through Upload file and find and replace matches within Download file that have $null in Password rows back to the Upload file. (I don't think we need to use Import-Csv??)
  • Don't need to sort the files to compare, because they're not apples to apples lists. If 30 users are added or removed the two lists don't have the same number or rows.
  • The list is about 1500 users.
  • What's the 'sed' type way of doing this in PS?

Is that like a one liner almost? Thanks again.

FISHMANPET
Mar 3, 2007

Sweet 'N Sour
Can't
Melt
Steel Beams
I've got a style question. I've got a script, and it does some things, but the person running it may not care about those things. So I'm using write-verbose. And I've got [CmdletBinding()] at the top of my script, so it can accept the -verbose flag. But when I do that, every command I'm running outputs verbose output as well, overwhelming my output!

I could attach -Verbose:$false to every command I call to scilence it, but that sounds bad. I would just say screw it and write-host (problematic) or write-out my output. What's the "proper" powershell way to do this?

Hadlock
Nov 9, 2004

If I need to suppress output, typically that line ends in

Blah | out-file $null

If you want to do it for a bunch of lines, you may be able to wrap them in a function and then

Function blah ($param) | out-file $null

Zaepho
Oct 31, 2013

Hadlock posted:

If I need to suppress output, typically that line ends in

Blah | out-file $null

If you want to do it for a bunch of lines, you may be able to wrap them in a function and then

Function blah ($param) | out-file $null

This would intercept and send output to the lovely fires of the bitbucket but Write-Host/Verbose/Warning/Error/Debug are all on different streams than output and would not get intercepted by this.

I believe CmdletBinding intentionally passes verbosity preferences though to the underlying commands. I guess you could wrap the worst offenders in another function without Cmdletbinding to break the chain so to speak.

Jethro
Jun 1, 2000

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

Mo_Steel
Mar 7, 2008

Let's Clock Into The Sunset Together

Fun Shoe

Dr. Arbitrary posted:

Trying not to reinvent the wheel, using Powershell v2, I've got a bunch of tasks I want to run on a bunch of servers. I want to do it in parallel and keep track of which steps succeed and fail so that I can assign an engineer to manually intervene.

Any good ways to keep track of this kind of thing?

Assuming the same set of tasks on multiple servers at the same time? You could make a script with the checks you want as if statements and the result as text:

code:
$files = Get-ChildItem $dir -include *.txt
if ( $files ) {
    "$computer had $files in $dir"
} else {
   "$computer DIDN'T have ANY text files in $dir so send in the engineers!"
}
Then call it as a scheduled task to "Start a Program", select Powershell, and add the following arguments:

-executionpolicy Bypass C:\scripts\mycoolscript.ps1 | Out-File C:\scripts\mycoollog.txt -Append -NoClobber

Not as fancy as say Start-Transcript but it should work; logic flow can let you make some more choices (pausing the script until an engineer handles something, etc.)

Dr. Arbitrary
Mar 15, 2006

Bleak Gremlin
No, this is a one time thing, so say we've got 100 servers that need significant configuration changes, and they all go through similar steps, some of which may fail, need to be remediated, and then move on.

I've been thinking of making some custom objects that have name, sequence number, succeed/fail, scriptblock.

Then for each of the servers I can have it start task 1 as a job, periodically check to see if it finished, proceed to 2 on the ones that are done, and so on.

If Server 45 fails on step 9, I want to be able to tell someone to manually fix the problem, and then continue to step 10.

Methanar
Sep 26, 2013

by the sex ghost
Are there are concerns I need to be aware of if I want to setup CredSSP?

I've been running into what is apparently the two hop problem and I've read that CredSSP is the answer to that.

Is setting it up just a matter of pushing out the correct GPOs like it seems?

Vulture Culture
Jul 14, 2003

I was never enjoying it. I only eat it for the nutrients.

Dr. Arbitrary posted:

No, this is a one time thing, so say we've got 100 servers that need significant configuration changes, and they all go through similar steps, some of which may fail, need to be remediated, and then move on.

I've been thinking of making some custom objects that have name, sequence number, succeed/fail, scriptblock.

Then for each of the servers I can have it start task 1 as a job, periodically check to see if it finished, proceed to 2 on the ones that are done, and so on.

If Server 45 fails on step 9, I want to be able to tell someone to manually fix the problem, and then continue to step 10.
Are you able to make these changes idempotent? Might be easier to just use something like DSC resources and not worry about the workflow angle at all -- it will just pick up whatever needs to be changed.

Adbot
ADBOT LOVES YOU

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Vulture Culture posted:

Are you able to make these changes idempotent? Might be easier to just use something like DSC resources and not worry about the workflow angle at all -- it will just pick up whatever needs to be changed.

That was going to be my recommendation until I saw "PowerShell 2".

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