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
Vulture Culture
Jul 14, 2003

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

FISHMANPET posted:

Nevermind what a loving task it was to get powershell to even search. And nevermind how impossible Microsoft has made it to actually get the AD cmdlets. Why in the hell would I have to run a special instance of Powershell (Active Directory Module for Windows PowerShell) to actually be able to query AD. Shouldn't running Powershell on the DC be enough?
Import-Module ActiveDirectory

FISHMANPET posted:

So I say to myself, this sounds perfect for Powershell! Except Powershell can't read the profile paths out of most of my accounts, they just show up as null. dsget works just fine, and looking at them in AD Users & Computers I see the bad profile path, but get-aduser shows nothing.
Get-ADUser -Filter * -Properties profilePath | Where-Object { $_.ProfilePath -match '\\server2' }

Adbot
ADBOT LOVES YOU

FISHMANPET
Mar 3, 2007

Sweet 'N Sour
Can't
Melt
Steel Beams

Misogynist posted:

Import-Module ActiveDirectory

Get-ADUser -Filter * -Properties profilePath | Where-Object { $_.ProfilePath -match '\\server2' }

That would have been just fine, except for a lot of the accounts the ProfilePath was listed as empty.

PhonyMcRingRing
Jun 6, 2002
So I may very well be using the Powershell ISE for the wrong thing, but I'm trying to use it as a replacement for the regular command prompt. No real reason other than I think it looks nicer. However, when trying to do some ruby on rails stuff, I noticed I can't get the "rails console" command to work. It starts the console, but the irb never pops up and I'm forced to terminate the ruby.exe instance that's launched before I can send any more commands through the ISE. Is the ISE unable to work with interactive programs being launched from inside of it?

adaz
Mar 7, 2009

PhonyMcRingRing posted:

So I may very well be using the Powershell ISE for the wrong thing, but I'm trying to use it as a replacement for the regular command prompt. No real reason other than I think it looks nicer. However, when trying to do some ruby on rails stuff, I noticed I can't get the "rails console" command to work. It starts the console, but the irb never pops up and I'm forced to terminate the ruby.exe instance that's launched before I can send any more commands through the ISE. Is the ISE unable to work with interactive programs being launched from inside of it?

The ISE runs in STA mode, if Ruby on Rails is requiring MTA then that could be it. I'm not familiar at all with the ruby tools to say for sure. I've launched interactive programs from inside the ISE before (usually winform type stuff from a powershell script).

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer
I've got a couple of projects that were given that require a list of Windows servers, their current OS (2k3, 2k3 R2, 2k8, 2k8R2, etc.) and their current Description field in AD. I've seen how to use dsquery to get a list on a per-OU basis, but optimally what I'd like is a script that queries AD for any machine and outputs its name, Description field, and server OS.

I am not allowed to use the Quest AD cmdlets, which seems to be the solution that everyone who doesn't work for my company goes for. I've already tried to convince the powers that be that it really won't do any harm, especially if all I'm running is a query, but it took enough convincing for me to let Powershell be used.

Any way I can make this happen?

adaz
Mar 7, 2009

MJP posted:

I've got a couple of projects that were given that require a list of Windows servers, their current OS (2k3, 2k3 R2, 2k8, 2k8R2, etc.) and their current Description field in AD. I've seen how to use dsquery to get a list on a per-OU basis, but optimally what I'd like is a script that queries AD for any machine and outputs its name, Description field, and server OS.

I am not allowed to use the Quest AD cmdlets, which seems to be the solution that everyone who doesn't work for my company goes for. I've already tried to convince the powers that be that it really won't do any harm, especially if all I'm running is a query, but it took enough convincing for me to let Powershell be used.

Any way I can make this happen?

Quest AD cmd-lets are crutches :colbert: and yes it's not too hard using the base .NET classes in DirectoryServices

code:
# Use the ADSI type accelerator to bind to your domain
$domain = [adsi]"LDAP://your.domain"

# Create a new DirectoryServices.DirectorySearcher pointed to your domain.
$ADSearcher = New-Object System.DirectoryServices.DirectorySearcher $domain

# Use LDAP search syntax filtering to setup our search filter, using the wildcard
# syntax to return all versions of windows Server
$adSearcher.filter = "(&(objectClass=Computer)(operatingSystem=Windows Server*))"

# Get the properties we care about. Cast to void to avoid printing out the array # index to the console every time we add a property
[void]$adsearcher.propertiestoload.add("operatingSystem")
[void]$adSearcher.propertiestoload.add("description")
[void]$adSearcher.propertiestoload.add("name")

# Retrieve our results.
$results = $adSearcher.FindAll()

# This is the code to export to csv since Export-CSV remains annoying to work with
# and won't handle just $results | export-Csv. So we first create a hashtable
$exportTable = @()
foreach($result in $results) {
	# Shorthand to create an object with 3 properties
	$outObj = "" | select name,description,os

	# set our properties, cast to String using the type accelerator
	$outObj.name = [string]$result.properties.name
	$outObj.description = [string]$result.properties.description
	$outObj.OS = [string]$result.properties.operatingsystem

	# add our object to our hash table
	$exportTable += $outObj
}

# Export to csv
$exportTable | export-Csv C:\temp\blah.csv -noTypeInformation

adaz fucked around with this message at 15:48 on Aug 24, 2012

vanity slug
Jul 20, 2010

I am writing a script to automate the generation of VMs in VMM2012 and I'm at a loss with an error I'm getting. Here's the part that's causing issues:

code:
#
# --- Load Snap-Ins and Modules ---
#
	if(@(Get-PSSnapin | where-object {$_.Name -eq "Microsoft.SystemCenter.VirtualMachineManager"} ).count -eq 0) { Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager }

$objs = @()

#
# --- Import CSV ---
#

$csv_import = Import-Csv "C:\VM Import\VMimport.csv" -Delimiter ,

foreach ($line in $csv_import) {
	$VMName = $line.VMName
	$VMHost = $line.VMHost
	$HyperVDiskPath = $line.HyperVDiskPath

	Write-Host "Creating "$VMName" on "$VMHost" using volume "$HyperVDiskPath"..."
}
Of course there's code after Write-Host for generating the actual VMs but it's irrelevant for the error:

code:
Unexpected token 'in' in expression or statement.
At C:\VM Import\CreateVDI.ps1:14 char:18
+ foreach ($line in <<<<  $csv_import) {
    + CategoryInfo          : ParserError: (in:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken
I've googled around a bit and really can't find the solution to this issue. I know I probably missed something extremely simple, but I'm not getting it right now :downs:

edit: Yep, it was really that simple. Changed it to

code:
$csv_import = Import-Csv "C:\VM Import\VMimport.csv" -Delimiter ","
and it works :)

vanity slug fucked around with this message at 15:05 on Aug 30, 2012

Swink
Apr 18, 2006
Left Side <--- Many Whelps
I need to set a HTML signature for a stack of OWA users. I grabbed this script from the web

code:
$mailboxes = get-mailbox 
$mailboxes| foreach {$file= "c:\signatures\" + ($_.samAccountName) + ".htm"; Set-MailboxMessageConfiguration -identity $_.samAccountNAme -SignatureHtml "$(Get-Content -Path $file -ReadCount 0)" -AutoAddSignature $True}
Which gets all the mailboxes, grabs the same-named html file from the folder and applies it to the OWA. What I want to do is turn it around so instead of iterating through every mailbox, it iterates through the files in c:\signatures and applies to the same-named mailbox.

The reason being I have 1000 mailboxes but only 500 OWA users, and I only know who they are based on whether they have a sig file in the folder.


Edit: Did it all by myself! Look at me go!

code:
$sigs = gci C:\sigs\ 

$sigs | foreach {$file = $_.FullName; Set-MailboxMessageConfiguration -identity $_.name -SignatureHtml "$(Get-Content -Path $File -ReadCount 0)" -AutoAddSignature $True}

Swink fucked around with this message at 07:03 on Sep 4, 2012

Wicaeed
Feb 8, 2005
:facepalm:

So for the long time was trying to get a powershell script that (simply) let me know if the current day was the first weekday of the month. For mailing purposes I send an email based on whether or not that is true

code:
$currentday = get-date
$weekdays = "Monday","Tuesday","Wednesday","Thursday","Friday"
$months = 1..12
$firstofmonth = foreach ($month in $months) {1..7| %{get-date -month $month -day $_} | ?{$weekdays -contains $_.dayofweek}|select -first 1}

Function Firstday {
    If ($firstofmonth -contains $currentday)
        {write-host "First weekday of the month"}
    Else
        {Write-Host "Not the first weekday of the month"}
    }

Firstday
FINALLY I was able to do it. I love/hate Powershell

Vulture Culture
Jul 14, 2003

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

Wicaeed posted:

:facepalm:

So for the long time was trying to get a powershell script that (simply) let me know if the current day was the first weekday of the month. For mailing purposes I send an email based on whether or not that is true

code:
$currentday = get-date
$weekdays = "Monday","Tuesday","Wednesday","Thursday","Friday"
$months = 1..12
$firstofmonth = foreach ($month in $months) {1..7| %{get-date -month $month -day $_} | ?{$weekdays -contains $_.dayofweek}|select -first 1}

Function Firstday {
    If ($firstofmonth -contains $currentday)
        {write-host "First weekday of the month"}
    Else
        {Write-Host "Not the first weekday of the month"}
    }

Firstday
FINALLY I was able to do it. I love/hate Powershell
You don't really need to do any date manipulation besides getting the day of the week and the day of the month. If you stop to consider what you're actually trying to find out, there are only two conditions that satisfy the test for "this is the first weekday of the month":

  • It's the 1st of the month and it's a weekday
  • It's the 2nd or 3rd of the month and it's Monday

So you can cut it down to this:

code:
$date = Get-Date
$day = $date.Day
$dow = $date.DayOfWeek
if (($day -eq 1 -and $dow -ne "Saturday" -and $dow -ne "Sunday") -or (($day -eq 2 -or $day -eq 3) -and $dow -eq "Monday")) {
    Write-Host "First weekday of month"
} else {
    Write-Host "Not first weekday of month"
}

Vulture Culture fucked around with this message at 00:15 on Sep 6, 2012

adaz
Mar 7, 2009

Powershell 3.0 is now available officially for download (win 7, win2008, win2k8 R2 and above). http://blogs.technet.com/b/heyscriptingguy/archive/2012/09/06/powershell-3-0-is-now-available-for-download.aspx

Highly recommended, the intellisense in the IDE alone is worth it

Swink
Apr 18, 2006
Left Side <--- Many Whelps
Never mind!

Swink fucked around with this message at 12:33 on Sep 11, 2012

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe
Am I going about things in entirely the wrong way, or is handling HTTP requests a very cumbersome process in Powershell? For instance, if I wanted to get google's homepage, I could do something like this:

code:
$Request = [System.Net.WebRequest]::Create("http://www.google.com")
$Request.Method = "Get"
$Response = $Request.GetResponse()
$Stream = $Response.GetResponseStream()
$Reader = New-Object System.IO.StreamReader $Stream;
$Reader.ReadToEnd()
Is there really no simpler way to do this?

kampy
Oct 11, 2008

stubblyhead posted:

Am I going about things in entirely the wrong way, or is handling HTTP requests a very cumbersome process in Powershell? For instance, if I wanted to get google's homepage, I could do something like this:

Is there really no simpler way to do this?

That's pretty much the way it goes in PowerShell v2, in v3 you can use Invoke-WebRequest http://www.google.com

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

kampy posted:

That's pretty much the way it goes in PowerShell v2, in v3 you can use Invoke-WebRequest http://www.google.com

Good thing I'm using PS 3.0! :v: This is about 1000% simpler, thanks for the tip!

Tomahawk513
Jul 18, 2011
I have a situation where I need to write a script that will look at three pieces of information in order to add them to certain corresponding mail groups. Normally this would not be difficult. However, the third piece of information is a combination of the first two. So it's like a Venn Diagram:

Location = Location Mail Group
Location + Role = Location Role Mail Group
Role = Role Mail Group

For Location and Role I wrote:

code:
$samaccountname = read-host -prompt "Enter Username"
$Location = read-host -prompt "Enter Office:"

switch ($Location)
    {
            Robinson {add-qadmemberof $samaccountname -group "Robinson All Mail group"}
            Westfield {add-qadmemberof $samaccountname -group "Westfield All Mail Group"}
            Central {add-qadmemberof $samaccountname -group "Central Ave Mail Group"}       
    }
All fine and dandy, but how do I tie the two together to create a third set of options?

In other words, I want a short version of:
code:
if ($location -eq "Alpha") -and ($role -eq "Bravo") {
    add-qadmemberof $samaccountname -group "Alpha Bravo Mail Group"
}
Thanks,
-Brian

adaz
Mar 7, 2009

There are a bunch of more elegant ways of doing this (SQL y'all) but based on what you described here you go. You create a typed object and run where-Object queries off that? I assume role is also entered by the users..

I.e.

code:
$userTable = @{}

$userObj = "" | select sam,location,role
$userObj.sam = read-host -prompt "Enter Username"
$userObj.Location = read-host -prompt "Enter Office:"
$userObj.role = read-host -prompt "Enter Role:"
$userTable += $userObj

# Group queries

$usersToAdd = $userTable | where-Object {$_.Location -eq "Hello"}
$usersToAdd | add-qadmemberof $_.sam -group "Robinson All Mail group"

# Group + Role queries
$usersToAdd = $userTable | where-Object {$_.Location -eq "Hello" -and $_.Role -eq "blah"} |

You can get Even Fancier by loading up a csv as an object that had the group info predefined in it and looping through that so you wouldn't have to hard code the queries.

adaz fucked around with this message at 03:25 on Sep 20, 2012

Swink
Apr 18, 2006
Left Side <--- Many Whelps
Anyone else getting a shitload of yellow warning errors with 3.0? I'm getting them with every command. Although it might be the exchange2010 snapin I'm using.

Also, half of the commands dont have a help entry, and update-help doesnt work. Running as Admin or otherwise.

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

Swink posted:

Anyone else getting a shitload of yellow warning errors with 3.0? I'm getting them with every command. Although it might be the exchange2010 snapin I'm using.

Also, half of the commands dont have a help entry, and update-help doesnt work. Running as Admin or otherwise.

I haven't had any problems with warnings myself. I have had some issues with Get-Help though, mostly that it wants to download updates to it frequently. It hasn't done it for a while though, but when I first installed it it would try the first time I'd use it in a session.

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer
A request came in to create a distro based on user names alone. That was done. Now the requestor wants a list of the email addresses of the users as well.

I'm using Exchange 2007 shell and get-distributiongroupmember -identity "groupname" | fl PrimarySMTPAddress lists the addresses, but is there any way to also list the name and then I can just > nameslist.csv it to him?

Edit: bada bing. get-distributiongroupmember -identity "groupname" | format-table Name,PrimarySMTPaddress > nameslist.csv did the trick and some text to columns made it legible.

MJP fucked around with this message at 16:47 on Sep 27, 2012

kampy
Oct 11, 2008

MJP posted:

Edit: bada bing. get-distributiongroupmember -identity "groupname" | format-table Name,PrimarySMTPaddress > nameslist.csv did the trick and some text to columns made it legible.

I don't have the exchange cmdlets installed, but you might want to consider using select and Export-Csv there instead of format-table, something like this should work:

code:
get-distributiongroupmember -identity "groupname" | select Name,PrimarySMTPAddress | Export-Csv -Path nameslist.csv -NoTypeInformation

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

kampy posted:

I don't have the exchange cmdlets installed, but you might want to consider using select and Export-Csv there instead of format-table, something like this should work:

code:
get-distributiongroupmember -identity "groupname" | select Name,PrimarySMTPAddress | Export-Csv -Path nameslist.csv -NoTypeInformation

Yeah, Import-csv is a POS, but export works pretty well. You don't need to do that sort of redirection in powershell.

aBagorn
Aug 26, 2004
So here's my situation, goons:

We have a .NET application hosted on our web server that does read only access to an old legacy UniVerse file store.

Whenever the connection times out or the Application Pool resets, the first access to the file store is inordinately slow.

What I'd like to do is script a dummy "search" and run it on the server 3-5 minutes before open of business each day.

The search is done using an AJAX POST method with a JSON object that is determined by the text in a text box.

If I just wanted to simulate that, would it be possible from a powershell standpoint?

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer
So what I'm trying to do is develop a Powershell script that I'd run as a daily scheduled task. We have three Citrix servers where individual user profiles get created.

What I want to do is tell Powershell to run the delprof2 command with the arguements specified (one script per server), say Y to start the process, then wait for it to ask "Delete profile X?"

Some profiles should never get deleted. It should say N to those. For everything else, it should say Y.

I have her X being what I think is the list of users to say N to. The $y line is what the command comes back with where I need it to say Y to start the process. After that it'll spit out a list of names and say "Delete profile 'profilelocation'" which waits for a Y or N.

I redacted out any potentially identifying info, so for the purposes of what you see, administrator, jdoe, and Citrix are the accounts that should always get an N.

code:
\\servername\c$\tools\delprof2 /c:\servername /p

$x = Administrator -or jdoe -or Citrix #Special accounts to never delete
$y = Delete inactive profiles on 'Servername'? (Yes/No) #Say Y to start the process
  if ($x) {Write-Host "N"} #Say N since this account should never be deleted
  elseif {Write-Host "Y"} #say Y to delete all other accounts not specified in $x 
 

Siets
Sep 19, 2006

by FactsAreUseless
Does anybody else do

code:
Write-Host -Fore Cyan
Write-Host -Fore DarkCyan
...for all their console output so that it looks like Tron text, or is that just me? :3:

(Also Consolas for life.)

Mierdaan
Sep 14, 2004

Pillbug
I cooked up a script to generate a list of AD account names, based off an HR-provided list of full names. I figure I'll throw it in here and see if anyone has a better / more effective way of doing this.

Basically I'm trying to account for the special snowflakes whose account name can't be easily guessed from their first initial and last name (our standard convention). This script still has issues with things like nicknames (HR has them on file as Elizabeth, their AD GivenName is Beth), people with complicated last names ("Van Buren"), etc. Seems to get about 98% of our users correctly, but accounting for the last 2% is a pain.

code:
import-module ActiveDirectory

#Required – CSV file with full names "fullNames.csv"
#Effect – generates file with SAMAaccountName names only "accountNames.csv"

$userlist = import-csv "Z:\scripts\fullNames.csv"

remove-item "Z:\scripts\accountNames.csv"
new-item "Z:\scripts\accountNames.csv" -type file
add-content "Z:\scripts\accountNames.csv" "Name"
Foreach($person in $userlist) {
    $stringName = $person.Name
    $stringNameArray = $stringName.split(" ")
    $accountName = $null
    $firstName = $stringNameArray[0]
    $lastName = $stringNameArray[-1]
    $guessAccountName = $firstName[0] + $lastName
    # First, check for properly-formed username (e.g. 'jsmith')
    $accountName = get-aduser $guessAccountName -properties * | where-object {$_.distinguishedName -like "*OU=Staff,DC=domain,DC=com"} | select -expand samaccountname
    if ($accountName -eq $null) {
            # Second, check for a user based on firstName + lastName
            $accountName = get-aduser -filter { GivenName -like $firstName -and SurName -like $lastName } -searchbase "OU=Staff,DC=domain,DC=com" -properties * | select -expand samaccountname
        }
    if ($accountName -eq $null) {
            # Third, check for a user with accountName == firstName (e.g. 'edwin')
            $accountName = get-aduser $firstName -properties * | where-object {$_.distinguishedName -like "*OU=Staff,DC=domain,DC=com"} | select -expand samaccountname
       }
    if ($accountName -ne $null) {
        # if a lookup succeeded, write output
        add-content "Z:\scripts\accountNames.csv" $accountName
        }
    else {
        # if no lookups succeeded, write easily-flagged output for human review
        $blargh = "________" + $stringName
        add-content "Z:\scripts\accountNames.csv" $blargh
        }
}

# Check that input/output rows match
$file1 = get-content "Z:\scripts\fullNames.csv"
$file2 = get-content "Z:\scripts\accountNames.csv"

if ($file1.length -eq $file2.length) {exit;}
else {write-host "File row counts don't match!!!"}

adaz
Mar 7, 2009

Why not search the GivenName and Lname attributes directly? LDAP search like "(&(fname=$fname)(sn=$lname))" etc? Are there any other key fields you can search on, like some companies will enter employeeID into the fields, or have a sane and rational email address schema you can search on.

Like ours is always first.last@domain.gov, or first.mi.last@domain.gov and we only allow - as special characters in the email. So that can usually get 99+% of users, there are always the few special folks who have to be manually found.

Mierdaan
Sep 14, 2004

Pillbug

adaz posted:

Why not search the GivenName and Lname attributes directly? LDAP search like "(&(fname=$fname)(sn=$lname))" etc? Are there any other key fields you can search on, like some companies will enter employeeID into the fields, or have a sane and rational email address schema you can search on.

I do do that, that's the second get-aduser I try. We still run into problems with people like Elizabeth vs. Beth, though. I guess that's the main problem, if we forced AD accounts to always be the legal names HR keeps on file we'd be a lot better off.

adaz
Mar 7, 2009

Mierdaan posted:

I do do that, that's the second get-aduser I try. We still run into problems with people like Elizabeth vs. Beth, though. I guess that's the main problem, if we forced AD accounts to always be the legal names HR keeps on file we'd be a lot better off.

Yeah there's not really a programming solution here other than use gname and fname attributes in AD to put in their given name and use fname to put in their "preferred" name. Or tie the accounts back to HR if you folks use employee number or something other UID

Mierdaan
Sep 14, 2004

Pillbug

adaz posted:

Yeah there's not really a programming solution here other than use gname and fname attributes in AD to put in their given name and use fname to put in their "preferred" name. Or tie the accounts back to HR if you folks use employee number or something other UID

Thanks, employee ID might work for us.

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer

MJP posted:

So what I'm trying to do is develop a Powershell script that I'd run as a daily scheduled task. We have three Citrix servers where individual user profiles get created.

What I want to do is tell Powershell to run the delprof2 command with the arguements specified (one script per server), say Y to start the process, then wait for it to ask "Delete profile X?"

Some profiles should never get deleted. It should say N to those. For everything else, it should say Y.

I have her X being what I think is the list of users to say N to. The $y line is what the command comes back with where I need it to say Y to start the process. After that it'll spit out a list of names and say "Delete profile 'profilelocation'" which waits for a Y or N.

I redacted out any potentially identifying info, so for the purposes of what you see, administrator, jdoe, and Citrix are the accounts that should always get an N.

code:
\\servername\c$\tools\delprof2 /c:\servername /p

$x = Administrator -or jdoe -or Citrix #Special accounts to never delete
$y = Delete inactive profiles on 'Servername'? (Yes/No) #Say Y to start the process
  if ($x) {Write-Host "N"} #Say N since this account should never be deleted
  elseif {Write-Host "Y"} #say Y to delete all other accounts not specified in $x 
 

Figured I'd re-inquire... anyone?

Defghanistan
Feb 9, 2010

2base2furious
Does anyone know how to find the file associated with the function currently loaded into memory?

For example let's say I load a function:

***begin***
cd D:\scripts
.\renameserver.ps1

Rename-Computer $name $creds
***end***

Is there any way to find the source file that Rename-Computer was loaded from? I've been digging for this and haven't found it anywhere but it seems really useful.

kampy
Oct 11, 2008

Defghanistan posted:

Does anyone know how to find the file associated with the function currently loaded into memory?

For example let's say I load a function:

***begin***
cd D:\scripts
.\renameserver.ps1

Rename-Computer $name $creds
***end***

Is there any way to find the source file that Rename-Computer was loaded from? I've been digging for this and haven't found it anywhere but it seems really useful.

code:
(Get-Item Function:\Rename-Computer).ScriptBlock.File

adaz
Mar 7, 2009

MJP posted:

Figured I'd re-inquire... anyone?

Sure, something like this.

code:
[array]$excludeUsers = "citrix","admin","blah"
$profiles = get-Childitem C:\users -directory  -exclude $excludeUsers


Defghanistan
Feb 9, 2010

2base2furious

kampy posted:

code:
(Get-Item Function:\Rename-Computer).ScriptBlock.File

Wow that didn't take long, thank you!

MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer

adaz posted:

Sure, something like this.

code:
[array]$excludeUsers = "citrix","admin","blah"
$profiles = get-Childitem C:\users -directory  -exclude $excludeUsers



So am I looking at this as a possible script:

code:
\\servername\c$\tools\delprof2 /c:\servername /p

$x = [array]$excludeUsers = "Citrix","admin","Track"
$profiles = get-Childitem C:\users -directory  -exclude $excludeUsers
$y = Delete inactive profiles on 'Servername'? (Yes/No) #Say Y to start the process
  if ($x) {Write-Host "N"} #Say N since this account should never be deleted
  elseif {Write-Host "Y"} #say Y to delete all other accounts not specified in $x 
Also I got a doozy of an item that I need to finish by 11/28... I am to make a script that:

1) When double-clicked, query all site OUs (e.g. one for NYC, one for ATL, one for each other physical location we have) and list the users in the Non-IT Users, Business Users, and Other Users OUs (names changed)
2) Display the results of the query in a dropdown list by Lastname, Firstname
3) Allow user to be selected in the dropdown and click Move in the script
4) When Move is clicked, add the user to a security group - optimally by using dsmove but other workable options should be OK.

I was able to use
code:
 get-aduser -filter * -searchbase "OU=Non-IT Users,OU=ATL,DC=subdomain,DC=domain,DC=com"
to get lists of users from each OU, but I can't figure out how to get it into the dropdown or even list the user's name by lastname, let alone the rest.

I guess to start: how do I do the listing by last name in a regular old Windows dropdown? Would it be something like this:

code:
# Display users in dropdown list
2
Select-GUIObject "Host" 
3
# Get the VMs for the selected host
4
$SelObj | Get-aduser for each OU and sub-OU | Out-GridView
Where I'd just run get-aduser with a list of OUs to display the results in?

MJP fucked around with this message at 16:48 on Nov 16, 2012

adaz
Mar 7, 2009

MJP you actually don't need the If statement in there, Get-Childitem just won't even return any values that match its exclusion filter.

As far as your other problem you get lucky I happen to have made a UI List function before in powershell. In general never try to do GUI stuff in powershell unless you have absolutely no choice. It's doable but as you can see from the code below it's also painful and not straightforward at all.

Also Choices should be an enumerable object, like an array of strings.

code:
#################
# Create-UIlist #
#################
# Need these :
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 

Function Create-UIList {
param ($Title,$ChoiceQuestion,$Choices)
# Create our form
$MainForm = New-Object System.Windows.Forms.Form 
$MainForm.Text = $Title
$MainForm.Size = New-Object System.Drawing.Size(300,200) 
$MainForm.StartPosition = "CenterScreen"

# Key Handlers for enter & Escape
$MainForm.KeyPreview = $True
$MainForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
    {$Script:Result=$ListBox.SelectedItem;$MainForm.Close()}})
$MainForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
    {$MainForm.Close()}})

# OK button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$Script:Result=$ListBox.SelectedItem;$MainForm.Close()})
$MainForm.Controls.Add($OKButton)

# Cancel Button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$MainForm.Close()})
$MainForm.Controls.Add($CancelButton)

# Label
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = $ChoiceQuestion
$MainForm.Controls.Add($objLabel) 

# Our list box
$ListBox = New-Object System.Windows.Forms.ListBox 
$ListBox.Location = New-Object System.Drawing.Size(10,40) 
$ListBox.Size = New-Object System.Drawing.Size(260,20) 
$ListBox.Height = 80

# Choices for list box
for ($i=0;$i -lt $Choices.Count; $i++) {
[void]$ListBox.Items.Add($Choices[$i])
}


# Add controls for Form & Show it.
$MainForm.Controls.Add($ListBox) 
$MainForm.Topmost = $True
$MainForm.Add_Shown({$MainForm.Activate()})
[void]$MainForm.ShowDialog()
}
Then something like this to use it

code:
Create-UiList "This is my title" "Pick someone pretty." $choicesArr

if($result) {
	# do something
}


MJP
Jun 17, 2007

Are you looking at me Senpai?

Grimey Drawer

adaz posted:

MJP you actually don't need the If statement in there, Get-Childitem just won't even return any values that match its exclusion filter.

As far as your other problem you get lucky I happen to have made a UI List function before in powershell. In general never try to do GUI stuff in powershell unless you have absolutely no choice. It's doable but as you can see from the code below it's also painful and not straightforward at all.

Also Choices should be an enumerable object, like an array of strings.

[code]
Create-UIlist

So how would I use all that to list the contents of the get-aditem cmdlet with all the OUs? If possible can I avoid creating a list to a CSV, or could I include a cmdlet to delete a created list? I'd like to avoid leaving complete lists of all our users on individual machines.

For the record, this is being done so individual help desk users can add users to our admin users group so they can install software after approval. Normally we get tickets to do it. This way we just delegate permissions in AD to the help desk people but we don't give them ADUC to do it.

adaz
Mar 7, 2009

MJP posted:

So how would I use all that to list the contents of the get-aditem cmdlet with all the OUs? If possible can I avoid creating a list to a CSV, or could I include a cmdlet to delete a created list? I'd like to avoid leaving complete lists of all our users on individual machines.

For the record, this is being done so individual help desk users can add users to our admin users group so they can install software after approval. Normally we get tickets to do it. This way we just delegate permissions in AD to the help desk people but we don't give them ADUC to do it.

I don't use the AD cmdlets so this code might nto work but what you want to do is when you grab your users pipe them through Select-Object and grab the property you want, like CN or DN. then send that list to the Create-Uilist. When the list returns with the user's they have selected iterate through, bind to their AD object and perform whatever operation you want.

code:

$users =  get-aduser -filter * -searchbase "OU=Non-IT Users,OU=ATL,DC=subdomain,DC=domain,DC=com" | select-Object {$_.cn}

Create-UiList -Title "This is a test." -ChoiceQuestion "Pick an Option" -Choices $users

if($result) {
	foreach($user in $result) {
		# Grab user off CN/DN and perform operation requested here.
	}

}

Adbot
ADBOT LOVES YOU

kampy
Oct 11, 2008

MJP posted:

So am I looking at this as a possible script:

code:
\\servername\c$\tools\delprof2 /c:\servername /p

$x = [array]$excludeUsers = "Citrix","admin","Track"
$profiles = get-Childitem C:\users -directory  -exclude $excludeUsers
$y = Delete inactive profiles on 'Servername'? (Yes/No) #Say Y to start the process
  if ($x) {Write-Host "N"} #Say N since this account should never be deleted
  elseif {Write-Host "Y"} #say Y to delete all other accounts not specified in $x 

Nope, that won't really help you.

With delprof2, wouldn't you be better off by passing /ed:citrix /ed:admin /ed:track arguments to it directly to exclude certain profiles instead of attempting to use powershell to do so?

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