/build/static/layout/Breadcrumb_cap_w.png

How-To: Unique Method to Apply a Label to Multiple Machines

NOTICE: I found a MUCH simpler way to do this here (thanks JasonEgg): http://www.itninja.com/question/how-do-i-populate-the-device-list-in-a-script-by-importing-contents-of-a-csv-file

Basically, just create a regular Smart Label in the Web GUI, and use System Name matches regex then the machine names separated by a pipe.

Example:



If you have a list separated by a new line or a csv of names, then you can use Notepad++ with the below Find/Replace to convert the list to the Regex query needed:


Original blog below:

------------------------------------------------------------------------------------------------------------------------------

While it's not ideal, sometimes it is required to deploy software based solely off of a list of machines provided by a user. Where I work, I am often given a list of 20-30 machines that need software deployed to them for testing purposes before it goes out to a larger (and more easily targeted) group.

There are multiple ways to handle this. For example, you could put the machines in an OU or an AD member group and create an LDAP label, you could have the users create a text file and create a custom inventory rule, you could upload a csv with an additional field to the asset records of those machines (I have been told this is the supported workaround.), you could type each machine name in manually to the Managed Installation or Script, you could apply a manual label to each machine, etc.

While all of these get the job done, I decided I would post a quick how-to on how I choose to handle this.

In a nutshell, I wrote a Powershell script that takes a list of machine names from a text file (separated by a new line) and generates a SQL query that can then be turned into a Smart Label.

Here is the code (Requires Powershell 5):

#REM This will generate a SQL query for multiple machine names in a text file

Function Get-InputFile($initialDirectory = "C:\") {

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
    
    $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.Title = "Select the text file containing host names"
    $OpenFileDialog.Multiselect = $false
    $OpenFileDialog.initialDirectory = $initialDirectory
    $OpenFileDialog.filter = "TXT (*.txt)| *.txt"
    $OpenDialogClick = $OpenFileDialog.ShowDialog()

    If ($OpenDialogClick -eq "OK") {

        Return $OpenFileDialog.FileName

    }

    Else {

        Write-Warning "Operation cancelled by user."

        Exit

    }

}

Function Get-SavePath($initialDirectory = "C:\") {

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null

    $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
    $SaveFileDialog.Title = "Select where to save the SQL Query"
    $SaveFileDialog.initialDirectory = $initialDirectory
    $SaveFileDialog.filter = "TXT (*.txt)| *.txt"
    $SaveDialogClick = $SaveFileDialog.ShowDialog()
    
    If ($SaveDialogClick -eq "OK") {

        Return $SaveFileDialog.FileName

    }

    Else {

        Write-Warning "Operation cancelled by user."

        Exit

    }

}

#Prompt for input text file
$InputFile= Get-InputFile
#Get machine names from specified file
$Machines= Get-Content $InputFile | Sort-Object

if ($Machines -eq $null) {

    Write-Error "The selected text file is blank."

    Exit

}

[int]$MachineCount = $Machines.Count

if ($MachineCount -eq 1) {

    $Prompt = Read-Host -Prompt "The selected text file only has one line. Continue? Yes/No"

    while("yes","no" -notcontains $Prompt) {

    Write-Warning "Please type either ""Yes"" or ""No"""

	$Prompt = Read-Host -Prompt "The selected text file only has one line. Continue? Yes/No"
    
    }

    if ($Prompt -eq "Yes" -or $Prompt -eq "yes") {

        $SavePath = Get-SavePath

        New-Item -ItemType File -Path $SavePath -Force | Out-Null

        Out-File -NoClobber -NoNewline -Append -InputObject "SELECT MACHINE.NAME AS SYSTEM_NAME, SYSTEM_DESCRIPTION, MACHINE.IP, MACHINE.MAC, MACHINE.ID as TOPIC_ID FROM MACHINE WHERE (MACHINE.NAME =""$Machine"")" -FilePath $SavePath

        Exit

    }

    elseif ($Prompt -eq "No" -or $Prompt -eq "no") {

        Write-Warning "Operation cancelled by user."

        Exit

    }

}
#Prompt for path to save output
$SavePath = Get-SavePath

New-Item -ItemType File -Path $SavePath -Force | Out-Null

[int]$Count = 0

Out-File -NoClobber -NoNewline -Append -InputObject 'SELECT MACHINE.NAME AS SYSTEM_NAME, SYSTEM_DESCRIPTION, MACHINE.IP, MACHINE.MAC, MACHINE.ID as TOPIC_ID FROM MACHINE WHERE (' -FilePath $SavePath

foreach ($Machine in $Machines) {

    $Count = ($Count + 1)

    if ($count -eq $MachineCount) {

        Out-File -NoClobber -NoNewline -Append -InputObject "(MACHINE.NAME =""$Machine""))" -FilePath $SavePath

    }

    else {
    
        Out-File -NoClobber -NoNewline -Append -InputObject "(MACHINE.NAME =""$Machine"") OR " -FilePath $SavePath

    }

}

I usually just right click the PS1 and Run with Powershell, but feel free to do what you want with it.

It will first prompt for the input file. This file should be formatted with each machine name on a new line.

Example:

MACHINE1
MACHINE2
MACHINE3

The script will then prompt for the directory and file name to save the output.

After you have the SQL query, you will need to create a Device Smart Label in the K1000.

0Qb5Aj.png  or rTLbqd.png

At this point, we'll just need to create a regular Smart Label. I usually just leave the default search criteria, name the label, and hit Save.

MOhGif.png

Then go to Label Manangement - Smart Labels, and click the link for the new label you created (not the pencil icon).

hGem7o.png

Now click "Edit SQL", and then replace the entire text block with the SQL query from the Powershell script.

hem0y5.png

JqkW46.png

Then hit save, and wait for devices to check in to get the label!

As of right now, I'm not aware of another way to create a SQL smart label. If you have found a better way, then please let me know!

Of course there are downsides to this. The machine won't get the label until next check-in, the label is harder to work with in Inventory, and it's a little less user-friendly to add/remove devices to the label. However, it has worked well for me, and I hope it could prove useful to others.

Comments

  • Great stuff, thanks! For tidier SQL, I would use:
    "MACHINE.NAME in ([comma separated names])"
    If you want this list to persist even if computers are renamed, consider using an intermediate query to find the Machine ID based on name, then use "MACHINE.ID in ([comma separated IDs])" instead of MACHINE.NAME - JasonEgg 8 years ago
    • Great notes! I'm a SQL beginner when it comes down to it, so I appreciate the feedback. I'll edit this post once I have time to make/test those changes. - anonymous_129525 8 years ago
  • Hey mate,
    Thanks for the post. but i am getting an error every time i execute your code.
    Are you sure the switch "-NoNewline" is a proper switch for Out-File?

    As I am getting the below run error:
    Out-File : A parameter cannot be found that matches parameter name 'NoNewline'.


    As far as I am aware PS has nonewline only for write-host, unless i am missing something here? - ICTLicences 7 years ago
    • Got it working on PowerShell v4 by using
      [System.IO.File]::WriteAllText($SavePath,"SELECT MACHINE.NAME AS SYSTEM_NAME, SYSTEM_DESCRIPTION, MACHINE.IP, MACHINE.MAC, MACHINE.ID as TOPIC_ID FROM MACHINE WHERE (MACHINE.NAME =""$Machine"")",[System.Text.Encoding]::ASCII)

      and
      [System.IO.File]::AppendAllText($SavePath,"SELECT MACHINE.NAME AS SYSTEM_NAME, SYSTEM_DESCRIPTION, MACHINE.IP, MACHINE.MAC, MACHINE.ID as TOPIC_ID FROM MACHINE WHERE (",[System.Text.Encoding]::ASCII) - ICTLicences 7 years ago
      • Sorry just saw this. The NoNewLine parameter was added to Out-File in Powershell 5 https://blogs.technet.microsoft.com/heyscriptingguy/2015/08/07/the-powershell-5-nonewline-parameter/

        However, after posting this blog, I found a much simpler way to do this here: http://www.itninja.com/question/how-do-i-populate-the-device-list-in-a-script-by-importing-contents-of-a-csv-file.

        Basically, just do a regular smart label with System Name matches regex with computer names separated by a pipe (Ex. MACHINE1|MACHINE2|MACHINE3) - anonymous_129525 6 years ago
This post is locked
 
This website uses cookies. By continuing to use this site and/or clicking the "Accept" button you are providing consent Quest Software and its affiliates do NOT sell the Personal Data you provide to us either when you register on our websites or when you do business with us. For more information about our Privacy Policy and our data protection efforts, please visit GDPR-HQ