Pablo's Powershell Pow-Wow

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

  1. DonutKing

    DonutKing Member

    Joined:
    Mar 21, 2004
    Messages:
    1,483
    Location:
    Tweed/Gold Coast
    It looks like you imported the CSV into an object called $groups (plural) but your next line is operating on $group (singular).

    Code:
    foreach ($group in $group)...
    Should have been

    Code:
    foreach ($group in $groups)...
    I suspect you previously imported the CSV file with all the groups into $group so it was not overwritten when you imported the CSV into $groups.
     
  2. looktall

    looktall Working Class Doughnut

    Joined:
    Sep 17, 2001
    Messages:
    26,668
    that's a typo in my post.

    the command was definitely $group in $groups.
     
  3. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,638
    -whatif

    Learn it,
    Live it,
    Love it.

     
    Bengareth and freaky_beeky like this.
  4. looktall

    looktall Working Class Doughnut

    Joined:
    Sep 17, 2001
    Messages:
    26,668
    I came this close to using -whatif but I figured "nah it's just one group that won't matter if I fuck it up".

    I got lucky in this case.
     
  5. Ravennoir

    Ravennoir Member

    Joined:
    May 1, 2007
    Messages:
    6,508
    Location:
    Melbourne
    Until you forget you put it on a line in the script and wonder why nothing happening :)

    I figured out why my function wasnt working

    I had the output in the wrong foreach loop, moved it up one and it worked well

    Now I have to work out all the other parts
     
  6. freaky_beeky

    freaky_beeky Member

    Joined:
    Dec 2, 2004
    Messages:
    1,169
    Location:
    Brisbane
    That's when you use -Confirm (like in looktall's example). You press go, and it says "doing blah on thing" and you say yes, it then asks you about a doing "blah on newthing", and you realise your mistake, and hopefully before anything is broken.
     
  7. bcann

    bcann Member

    Joined:
    Feb 26, 2006
    Messages:
    6,118
    Location:
    NSW
    Gday All,

    I have some powershell code that i need to run on a RDS Server across all user sessions (Basically a HR message balloon popup with some whiney HR message for all users to barf over) How can i get this to run as a scheduled task simultaneously across all RDS Sessions?
     
  8. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,638
    I can't think of any nice way of doing this.

    I'd probably end up with an agent type process that runs on startup, and polls for message.txt every 5 minutes, and then shits it all over the screen when it finds a change.
     
  9. DonutKing

    DonutKing Member

    Joined:
    Mar 21, 2004
    Messages:
    1,483
    Location:
    Tweed/Gold Coast
    Assuming you want to run it at a specific time for all users: Can you load the script as a scheduled task, under User preferences in group policy?
    Set it to run as %LogonDomain%\%LogonUser% and run only when user is logged on. Make sure to tick 'run in user context' under the Common tab.


    If you need to display messages ad-hoc, can you use Send-RDUserMessage from the RemoteDesktop module? You can use qwinsta command to get the list of user sessions from the server, parse its output and loop through it.
     
  10. bcann

    bcann Member

    Joined:
    Feb 26, 2006
    Messages:
    6,118
    Location:
    NSW
    after a fair bit of googling as HR wants it to display at a specific time (IE 11am), i can't just call it via a startup script. But i did find out that if you want it to run "Consoleless" you need to call it via ... VB Script....

    So setup a scheduled task to call the VB Script to call the Powershell to remain consoleless....

    command = "powershell.exe -nologo -command C:\HR-Message\HR-Message.ps1"
    set shell = CreateObject("WScript.Shell")
    shell.Run command,0

    And just because you guys may need it one day here is the powershell script that i grabbed from someone else on the net and customised.... please try not to cry as i am so not a scripter, but basically it reads from a .csv and randomly picks a quote and displays it via a popup bubble, yes i know its as ugly as sin, but again i suck @ powershell

    Function Invoke-BalloonTip {
    <#
    .Synopsis
    Display a balloon tip message in the system tray.
    .Description
    This function displays a user-defined message as a balloon popup in the system tray. This function
    requires Windows Vista or later.
    .Parameter Message
    The message text you want to display. Recommended to keep it short and simple.
    .Parameter Title
    The title for the message balloon.
    .Parameter MessageType
    The type of message. This value determines what type of icon to display. Valid values are
    .Parameter SysTrayIcon
    The path to a file that you will use as the system tray icon. Default is the PowerShell ISE icon.
    .Parameter Duration
    The number of seconds to display the balloon popup. The default is 1000.
    .Inputs
    None
    .Outputs
    None
    .Notes
    NAME: Invoke-BalloonTip
    VERSION: 1.0
    AUTHOR: Boe Prox
    #>


    [CmdletBinding()]
    Param (
    [Parameter(HelpMessage="The message title")]
    [string]$Title="Attention $env:username",

    [Parameter(HelpMessage="The message type: Info,Error,Warning,None")]
    [System.Windows.Forms.ToolTipIcon]$MessageType="Info",

    [Parameter(HelpMessage="The path to a file to use its icon in the system tray")]
    [string]$SysTrayIconPath='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe',

    [Parameter(HelpMessage="The number of milliseconds to display the message.")]
    [int]$Duration=5000
    )

    Add-Type -AssemblyName System.Windows.Forms

    If (-NOT $global:balloon) {
    $global:balloon = New-Object System.Windows.Forms.NotifyIcon

    #Mouse double click on icon to dispose
    [void](Register-ObjectEvent -InputObject $balloon -EventName MouseDoubleClick -SourceIdentifier IconClicked -Action {
    #Perform cleanup actions on balloon tip
    Write-Verbose 'Disposing of balloon'
    $global:balloon.dispose()
    Unregister-Event -SourceIdentifier IconClicked
    Remove-Job -Name IconClicked
    Remove-Variable -Name balloon -Scope Global
    })
    }

    $importpath = "C:\hr-message\HR-Message.csv"
    $count = 1
    $list = Import-csv -Path $importpath | select -Expandproperty Message
    $Message = get-random -Inputobject $list -Count $count

    #Need an icon for the tray
    $path = Get-Process -id $pid | Select-Object -ExpandProperty Path

    #Extract the icon from the file
    $balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($SysTrayIconPath)

    #Can only use certain TipIcons: [System.Windows.Forms.ToolTipIcon] | Get-Member -Static -Type Property
    $balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]$MessageType
    $balloon.BalloonTipText = $Message
    $balloon.BalloonTipTitle = $Title
    $balloon.Visible = $true

    #Display the tip and specify in milliseconds on how long balloon will stay visible
    $balloon.ShowBalloonTip($Duration)

    Write-Verbose "Ending function"

    }

    Add-Type -AssemblyName System.Windows.Forms
    Invoke-BalloonTip -Title 'Attention!' -MessageType Info
     
  11. miicah

    miicah Member

    Joined:
    Jun 3, 2010
    Messages:
    7,501
    Location:
    Mount Cotton, QLD
    Before I start, the script I wrote works. I just want to know if it is possible to condense the section inside the IF statement, and if it's actually worth doing?

    Code:
    $wsDetails = Get-ADComputer -Filter * -SearchBase $labDetails -Properties Description
    
    #Start new CimSession using the Lab list we grabbed before
    $CIMList = New-CimSession -ComputerName $wsDetails.Name -Credential $creds -Authentication Negotiate -Name remoteWS
    
    foreach ($CIMObject in $CIMList)
    {
        for ($i = 0; $i -le $wsDetails.Count; $i++)
        {
            if ($CIMObject.ComputerName -eq $wsDetails[$i].Name)
            {
                $currentWS = Get-CimInstance -ComputerName $CIMObject.ComputerName -ClassName Win32_OperatingSystem
                $currentWS | Set-CimInstance -Property @{Description = $wsDetails.Description[$i]}
                $newDescription = $currentWS | Select-Object -ExpandProperty Description
    
                "Description updated for $($CIMObject.ComputerName). Now set to: $($newDescription)"           
                Break;
            }
        }
    }
     
  12. freaky_beeky

    freaky_beeky Member

    Joined:
    Dec 2, 2004
    Messages:
    1,169
    Location:
    Brisbane
    Just to make sure i'm reading this right, you're just updating the computers' description to the value stored in the computers AD accounts description field?

    Out of curiosity, what monitoring system do you use in your environment? (e.g. SCOM)
     
  13. miicah

    miicah Member

    Joined:
    Jun 3, 2010
    Messages:
    7,501
    Location:
    Mount Cotton, QLD
    Yes that's correct. And I think we (not you specifically) went through this in another thread, I work in education and the way that SCOM is set up here, it's almost impossible for them to give us permissions to do this kind of thing.

    So I have to find creative ways to do simple MS tasks.
     
  14. freaky_beeky

    freaky_beeky Member

    Joined:
    Dec 2, 2004
    Messages:
    1,169
    Location:
    Brisbane
    Yeah, I was going to suggest you write a quick SCOM management pack to do the exact thing, so that instead of having to run this against all your machines, you instead make all your machines do it themselves or alert.

    As for your code, the ';' after Break is superfluous and inconsistent with the remainder of your code.

    I expect you could possibly speed up the whole thing, with some filtering for online machines with remote CIM configured, via some testing using Test-NetConnection or Test-Connection, depending on how clean your AD is.

    Otherwise, I don't think you'd get a much faster.

    You may also want to consider putting a Try and Catch around that Set-CIMInstance, (or everything), in case you get some permission denied (or other weird errors).

    Also, just re-reading through, does $newdescription actually get updated to the new description?

    Shouldn't it be something like
    Code:
    $currentWS = $currentWS | Set-CimInstance -Property @{Description = $wsDetails.Description[$i]} -PassThru
    $newDescription = $currentWS | Select-Object -ExpandProperty Description
    
    Otherwise $newDescription is just getting the value of the "currentWS" description, which *may* not be the same as the one you've just updated?
     
    miicah likes this.
  15. miicah

    miicah Member

    Joined:
    Jun 3, 2010
    Messages:
    7,501
    Location:
    Mount Cotton, QLD
    $currentWS gets piped to Set-CimInstance which is when the description gets updated. So I hope that continuing to use that object will be up to date. I believe it works as I have tested it with a few different AD groups.
     
  16. tensop

    tensop Member

    Joined:
    Mar 26, 2002
    Messages:
    1,542
    OK, got one my brain simply cant figure out how to get started on

    I have a group named GS-SRT, with the HomePhone attribute populated with TWI.
    I have a user with a samaccountnamed John Twibbles, with the EmployeeID attribute populated with TWI.

    the unique match between the group and the user is the HomePhone/EmployeeID

    How the hell do i script it to add a user to the group where the two fields match?

    My brain is too cooked, can't even figure out how to explain this one :p
     
    Last edited: Mar 9, 2019
  17. OP
    OP
    PabloEscobar

    PabloEscobar Member

    Joined:
    Jan 28, 2008
    Messages:
    14,638
    Whats TWI?

    If $user.employeeid -eq $group.HomePhone then
    Add-Adgroupmember -identity $Group -members $User
     
  18. RaZ

    RaZ Member

    Joined:
    Aug 6, 2001
    Messages:
    391
    Location:
    Brissy
    Seeking help because my brain has gone full tard today; I have done this before by taking examples but today everything seems to be a fail for me :(

    Whats needed?
    I have a CSV file with two columns of exported data. Column 1 has Citrix published application names, column 2 has a number for application limits
    I need a script to import the csv file and take each value from a row and pass them to a powershell command;
    eg;

    from CSV file;
    Appname | Userlimit
    myapp3 | 5
    myapp4 | 6
    myapp5 | 10
    myapp6 | 2

    command required ;
    Set-BrokerApplication -Name $appname -MaxPerUserInstances $userlimit

    And do this for each app listed in the csv file aka a loop I guess? I no poweshell guru :p

    Why? To apply application instance limits to about 1800 published apps.

    And as sharing is caring ; below I have pasted a script I did for changing delivery groups for published apps ;) I couldn't find one anywhere

    ##########################################
    #Script created by Chris
    #Usage: changing delivery groups assigned to applications, by delivery group for Xenapp 7.x
    #-----------------------------------------------------------------------------
    #Script below gets list of apps from the Delivery group UUID - to find the UUID of the delivery group you want to get an application list from
    #run the following command;
    Get-BrokerDesktopGroup | Select UUID,Name
    #Then look for the UUID of the delivery group you want to get applications from and replace in the below line;eg; -AssociatedDesktopGroupUUID 8a582253-e670-4c77-801a-b6bbdcc12d52
    #########################################
    $DGLIST = Get-BrokerApplication -AssociatedDesktopGroupUUID 8a582253-e670-4c77-801a-b6bbdcc12d52 | select ApplicationName
    #Gets list of application from Delivery group and holds that list in the $DGlist vavriable

    foreach ($app in $DGLIST.ApplicationName){
    Write-host "Migrating $app DG"#Writes to screen the application its changing delivery groups on
    Get-BrokerApplication -ApplicationName $app | Add-BrokerApplication -DesktopGroup "Production Group" -Priority 0
    Get-BrokerApplication -ApplicationName $app | Remove-BrokerApplication -DesktopGroup "PRD 2008R2"

    }
    #The above section loops through all apps listed in the $DGLIST and changes the delivery groups set above with the -DesktopGroup filter
     
  19. Myne_h

    Myne_h Member

    Joined:
    Feb 27, 2002
    Messages:
    11,442
    If you're only going to do it once

    Paste into notepad, replace pipes with <tab>
    Paste into excel, space out and paste command appropriately into columns and drag down.
    Copy to notepad if req'd, replace tabs with space
    Paste into powershell.

    I know it's not an answer. But it's a solution if it's an immediate problem ;)
     
    RaZ likes this.
  20. RaZ

    RaZ Member

    Joined:
    Aug 6, 2001
    Messages:
    391
    Location:
    Brissy
    Firstly thank you kindly for replying;

    That is an idea, but I am also forcing myself to learn it as well. Its not urgent so yeah - but I see what your saying and yep, I have done that before and used search and replace to edit it all too :) Works well in a pinch.
     

Share This Page

Advertisement: