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
stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe
Thanks, will try this out tomorrow.

Adbot
ADBOT LOVES YOU

kampy
Oct 11, 2008

stubblyhead posted:

but it doesn't work if $myCollection only has a single element. I'm not sure if this is how the PowerCLI cmdlets are written or if it's just how Powershell works, but the Get-Cluster cmdlet will return a single object if there's only one that matches the criteria, and a collection of them if there's multiple. The Cluster object doesn't have a Length property, so Get-Random thrown an error because the parameter gets passed a null value. I'd prefer not to do a check on the length before doing this if possible. Is there any way I can make it handle a single object as a collection with length 1, or is there just a better way to approach this altogether?

You could also try forcing $myCollection to be an array, that way it will always have a length.

code:
[array] $myCollection = Whatever-Command

mobby_6kl
Aug 9, 2009

by Fluffdaddy
What's up with Powershell script execution being disabled by default? I get "security", but you can run any exe file by default, so...

Anyway, what's the most reasonable (user friendly, foolproof) way to allow people to run my scripts just by double clicking on them? Right now I have them search for Powershell it in the start menu, run as admin, then paste in "set-executionpolicy remoteonly", run that, then CD to the correct directory, and run the script by typing out the name. All this almost defeats the purpose of having the script in the first place.

adaz
Mar 7, 2009

mobby_6kl posted:

What's up with Powershell script execution being disabled by default? I get "security", but you can run any exe file by default, so...

Anyway, what's the most reasonable (user friendly, foolproof) way to allow people to run my scripts just by double clicking on them? Right now I have them search for Powershell it in the start menu, run as admin, then paste in "set-executionpolicy remoteonly", run that, then CD to the correct directory, and run the script by typing out the name. All this almost defeats the purpose of having the script in the first place.

.exe's are old so they run with terrible practices (and really even that is quite a bit different nowadays with .NET assemblies). powershell is new so designed to be secure by default.

GPO out the execution policy and create a shortcut to run the script by invoking powershell.exe -command. You will never be able to just doubleclick on a ps1 file and have it execute.

gbeck
Jul 15, 2005
I can RIS that

mobby_6kl posted:

What's up with Powershell script execution being disabled by default? I get "security", but you can run any exe file by default, so...

Anyway, what's the most reasonable (user friendly, foolproof) way to allow people to run my scripts just by double clicking on them? Right now I have them search for Powershell it in the start menu, run as admin, then paste in "set-executionpolicy remoteonly", run that, then CD to the correct directory, and run the script by typing out the name. All this almost defeats the purpose of having the script in the first place.

You can use a batch file or shortcut to launch the script without having to change the local execution policy.
code:
powershell.exe -executionpolicy remotesigned -nologo -noprofile -file file.ps1

Mario
Oct 29, 2006
It's-a-me!

stubblyhead posted:

How would you guys handle this kind of situation? I want to randomly arrange a collection. I can do it like this:
code:
$random = Get-Random -InputObject $myCollection -Count $myCollection.Length
but it doesn't work if $myCollection only has a single element. I'm not sure if this is how the PowerCLI cmdlets are written or if it's just how Powershell works, but the Get-Cluster cmdlet will return a single object if there's only one that matches the criteria, and a collection of them if there's multiple. The Cluster object doesn't have a Length property, so Get-Random thrown an error because the parameter gets passed a null value. I'd prefer not to do a check on the length before doing this if possible. Is there any way I can make it handle a single object as a collection with length 1, or is there just a better way to approach this altogether?
You can also use @ to force the object to behave as an array:
code:
PS> (1, 2, 3 | Get-Random -Count 1).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType


PS> @(1, 2, 3 | Get-Random -Count 1).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

mobby_6kl
Aug 9, 2009

by Fluffdaddy

adaz posted:

.exe's are old so they run with terrible practices (and really even that is quite a bit different nowadays with .NET assemblies). powershell is new so designed to be secure by default.

GPO out the execution policy and create a shortcut to run the script by invoking powershell.exe -command. You will never be able to just doubleclick on a ps1 file and have it execute.


gbeck posted:

You can use a batch file or shortcut to launch the script without having to change the local execution policy.
code:
powershell.exe -executionpolicy remotesigned -nologo -noprofile -file file.ps1

Thanks guys. I ended up using the batch file method, though I had to dick around a bit to prevent it from messing with current working directory when it's executed in admin mode.

ProtoKaiser
Feb 28, 2005

Hello, IT. Have you tried turning it off and on again?

mobby_6kl posted:

Thanks guys. I ended up using the batch file method, though I had to dick around a bit to prevent it from messing with current working directory when it's executed in admin mode.

I've been having the same issue with running my PS1's. Fortunately, I just found this handy piece of code to add at the top of a script:
http://blogs.msdn.com/b/virtual_pc_guy/archive/2010/09/23/a-self-elevating-powershell-script.aspx

Then all you need to do is right click the PS1 and "Run with PowerShell".

Titan Coeus
Jul 30, 2007

check out my horn

Mario posted:

You can also use @ to force the object to behave as an array:
code:
PS> (1, 2, 3 | Get-Random -Count 1).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType


PS> @(1, 2, 3 | Get-Random -Count 1).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

This is the right way to do this. PowerShell uses "array unpacking" to take advantage of the pipeline. I personally hate this feature, but fortunately the @($something) will make something an array if it isn't already - if it is already an array then it won't do anything. Anytime I am expecting something to be an array, I put @() around it to be sure.

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

Hay guys I'm back, this time with a lot more PowerShell under my belt and asking kind of an academic question. I've made a short little script that harvests tracking information from CSV files downloaded from an FTP server. checks the archive directory to see if the file already exists, and if it doesn't exist email the contents of the file somewhere and move it to the archive folder. It's basically (boring stuff cut out):

code:
$f1Path = "d:\blah\"
$f2Path = "d:\blah\archive\"

$f1 = Get-ChildItem -path $f1Path -Filter *.csv
$f2 = Get-ChildItem -path $f2Path -Filter *.csv

If ( $f1 -and $f2 ) {
	$f3 = Compare-Object -ReferenceObject $f1 -DifferenceObject $f2 | Where-Object { $_.SideIndicator -eq "<="}
}


if ($f3) {
	#build email body
	$BodyText = foreach ($a in $f3) { Import-CSV ($f1Path + $a.InputObject) -header("HEADERS") 
        | Select-Object HEADERS | convertto-html }
	
	#send email etc.
	$emailMessage.Body = $BodyText
	 
	#copy files to archive
	foreach ($a in $f3) { copy-item -Path ($f1Path + $a.InputObject) -Destination $f2Path }
}
So I was showing the recipient of this email how things would work, and as an example I used
code:
$uo = Import-CSV tracktest.csv
$uo

Column1     : Value
Column2     : Value
Column3     : Value
Column4     : Value
etc.
And apparently, they freakin love the default output to screen that occurs as above (e.g. all columns basically as rows) and I can't seem to figure out how to do it easily in PowerShell. All the transpose code I've found is messy and... messy. Is there an easy way to have the CSV object output to string as a vertical row of values in one column instead of Column1,Column2,Column3?

Titan Coeus
Jul 30, 2007

check out my horn

Scaramouche posted:

Hay guys I'm back, this time with a lot more PowerShell under my belt and asking kind of an academic question. I've made a short little script that harvests tracking information from CSV files downloaded from an FTP server. checks the archive directory to see if the file already exists, and if it doesn't exist email the contents of the file somewhere and move it to the archive folder. It's basically (boring stuff cut out):

code:
$f1Path = "d:\blah\"
$f2Path = "d:\blah\archive\"

$f1 = Get-ChildItem -path $f1Path -Filter *.csv
$f2 = Get-ChildItem -path $f2Path -Filter *.csv

If ( $f1 -and $f2 ) {
	$f3 = Compare-Object -ReferenceObject $f1 -DifferenceObject $f2 | Where-Object { $_.SideIndicator -eq "<="}
}


if ($f3) {
	#build email body
	$BodyText = foreach ($a in $f3) { Import-CSV ($f1Path + $a.InputObject) -header("HEADERS") 
        | Select-Object HEADERS | convertto-html }
	
	#send email etc.
	$emailMessage.Body = $BodyText
	 
	#copy files to archive
	foreach ($a in $f3) { copy-item -Path ($f1Path + $a.InputObject) -Destination $f2Path }
}
So I was showing the recipient of this email how things would work, and as an example I used
code:
$uo = Import-CSV tracktest.csv
$uo

Column1     : Value
Column2     : Value
Column3     : Value
Column4     : Value
etc.
And apparently, they freakin love the default output to screen that occurs as above (e.g. all columns basically as rows) and I can't seem to figure out how to do it easily in PowerShell. All the transpose code I've found is messy and... messy. Is there an easy way to have the CSV object output to string as a vertical row of values in one column instead of Column1,Column2,Column3?

Try this:

code:
Import-CSV tracktest.csv | Format-List | Out-String

Titan Coeus fucked around with this message at 06:46 on Feb 21, 2013

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

Titan Coeus posted:

Try this:

code:
Import-CSV tracktest.csv | Format-List | Out-String

Well check that poo poo out. I had already tried that (realizing that Out-* was the only thing I could use) but it didn't work. But then I got the brainwave of setting the email HTML to $false, and sure enough it came through. Makes me wonder how much the HTML aspect was screwing up my other tries at it, and if it would have worked all along with HTML if I just thought to put '<PRE>' in front of it. Thanks Titan Coeus, you're worthy of stealing a pie from Estelle Getty.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
I imagine this is one of those issues no one will be able to help with. I'm generating an XML report which contains Windows Backup history (from the event log), Windows update information from a check for updates, and the Windows update history.

I run it as a scheduled task, and I dump this all into an XML file. However, if it's run as a scheduled task (SYSTEM account), the strings suffer bizarre formatting issues:

output XML posted:

<item ref='KB982132' date='12/15/2011 13:24:00 GMT'>Ǝecurity Update for Windows Server 2008 R2 x64 Edition (KB982132)</item><item ref='KB2544893' date='12/15/2011 13:23:47 GMT'>ƙecurity Update for Windows Server 2008 R2 x64 Edition (KB2544893)</item><item ref='KB2533552' date='12/15/2011 13:23:33 GMT'>Ʀpdate for Windows Server 2008 R2 x64 Edition (KB2533552)</item><item ref='KB2588516' date='12/15/2011 13:23:21 GMT'>Ƥecurity Update for Windows Server 2008 R2 x64 Edition (KB2588516)</item><item ref='KB2509553' date='12/15/2011 13:23:07 GMT'>Ưecurity Update for Windows Server 2008 R2 x64 Edition (KB2509553)</item><item ref='KB2539636' date='12/15/2011 13:23:02 GMT'>Security Update for Microsoft .NET Framework 4 on Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008, Windows Server 2008 R2 for x64-based Systems (KB2539636)</item><item ref='KB2536276' date='12/15/2011 13:20:36 GMT'>ƺecurity Update for Windows Server 2008 R2 x64 Edition (KB2536276)</item><item ref='KB2506212' date='12/15/2011 13:20:22 GMT'>Džecurity Update for Windows Server 2008 R2 x64 Edition (KB2506212)</item><item ref='KB2124261' date='12/15/2011 13:20:07 GMT'>ǐecurity Update for Windows Server 2008 R2 x64 Edition (KB2124261)</item><item ref='KB2633952' date='12/15/2011 13:19:53 GMT'>ưpdate for Windows Server 2008 R2 x64 Edition (KB2633952)</item><item ref='KB2620712' date='12/15/2011 13:19:30 GMT'>Ǜecurity Update for Windows Server 2008 R2 x64 Edition (KB2620712)</item><item ref='KB982799' date='12/15/2011 13:19:14 GMT'>Security Update for Windows Server 2008 R2 x64 Edition (KB982799)</item><item ref='KB2500170' date='12/15/2011 13:17:40 GMT'>ǒecurity Update for Microsoft Chart Controls for Microsoft .NET Framework 3.5 Service Pack 1 (KB2500170)</item><item ref='KB975467' date='12/15/2011 13:17:32 GMT'>.ecurity Update for Windows Server 2008 R2 x64 Edition (KB975467)</item><item ref='KB2567680' date='12/15/2011 13:17:21 GMT'>ecurity Update for Windows Server 2008 R2 x64 Edition (KB2567680)</item><item ref='KB890830' date='12/15/2011 13:16:57 GMT'>
indows Malicious Software Removal Tool x64 - December 2011 (KB890830)</item><item ref='' date='12/15/2011 13:16:01 GMT'>Windows Internet Explorer 9 for Windows Server 2008 R2 for x64-based Systems</item><item ref='KB2463332' date='12/15/2011 13:11:58 GMT'>Windows Internal Database Service Pack 4 for x64 Edition (KB2463332)</item><item ref='' date='12/15/2011 11:46:03 GMT'>:ϸ</item></task></tasks></xml>

Random characters appear. This does NOT happen when the script is run from the powershell window.

Other points to note:
The XML is generated in a long string (as opposed to an object based system).
To make sure the string wasn't overflowing, I echo'd the Update title information (from the same loop) into a text file, and the random characters persisted there too.
The machines' RAM is fine across the servers this happens on.
The error occurs even if the scheduled task is run under the same account as the powershell window (domain admin)
The command's XML output is the same no matter which user runs it (except the random characters)
This happens randomly on some of the servers, and not others.
Tried Powershell 3, and it was hard to tell if that fixed it or not, because it messed up other parts of the script so I couldn't replicate exactly.
Happens on a few of the servers, but not all, with no obvious difference.
I've tried putting in lags between the update check and the installed update dump, and this solves nothing.


Like I say, I suspect everyone else will be at a loss too :(

wwb
Aug 17, 2004

First, stop generating XML as strings. It isn't a string it is an object graph with a string representation.

As a temporary fix, you should try forcing a particular encoding.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

wwb posted:

First, stop generating XML as strings. It isn't a string it is an object graph with a string representation.

As a temporary fix, you should try forcing a particular encoding.

I will move away from XML as strings, however, the problem arises even when I do something like:

code:
	$string = "";
	foreach($update in $updates) {
		$string += $update.Title;
	}
	$string | Out-File "file.txt" -Encoding ASCII
This makes me believe it's something else going on. Additionally, if I turn off the windows update check in the script, the problems go away.

Also, I have tried replacing the foreach loop with a HUGE string containing the (valid) XML of all the historic updates, and this works absolutely fine - even with the update check in place.

Powerful Two-Hander
Mar 10, 2004

Mods please change my name to "Tooter Skeleton" TIA.


Are you doing something weird trying to escape out > characters? If you're doing that and converting cross character sets so can get odd results as the raw values get converted between character sets. At the very least, does setting the encoding to UTF-8 change anything?

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

Powerful Two-Hander posted:

Are you doing something weird trying to escape out > characters? If you're doing that and converting cross character sets so can get odd results as the raw values get converted between character sets. At the very least, does setting the encoding to UTF-8 change anything?

I solved the issues by re-writing every single line of code to use the XML object. It's now insanely messy due to the tedious nature of creating attributes everywhere, but at least it works.

UTF-8 didn't change anything at the time

jonnii
Dec 29, 2002
god dances in the face of the jews
I've been working on a set of build/deploy scripts in powershell and since it's my first foray into creating anything I'm willing to show to the public I'd love to get some feedback to make sure I'm doing things correctly. The scripts are here

https://github.com/jonnii/BuildDeploySupport/tree/master/package/tools/deploy

The first thing I've done wrong is that I'm not using Verb-Noun style naming, which is something I'm going to fix. Is there anything else I could do?

gbeck
Jul 15, 2005
I can RIS that

jonnii posted:

I've been working on a set of build/deploy scripts in powershell and since it's my first foray into creating anything I'm willing to show to the public I'd love to get some feedback to make sure I'm doing things correctly. The scripts are here

https://github.com/jonnii/BuildDeploySupport/tree/master/package/tools/deploy

The first thing I've done wrong is that I'm not using Verb-Noun style naming, which is something I'm going to fix. Is there anything else I could do?

A couple of things I noticed
  • Use comment based help. I always appreciate being able to "get-help" on a script and get reasonable results.
  • Add CmdletBinding
  • Avoid using Write-Host. If at some point you wanted to be able to put objects in the pipeline the Write-Hosts are going to cause problems. You can use Write-Verbose instead and then just call your script with -verbose (assuming CmdletBinding).
  • Avoid using aliases in the script. You should always use the proper name for commands/cmdlets/params. For example: Remove-Item instead of rm. If you don't know the actual name you can run get-help {alias}. It will return the help for the actual command.
  • This is just a personal preference but I avoid using the backtick (`) in scripts. For commands that have a lot a params I use splatting instead.

Mierdaan
Sep 14, 2004

Pillbug

gbeck posted:

[*]This is just a personal preference but I avoid using the backtick (`) in scripts. For commands that have a lot a params I use splatting instead.

Splatting is a thing? Why do you prefer it?

jonnii
Dec 29, 2002
god dances in the face of the jews

gbeck posted:

A couple of things I noticed
  • Use comment based help. I always appreciate being able to "get-help" on a script and get reasonable results.
  • Add CmdletBinding
  • Avoid using Write-Host. If at some point you wanted to be able to put objects in the pipeline the Write-Hosts are going to cause problems. You can use Write-Verbose instead and then just call your script with -verbose (assuming CmdletBinding).
  • Avoid using aliases in the script. You should always use the proper name for commands/cmdlets/params. For example: Remove-Item instead of rm. If you don't know the actual name you can run get-help {alias}. It will return the help for the actual command.
  • This is just a personal preference but I avoid using the backtick (`) in scripts. For commands that have a lot a params I use splatting instead.

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?). I couldn't get the splats working with the calls to mage =(

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

Defghanistan
Feb 9, 2010

2base2furious
Hello,

I am trying to write a function that takes a parameter as non-mandatory input and turns it into a global variable within the function.

The idea being that the user passes:

PS:> Open-PSSession $ip $creds $variable

and it opens a session for him that is mapped to $variable. I can make this work with a static variable by simply using $global:s = (command) within the function, but what I want to do is use $global:$variable = (command) so that it maps the sessions to whatever variable the user desires.

What's the best way to go about this?

Edit: Forget it, I am an idiot. Just run $frank = Open-PSSession $Param1 $Param2

It's Friday, whatever

Defghanistan fucked around with this message at 18:58 on Apr 5, 2013

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer
I've got the script below which shows all accounts that are going to expire in the next 60 days:

code:
search-adaccount -accountexpiring -timespan (new-timespan -days 60) | ft Name,samaccountname,accountexpirationdate > Useraccounts-expiring-2months.csv
I need to set it up so that it only displays samaccountnames that start with the word "con-" (we use it for consultants). I tried the code below and the cmdlet runs, but produces no output. I'd previously run it without the where cmdlet below and it does produce a list of users whose accounts are expiring, including con- users.

code:
search-adaccount -accountexpiring -timespan (new-timespan -days 60) | where {$_.Samaccountname -eq "Con-*"} | ft Name,samaccountname,accountexpirationdate > Useraccounts-expiring-2months.csv
Any knowledge on how I should format the wildcard mask that will only show con- user IDs?

Mierdaan
Sep 14, 2004

Pillbug
Use where {$_.samaccountname -like "Con-*"} instead.

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer

Mierdaan posted:

Use where {$_.samaccountname -like "Con-*"} instead.

The man = you. Spits out exactly what I need!

A secondary question, not entirely Powershell but possibly a logical growth out of it. Let's say you have a csv that Powershell creates automatically from a script. Anyone know of an application or service that runs automatically, takes the csv, applies text to columns (fixed width), saves it as xls, and saves it to another location?

It'd go like this:

1) The search-adaccount cmdlet runs, generating a list of users by name, samaccountname, and lastlogondate to SearchAccount.csv
2) The solution opens SearchAccount.csv
3) The solution runs text to columns across predetermined widths
4) The file is saved as Q:\Audit\ExpiringAccounts.csv

MJP fucked around with this message at 19:53 on Apr 10, 2013

adaz
Mar 7, 2009

MJP posted:

The man = you. Spits out exactly what I need!

A secondary question, not entirely Powershell but possibly a logical growth out of it. Let's say you have a csv that Powershell creates automatically from a script. Anyone know of an application or service that runs automatically, takes the csv, applies text to columns (fixed width), saves it as xls, and saves it to another location?

It'd go like this:

1) The search-adaccount cmdlet runs, generating a list of users by name, samaccountname, and lastlogondate to SearchAccount.csv
2) The solution opens SearchAccount.csv
3) The solution runs text to columns across predetermined widths
4) The file is saved as Q:\Audit\ExpiringAccounts.csv

You can do all this in powershell using the Excel Interop classes and the TextToColumns method: http://msdn.microsoft.com/en-us/library/office/microsoft.office.interop.excel.range.texttocolumns%28v=office.14%29.aspx.

The scripting guys have done a number of columns on working with Excel data from powershell: http://blogs.technet.com/b/heyscriptingguy/archive/tags/microsoft+excel/?Redirected=true

adaz fucked around with this message at 00:03 on Apr 11, 2013

Defghanistan
Feb 9, 2010

2base2furious
Ok got another one, hopefully less obvious than my last question:

I use WDS to deploy production servers but for various reasons I do not want to auto-join a domain. My process then is:

Use WDS to deploy servers in the imaging VLAN (we don't allow DHCP helpers to span VLANs)
Servers come up in workgroup
Servers are Re-IP'd to final production IP addresses
Servers are moved into accurate VLAN's
Servers are added to domain and baselined

The step I am having issues with is how to remotely add batches of servers to the domain via PS remoting.

Specifically, the usage of Get-Credential objects when working with Add-Computer.

The way I can get around it via ICM is running manual commands:

icm $sessions {$username = "domain\user"}
icm $sessions {$password = "plaintextpassword"}
icm $sessions {$securepass = $password | ConertTo-SecureString -asPlainText -Force}
icm $sessions {$creds = New-Object System.Management.Automation.PSCredential ($username,$securepass)}
icm $sessions {$domain = "domain.name.com"
icm $sessions {Add-Computer -DomainName $domain -Credential $creds}

but when I convert this to a function using the exact same process I am unable to make this work correctly using

PS:> icm $sessions {Function-Name ($Args[0]) ($Args[1]) ($Args[2])} -ArgumentList $domain $username $password

What is the best way to add remote servers to a domain en masse? Ideally in the most secure way possible, avoiding plaintext passowrds (this is a lower priority right now, just need something that works).

My current workaround is to just not pass a password in Add-Computer and have every computer prompt me to re-type the password. This works, but if you were doing more than like, 10, it would be awful.

Edit: I resolved my issue- it was a minor mistake on my end within the function. I'll post up my server baselining process soon to get some input on it because I'd like to improve it.

Defghanistan fucked around with this message at 16:34 on Apr 15, 2013

Swink
Apr 18, 2006
Left Side <--- Many Whelps
Am I using If statements correctly?

code:
$Location = "Melbourne"

If ($location = "Sydney") {
Do things
}

Elseif ($location = "Melbourne") {
Do nothing
}

When I run the above, when it hits the first If statement it changes the variable to "Sydney" and runs the code for the Sydney location. How should I be writing it?

EDIT - Solved. need to use -eq instead of the "=" sign.



New Question:

How easy is it to create a web frontend for powershell scripts? For instance a user creation script with a dropdown box to select department.

Swink fucked around with this message at 07:30 on Apr 16, 2013

Drumstick
Jun 20, 2006
Lord of cacti
I need a way to change the dial-in settings for users in AD to Control Access Through NPS Network Policy. So far my searching has only turned up ways to set it to Allow or Deny. Does anyone have any suggestions on how to set this? Some users are set correctly, however I have 12,000 students/staff accounts that need to be set so they authenticate on our radius server.

The Gripper
Sep 14, 2004
i am winner

Drumstick posted:

I need a way to change the dial-in settings for users in AD to Control Access Through NPS Network Policy. So far my searching has only turned up ways to set it to Allow or Deny. Does anyone have any suggestions on how to set this? Some users are set correctly, however I have 12,000 students/staff accounts that need to be set so they authenticate on our radius server.
I believe you can just do netsh set user name=adusername dialin=policy, which should use remote access policies to determine access (which in this case should match the Control access through NPS Network Policy setting).

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Swink posted:

New Question:

How easy is it to create a web frontend for powershell scripts? For instance a user creation script with a dropdown box to select department.

You're going to want to do it in ASP .NET. You should be able to execute a PowerShell script from C# / VB with the System.Management.Automation assembly, although I'm not sure what restrictions are in place there.

What you definitely shouldn't do is make a webpage that allows arbitrary commands to be executed on the web server in order to make your script work.

Drumstick
Jun 20, 2006
Lord of cacti

The Gripper posted:

I believe you can just do netsh set user name=adusername dialin=policy, which should use remote access policies to determine access (which in this case should match the Control access through NPS Network Policy setting).

I tried this and it kept returning an error, command not found.
I did find set-aduser <name> -replace @{msnpallowdialin=$true/$false} but to allow by policy it needs to be set as empty which to be honest, I have no idea how to do.

Edit: Found a tool to do it. http://admodify.codeplex.com/ doesnt help me learn anything more about powershell, but it sure does get the job done.

Drumstick fucked around with this message at 13:34 on Apr 16, 2013

The Gripper
Sep 14, 2004
i am winner

Drumstick posted:

I tried this and it kept returning an error, command not found.
I did find set-aduser <name> -replace @{msnpallowdialin=$true/$false} but to allow by policy it needs to be set as empty which to be honest, I have no idea how to do.
Hm, that is pretty annoying. You could try setting msnpallowdialin=$null and see if that counts as the default value, since MSDN seems to list that attribute as being boolean when it obviously isn't.

Vulture Culture
Jul 14, 2003

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

Swink posted:

How easy is it to create a web frontend for powershell scripts? For instance a user creation script with a dropdown box to select department.
Work on the basics before getting too far ahead of yourself or you're gonna have a bad time. (Also, whoever has to maintain this poo poo once you leave is gonna hate you beyond belief.)

evil_bunnY
Apr 2, 2003

It would be trivial to make a CLI script user-friendly instead.

Drumstick
Jun 20, 2006
Lord of cacti

The Gripper posted:

Hm, that is pretty annoying. You could try setting msnpallowdialin=$null and see if that counts as the default value, since MSDN seems to list that attribute as being boolean when it obviously isn't.

Yeah, that was the confusing part. Everything I saw had it listed as a boolean when there are 3 options. I did try and set it to $null and it would throw up a bunch of errors. After trying a few things I was able to find that program that got me what I needed. Thank you for the help!

Swink
Apr 18, 2006
Left Side <--- Many Whelps

evil_bunnY posted:

It would be trivial to make a CLI script user-friendly instead.

You're right. You're all right. I needed that reality check.

Is there a prettier method of getting the user to make a selection? At the moment I use this:


Switch ($Choice)
{
1 {$location = "Sydney"}
2 {$location = "Melbourne"}
3 {$location = "Brisbane"}
}

Which I find a bit hideous.

kampy
Oct 11, 2008

Swink posted:

Is there a prettier method of getting the user to make a selection? At the moment I use this:

Parameters for your script/function would be the best way really, here are a couple of simple examples, check help about_functions_advanced_parameters in powershell for more things you could do:

code:
function Show-Thingy
{
    param
    (
        [Parameter(Mandatory=$true)]
        [ValidateSet("Melbourne","Sydney","Brisbane")]
        [String] $Location
    )

    $Location
}

function Show-OtherThingy
{
    [CmdletBinding(DefaultParameterSetName="Melbourne")]
    param
    (
        [Parameter(ParameterSetName="Melbourne")]
        [Switch] $Melbourne,
        [Parameter(ParameterSetName="Sydney")]
        [Switch] $Sydney,
        [Parameter(ParameterSetName="Brisbane")]
        [Switch] $Brisbane,
        [String] $Name="nobody"
    )
    Process
    {
        "{0}, said {1}" -f ($PSCmdlet.ParameterSetName, $Name)

        if ($PSCmdlet.ParameterSetName -eq "Sydney")
        {
            "Hello $Name!"
        }
    }
}

Adbot
ADBOT LOVES YOU

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer
I'm trying to identify all AD accounts that are expired and have also never logged on, while excluding the Out of Band group (it's got all the $ime computer accounts).

Here's what I've got:

code:
get-aduser -filter {not ( lastlogontimestamp -like "*" -and (enabled -eq $false) -and (distinguishedname -not like "*out of*") }
This returns no results. If I use enabled -eq $true that also returns nothing. However, if I remove the -and (distinguishedname) part, I get a long list of users.

The only thing is that this lists disabled users, not users who have account expiration dates which have already passed. Let's say Jane Doe had an expiration date of last week - I want to find Jane Doe, not John Doe, a user who had no expiration date in AD but was disabled.

I tried looking around for an AD attribute that specifies an expired user with no luck - anyone know how I can go about that, and how I should execute the filter to exclude Out of Band?

Edit: Okay, found my answer in the Powershell.org forums:

code:
get-aduser -filter {not ( lastlogontimestamp -like "*" -and (enabled -eq $false) | where {$_.DistinguishedName -notmatch 'Out of'
I added a few of these to the cmdlet for other OUs to filter out and they're pretty effective.

Still looking for how I can only search on Expired users - I'm still getting Disabled users.

MJP fucked around with this message at 20:54 on Apr 30, 2013

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