Pablo's Powershell Pow-Wow

Discussion in 'Business & Enterprise Computing' started by PabloEscobar, Sep 18, 2014.

  1. Ravennoir

    Ravennoir Member

    Joined:
    May 1, 2007
    Messages:
    6,504
    Location:
    Melbourne
    Cool run down on Get-ADUser.

    Im wondering if you have come across an issue I had when using Get-ADUser

    I wanted to get the date that accounts were created so i could filter out some new users.

    Running a command "Get-ADUser <userid> | Select Name,Createdate (from memory) would give me the correct information.

    Running the same command either with -filter *, or in a foreach loop wouldnt return the createdate

    These accounts were created using FIM, so I dont know if that plays a part in it
     
  2. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,412
    How the accounts were created should have no bearing on it, every AD account will have the properties existing, (although some may not be set).

    I'm not sure how you would have gotten the creation date, without using the -properties parameter, because, as per Caveat #1, "whenCreated" isn't a property that is fetched by default.

    But your example can be used to illustrate a couple of things.

    First up -Searchbase... as above, searching through 500K users in my AD takes about 40 seconds, I don't want to wait 40 seconds each time as I'm doing stuff for these examples. so instead, I set my searchbase to an OU that only contains a few users, and I get my results in milliseconds instead of minutes.

    Second, Properties, and filtering on such things.

    Code:
    Get-ADUser -Filter 'title -like "Turtle Tamer"' -SearchBase "OU=TestORGOU,DC=CORP,DC=WHYADMIN,DC=COM"
    
    Get-ADUser -Filter * -SearchBase "OU=TestORGOU,DC=CORP,DC=WHYADMIN,DC=COM" | Where-Object {$_.Title -like "Turtle Tamer"}
    
    These are similar to our example above, instead of filtering on Names starting with A, we are filtering on Titles that are equal to "Turtle Tamer" But unlike the example above, these 2 commands don't give us the same output.

    Example 1, asks AD for all users who have the title of "Turtle Tamer" and AD returns the default properties for those users.

    AD know all about titles, so it does the search for you, and spits out the results, the default property set (as per Caveat #1) doesn't have Title as a fetched property... but because the filtering was done by the Active Directory, the results are correct.

    Example 2 asks for All users, AD returns all Users, and the Where-Object searches those returned users for the title property. Where-Object is being passed AD user objects that ONLY CONTAIN DEFAULT PROPERTIES, so when it looks for a Title property, it doesn't find one, and errors out. the results are not correct

    TL:DR - You can use -filter to filter on AD properties that may not become part of the AD user object you get back, You can only use Where-Object (and Select-Object) on Properties that are Part of the AD User object you get back

    Back to your issue though Ravennoir...


    Code:
    Get-ADUser -Filter * -SearchBase "OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM" | FL *
    
    Fetches all our users (because -Filter * matches everything) in the Simpsons OU, and FL * will show all the properties we can play with.

    Code:
    DistinguishedName  : CN=Bart J. Simpson,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Bart
    Name               : Bart J. Simpson
    ObjectClass        : user
    ObjectGUID         : 38f37c93-7d20-402c-b5f7-0f42758ce8d6
    SamAccountName     : bart.simpson
    SID                : S-1-5-21-1813243300-450990311-3672857015-1166
    Surname            : Simpson
    UserPrincipalName  : bart.simpson@CORP.WHYADMIN.COM
    PropertyNames      : {DistinguishedName, Enabled, GivenName, Name...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 10
    
    DistinguishedName  : CN=Homer J. Simpson,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Homer
    Name               : Homer J. Simpson
    ObjectClass        : user
    ObjectGUID         : 27588248-ee93-470e-aa72-083bdc201389
    SamAccountName     : Homer.Simpson
    SID                : S-1-5-21-1813243300-450990311-3672857015-1167
    Surname            : Simpson
    UserPrincipalName  : Homer.Simpson@CORP.WHYADMIN.COM
    PropertyNames      : {DistinguishedName, Enabled, GivenName, Name...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 10
    
    DistinguishedName  : CN=Carl Carlson,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Carl
    Name               : Carl Carlson
    ObjectClass        : user
    ObjectGUID         : 564e3f46-440f-4189-a7d7-2bc19639f38e
    SamAccountName     : carl.carlson
    SID                : S-1-5-21-1813243300-450990311-3672857015-1168
    Surname            : Carlson
    UserPrincipalName  : carl.carlson@CORP.WHYADMIN.COM
    PropertyNames      : {DistinguishedName, Enabled, GivenName, Name...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 10
    
    DistinguishedName  : CN=Lenny Leonard,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Lenny
    Name               : Lenny Leonard
    ObjectClass        : user
    ObjectGUID         : 85c773b0-d4f3-409f-8450-44aaa7b3beb3
    SamAccountName     : Lenny.Leonard
    SID                : S-1-5-21-1813243300-450990311-3672857015-1169
    Surname            : Leonard
    UserPrincipalName  : Lenny.Leonard@CORP.WHYADMIN.COM
    PropertyNames      : {DistinguishedName, Enabled, GivenName, Name...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 10
    
    DistinguishedName  : CN=Ralph Wiggum,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Ralph
    Name               : Ralph Wiggum
    ObjectClass        : user
    ObjectGUID         : cf4db3c2-abb6-480e-9c43-9dca4af1e219
    SamAccountName     : Ralph.Wiggum
    SID                : S-1-5-21-1813243300-450990311-3672857015-1170
    Surname            : Wiggum
    UserPrincipalName  : Ralph.Wiggum@CORP.WHYADMIN.COM
    PropertyNames      : {DistinguishedName, Enabled, GivenName, Name...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 10
    
    We've got our 5 users, but in our user objects, we are missing some pretty important things that we'd like to have available to use on the pipeline, or further in the script. To get these, we need to add a -properties parameter to get-aduser, and specify the properties we want (in this case, created and whencreated (NFI what the difference is))

    So no we have;

    Code:
    Get-ADUser -Filter * -SearchBase "OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM" -Properties whenCreated,Created | FL *
    
    [B]Created            : 20/11/2014 11:40:08 AM[/B]
    DistinguishedName  : CN=Bart J. Simpson,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Bart
    Name               : Bart J. Simpson
    ObjectClass        : user
    ObjectGUID         : 38f37c93-7d20-402c-b5f7-0f42758ce8d6
    SamAccountName     : bart.simpson
    SID                : S-1-5-21-1813243300-450990311-3672857015-1166
    Surname            : Simpson
    UserPrincipalName  : bart.simpson@CORP.WHYADMIN.COM
    [B]whenCreated        : 20/11/2014 11:40:08 AM[/B]
    PropertyNames      : {Created, DistinguishedName, Enabled, GivenName...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 12
    
    Created            : 20/11/2014 11:40:34 AM
    DistinguishedName  : CN=Homer J. Simpson,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Homer
    Name               : Homer J. Simpson
    ObjectClass        : user
    ObjectGUID         : 27588248-ee93-470e-aa72-083bdc201389
    SamAccountName     : Homer.Simpson
    SID                : S-1-5-21-1813243300-450990311-3672857015-1167
    Surname            : Simpson
    UserPrincipalName  : Homer.Simpson@CORP.WHYADMIN.COM
    whenCreated        : 20/11/2014 11:40:34 AM
    PropertyNames      : {Created, DistinguishedName, Enabled, GivenName...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 12
    
    Created            : 20/11/2014 11:41:22 AM
    DistinguishedName  : CN=Carl Carlson,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Carl
    Name               : Carl Carlson
    ObjectClass        : user
    ObjectGUID         : 564e3f46-440f-4189-a7d7-2bc19639f38e
    SamAccountName     : carl.carlson
    SID                : S-1-5-21-1813243300-450990311-3672857015-1168
    Surname            : Carlson
    UserPrincipalName  : carl.carlson@CORP.WHYADMIN.COM
    whenCreated        : 20/11/2014 11:41:22 AM
    PropertyNames      : {Created, DistinguishedName, Enabled, GivenName...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 12
    
    Created            : 20/11/2014 11:41:50 AM
    DistinguishedName  : CN=Lenny Leonard,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Lenny
    Name               : Lenny Leonard
    ObjectClass        : user
    ObjectGUID         : 85c773b0-d4f3-409f-8450-44aaa7b3beb3
    SamAccountName     : Lenny.Leonard
    SID                : S-1-5-21-1813243300-450990311-3672857015-1169
    Surname            : Leonard
    UserPrincipalName  : Lenny.Leonard@CORP.WHYADMIN.COM
    whenCreated        : 20/11/2014 11:41:50 AM
    PropertyNames      : {Created, DistinguishedName, Enabled, GivenName...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 12
    
    Created            : 20/11/2014 11:42:24 AM
    DistinguishedName  : CN=Ralph Wiggum,OU=Simpsons,OU=Staff,DC=CORP,DC=WHYADMIN,DC=COM
    Enabled            : True
    GivenName          : Ralph
    Name               : Ralph Wiggum
    ObjectClass        : user
    ObjectGUID         : cf4db3c2-abb6-480e-9c43-9dca4af1e219
    SamAccountName     : Ralph.Wiggum
    SID                : S-1-5-21-1813243300-450990311-3672857015-1170
    Surname            : Wiggum
    UserPrincipalName  : Ralph.Wiggum@CORP.WHYADMIN.COM
    whenCreated        : 20/11/2014 11:42:24 AM
    PropertyNames      : {Created, DistinguishedName, Enabled, GivenName...}
    AddedProperties    : {}
    RemovedProperties  : {}
    ModifiedProperties : {}
    PropertyCount      : 12
    
    Without specifying Created or WhenCreated in a properties parameter, I can't really see how they would become part of the returned Object.
     
  3. EvilGenius

    EvilGenius Member

    Joined:
    Apr 26, 2005
    Messages:
    10,739
    Location:
    elsewhere
    Sorry if this question doesn't meet the standards of the rest of the thread, but here goes..

    Trying to change a service startup type on a list of computer names. I have the list of names in a csv file.

    > $computers = import-csv C:\names.csv
    > foreach ($name in $computers) { set-service -name servicename -startuptype automatic

    This doesn't throw any errors, just leaves me at a >> prompt. Nothing seems to happen on any of the pcs in the list.


    I assume I'm doing it completely wrong.. yes?
     
  4. wullieb1

    wullieb1 Member

    Joined:
    Jul 9, 2013
    Messages:
    469
    Your missing } from the end of your second command

    > $computers = import-csv C:\names.csv
    > foreach ($name in $computers) { set-service -name servicename -startuptype automatic}
     
  5. Segression

    Segression Member

    Joined:
    Feb 29, 2004
    Messages:
    1,964
    Location:
    Sydney, NSW
    This is very cool, thanks heaps for all your effort in piecing this together for the community. Always wanted to learn some powershell stuff.
     
  6. EvilGenius

    EvilGenius Member

    Joined:
    Apr 26, 2005
    Messages:
    10,739
    Location:
    elsewhere
    Always the simple things.. cheers.

    That worked, at least on screen. I've run:

    foreach ($name in $computers) { set-service -name servicename -startuptype automatic }

    Then

    foreach ($name in $computers) { start-service -name servicename }

    Then

    foreach ($name in $computers) { get-service -name servicename }


    It returns a list that says 'running' for that service on each machine. When I inspect the machines themselves though, the service state is stopped and startup type is manual. :confused:
     
  7. Ravennoir

    Ravennoir Member

    Joined:
    May 1, 2007
    Messages:
    6,504
    Location:
    Melbourne
    How are you connecting to the remote computers ?


    I think this is more of what you need

    Code:
    $computers = import-csv C:\names.csv
    
    
    foreach ($name in $computers) 
        { 
        set-service -ComputerName $name -name servicename -startuptype automatic 
        start-service  -ComputerName $name -name servicename
        get-service -ComputerName $name -name servicename
        }
    
    
    Otherwise it is running the set\get-service on the local machine

    (I also simplfied your script, but thats preference)

    Also, a good tip is to write your scipts up in Powershell ISE, it tells you when you miss the simple things, like a } :)
     
  8. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,412
    Because you haven't specified the Computer you want to check the service on. If you don't specify the -computername parameter, by default, powershell will look at the local system it is running on.
     
  9. EvilGenius

    EvilGenius Member

    Joined:
    Apr 26, 2005
    Messages:
    10,739
    Location:
    elsewhere
    So its just running a check on my own machine once for each line in the CSV?
     
  10. Ravennoir

    Ravennoir Member

    Joined:
    May 1, 2007
    Messages:
    6,504
    Location:
    Melbourne
    Yeah, everytime it runs through the loop its only checking the services locally
     
  11. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,412
    I fully support liberal use of write-host when troubleshooting scripts, sure, you should use write-debug or write-output (because write-host breaks pipelining), but we aren't coding for sheep stations....

    If Crap.csv contains

    Code:
    ServerName
    SERVER1
    SERVER2
    
    then

    Code:
    $computers = Import-Csv C:\scripts\crap.csv
    $ServiceName = "wuauserv"
    
    foreach ($computer in $computers) {
    
    #Checking Service Status and Startup Type
    $Service = Get-Service -ComputerName $computer.ServerName -Name $ServiceName
    $ServiceStartupType = Get-WmiObject -computer $computer.ServerName -Class Win32_Service -Property StartMode -Filter "Name='$ServiceName'"
    write-host $Service.DisplayName is $Service.status on $computer.ServerName and is $ServiceStartupType.StartMode
    
    #If the Service isn't set to Auto, set it
    If ($ServiceStartupType.StartMode -ne "Auto") {
    Set-Service -ComputerName $computer.ServerName -Name $ServiceName -StartupType Automatic
    Write-Host Setting $ServiceName to Automatic on $Computer.ServerName
    }
    
    #If The service is Running, Start it
    If ($Service.Status -ne "Running") {
    Set-Service -ComputerName $computer.ServerName -Name $ServiceName -Status Running
    Write-Host Starting $ServiceName on $Computer.ServerName
    }
    
    #Run Check Again
    $Service = Get-Service -ComputerName $computer.ServerName -Name $ServiceName
    $ServiceStartupType = Get-WmiObject -computer $computer.ServerName -Class Win32_Service -Property StartMode -Filter "Name='$ServiceName'"
    write-host $Service.DisplayName is $Service.status on $computer.ServerName and is $ServiceStartupType.StartMode
    }
    
    produces

    Code:
    Windows Update is Stopped on SERVER1 and is Disabled
    Setting wuauserv to Automatic on SERVER1
    Starting wuauserv on SERVER1
    Windows Update is Running on SERVER1 and is Auto
    Windows Update is Running on SERVER2 and is Auto
    Windows Update is Running on SERVER2 and is Auto
    
    also, depending on your CSV, you may need to use get-content instead of import-csv.

    Import-CSV gets the content as a Name=Value pair, so you need to reference them using dot notation. Get-Content will get the info in a useable form, and is preffered if you just have a list of computers with no heading.

    Code:
    $CSV = Import-Csv C:\scripts\crap.csv
    
    Write-Host "Import-CSV Example"
    foreach ($Value in $CSV){
    Write-Host $Value
    }
    
    $Content = Get-Content C:\Scripts\crap.csv
    
    Write-Host "Get-Content Example"
    foreach ($item in $Content){
    Write-Host $item
    }
    
    
    
    results in


    Code:
    Import-CSV Example
    @{ServerName=SERVER1}
    @{ServerName=SERVER2}
    Get-Content Example
    ServerName
    SERVER1
    SERVER2
    
     
    Last edited: Mar 18, 2015
  12. Great_Guru

    Great_Guru Member

    Joined:
    Sep 5, 2001
    Messages:
    1,225
    Location:
    Australia
    Nice write up Pablo. Pet peeve of mine which may be fixed in PS5 (haven't checked it out yet).

    Get-Service cmdlet "why you no startuptype property"

    Or maybe you'll share some wisdom with me. I noticed you had to call in some WMI for your script above which reminded me.
     
  13. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,412
    No wisdom, Its better suited for a Rant.

    Theres a few gotcha's like that... In my mind... if <blah> is modifiable, then get-<anything> -blah, should be able to be modified by set-<anything> -blah [blah's value]

    And alternativily, if somethign can be set with set-<anything> -blah [anything] then it's value should be retrieved by get-<anything>

    Code:
    $psversiontable.psversion
    get-service wuauserv | FL *
    
    ---
    
    Major  Minor  Build  Revision
    -----  -----  -----  --------
    5      0      9841   0       
    
    
    
    
    Name                : wuauserv
    RequiredServices    : {rpcss}
    CanPauseAndContinue : False
    CanShutdown         : True
    CanStop             : True
    DisplayName         : Windows Update
    DependentServices   : {}
    MachineName         : .
    ServiceName         : wuauserv
    ServicesDependedOn  : {rpcss}
    ServiceHandle       : SafeServiceHandle
    Status              : Running
    ServiceType         : Win32ShareProcess
    Site                : 
    Container           : 
    
    Nothing seems different in 5 :(. Just going to be one of the annoyances I think.
     
  14. EvilGenius

    EvilGenius Member

    Joined:
    Apr 26, 2005
    Messages:
    10,739
    Location:
    elsewhere
    Thanks for that Pablo :thumbup:
     
  15. Great_Guru

    Great_Guru Member

    Joined:
    Sep 5, 2001
    Messages:
    1,225
    Location:
    Australia
    Saw this one online and I rate it :lol:

    Enable PowerShell - Hardcore mode

    Code:
    $ExecutionContext.InvokeCommand.CommandNotFoundAction = { Stop-Computer -Force }
    Note: Do not run this on production machines...

    If you type a command that isn't found - machine shuts down. Personally true hardcore mode would be clean-disk operation :p
     
  16. Tekin

    Tekin Member

    Joined:
    Nov 16, 2002
    Messages:
    4,039
    Location:
    Elsewhere.
    Heh - you could even have versions.

    Basic string error - turn off the monitor
    Invalid command - turn off the machine
    Trying to run a command on a new machine and forgetting to set permissions - deletes everything
     
  17. Tekin

    Tekin Member

    Joined:
    Nov 16, 2002
    Messages:
    4,039
    Location:
    Elsewhere.
    Powershell gurus!

    I come to you with an easy one that is absolutely doing my head in this morning.

    I have a collection of text files (application/DB setting extracts from Essbase if you're interested) and I'm trying to consolidate them into a single flat file that I can load.

    Unfortunately the output format sucks....like really sucks. This is an example:

    Code:
    MAXL> query database Cost.Costs get dbstats data_block;
    
     number_of_dimension declared_block_size actual_block_size   declared_maximum_bl actual_maximum_bloc number_of_non_missi number_of_non_missi number_of_total_blo index_type          average_block_densi average_sparse_dens block_compression_r average_clustering_ average_fragmentati free_space_is_recov estimated_bytes_of_
    +-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------
                       9              195624               29250          4604107662          2610376560               75655             1453214             1528869                   1     0.4103931623932     0.0585689062424   0.005456782528453     0.7632575306584  2.78530155703e-006               FALSE                   0
    
     OK/INFO - 1241044 - Records returned: [1].
    So, what I'm trying to do is come up with a csv file that has 2 lines, the header information on the first and the data on the second, without all the rest of the crap.

    I started trying to write it using regular expressions, but I'm a beginner with that as well. Then I realised, one of the things I CAN set in the script is column width.

    So, after all that rambling, my question to you is:

    Can I use powershell to parse a text file to csv using column width as a delimiter? Like, is there a way to use the stock delimiter field in convert to csv to do this?

    Edit: Ahhh - as is always the case, I found this immediately after posting. I need a Schema.ini file and all my problems are solved!
     
    Last edited: Mar 29, 2015
  18. freaky_beeky

    freaky_beeky Member

    Joined:
    Dec 2, 2004
    Messages:
    1,169
    Location:
    Brisbane


    So how'd you go? Did you get everything working as expected?

    EDIT:
    So after I saw this, I was just mucking around and thought of the this...
    It doesn't work because your output has two columns with the same name, but if you make all of them unique it does:
    Code:
    $content = #your excerpt in a text file, but simply $content = <command> should be okay
    $content -notmatch 'OK|\+.+' | %{$_.Trim() -replace '\s+',','} | ConvertFrom-Csv 
    
    #you could then just add this to the end of the last command: | Export-Csv -NoTypeInformation tekin.csv
    #or you could just | Out-File -force -append -filePath tekin.csv
    
     
    Last edited: Mar 30, 2015
  19. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,412
  20. freaky_beeky

    freaky_beeky Member

    Joined:
    Dec 2, 2004
    Messages:
    1,169
    Location:
    Brisbane
    That is sweet!

    I can't wait to use that in reality.

    I've put WMF5.0 on my test vm and using the new Invoke-ScriptAnalyzer cmdlet.



    That's arousing me to an almost uncomfortable level. Significantly speeding up script Peer Reviews and code readability.
     

Share This Page

Advertisement: