cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
bkelly
By
Flexera Alumni

Now you can keep all your systems up to date, hands free, using AdminStudio's Package Feed Module and its powerful automation support.

In this article by AdminStudio's Product Management team (Bob Kelly and Kiran Mantagi) we highlight how you can leverage the powerful automation capabilities of AdminStudio to automatically convert a list of applications into deployment ready packages. Such automation can be run regularly to identify, package and publish new versions of each application as new versions are introduced by the vendor! 

One of the major challenges for IT Professionals is to keep systems up to date with the latest version of the software they manage (a critical task when you consider the majority of such updates include security fixes). From a software security standpoint, an ideal environment is the one where all systems are current with the latest version immediately as new versions are released. IT Pros spend countless hours trying to keep up: learning of new updates, researching silent command line switches and customization options, etc.

A typical scenario of how you would go about updating the systems in your environment would be:

  1. Using a software inventory report, look to see which have new versions released
  2. For each, download the installer to a managed folder structure
  3. Research how to perform a silent installation of the product
    • Examine the installer to determine what kind of options it might support
    • Look to online documentation and community resources to expose silent installation options
    • Test the discovered silent installation options to confirm it performs as expected
    • If it cannot be silently installed or customization options are insufficient, the installer is typically repackaged with a solution like AdminStudio’s Repackger
  4. It is common for many organizations to next wrap the installer and silent command line into a standardized script to ensure consistency, control behavior, and provide a mechanism for further customization of the installation.
  5. Add the installation package to an endpoint management system like Configuration Manager (SCCM)
  6. Deploy the application to test systems to confirm success prior to a full production deployment
    • Mitigate failures related to Windows Compatablity, failure to conform to best practices, conflicts with previously deployed applications, etc.

With AdminStudio’s revolutionary Package Feed Module, released in AdminStudio 2019 R2, getting new software updates and silent command line switches is quick and easy. Package Feed Module provides access to nearly 3000 software entries with a focus on those frequently used in an Enterprise. Package Feed Module provides easy download of the latest version of the setup files along with the tested silent command line switches just by a few clicks of a button. To learn more about Package Feed Module, click here.

Now imagine, you could take that inventory report from step #1 above and automate the rests of those tasks. A new version is released for a product—a new package appears in your deployment system, tested and ready for initial deployment. Thanks to the script outlined below, this dream is now a reality…

This article explains how you will be able to achieve this automation using the provided PowerShell Script which leverages AdminStudio’s powerful automation capabilities exposed via PowerShell Cmdlets. For the complete list of PowerShell Cmdlets exposed by AdminStudio, please refer to our documentation here.

Prerequisites:

  • AdminStudio Enterprise 2019 R2 (or later) installed and activated
  • An established AdminStudio Catalog (video)
  • Subscription to Package Feed Module (datasheet)

Let’s get started..

Launch the 32-bit Windows PowerShell ISE as Administrator on the machine where AdminStudio is installed and open the below PowerShell Script in the editor.

You will see a section titled, ‘User Defined Settings’ at the beginning of the script. These are one time settings that must be edited to match your environment. It is pretty straight forward. Simply replace the value of variables like SQL Server, SQL Server User Name, etc. with the actual values applicable to your environment. This sample script shows various settings needed for distributing an application from AdminStudio to ConfigMgr. If you have any other end point management system in your environment other than ConfigMgr, please refer AdminStudio help library to learn what alternative settings are required to handle the connection between AdminStudio and your end point management system for the publishing of applications. If you do not wish to publish the resulting packages to your endpoint management system, you may choose to either comment these variables out, or simply delete them. Typically, there should be no need not edit any of the ‘Non-User Settings’.

After all the user defined variables are set to the correct values, the script is ready to run. Within few seconds you will be presented with the dialog below (figure 1). Enter the path and file name of a CSV file containing your list of software and click OK. Don’t worry about what other columns may exist in the CSV file, just be sure to have a title row and one column that contains Product Name and another that contains Vendor Name.

Figure 1. Dialog to provide the path of the software inventory file.Figure 1. Dialog to provide the path of the software inventory file.

Below (figure 2) is an example of what a simple CSV list might look like:

Figure 2. A simple example of an inventory list suitable for this scriptFigure 2. A simple example of an inventory list suitable for this script

Next, you will see the below dialog (figure 3). The drop down lists all the column names detected in the CSV file. Choose the name of the column which lists the Product Name of the software. Depending on the source of your list, the name of this column will vary, some may identify Product Name as "Name", "Software Name", "Display Name" etc.

Figure 3: Select the column which represents Product Name.Figure 3: Select the column which represents Product Name.

You will then be prompted to supply the column name for the Vendor  via the below dialog (figure 4). Depending on the source of your list, Vendor Name might also be identified as "Manufacturer", "Publisher", etc. Simply select the column name from the drop down which represents Vendor Name and Click OK to continue.

Figure 4: Select the column which represents Vendor Name.Figure 4: Select the column which represents Vendor Name.

Finally, upon clicking OK in the previous dialog, you will be presented with the below choice (figure 5). Here you can specify what operation you want to perform-- first choose to Search Apps or to Process Apps.

Figure 5: Select an option: to either search for apps or to process the appsFigure 5: Select an option: to either search for apps or to process the apps

Search Apps: Selecting ‘Search Apps’ will take your inventory list from the CSV file and search Package Feed Module for the matching installers. The ‘Search Apps’ action fetches the search results, updates the CSV with the results and stops. Output of the search results will be added as new columns in the same CSV file. An example list with the additional columns added can be seen in the below screenshot (figure 6). If multiple results are found while searching for a product, then all the matched results will be updated in the new MatchedProductName column. If there is just one match found, then the same name will be updated in the SelectedProductName column and if multiple matches are found, then the first name from the list will be specified in the SelectedProductName column. 

Figure 6: Search results updated into the input csv file for the ‘Search Apps’ actionFigure 6: Search results updated into the input csv file for the ‘Search Apps’ action

Process Apps: The ‘Process Apps’ option executes selected tasks against the list. The below dialog (figure 7) lets you choose the tasks that you would like to perform for each application installer selected. This is a sample script, and so shows a very limited list of actions. You can extend this list of actions to cover a long list of other valuable operations AdminStudio can perform, such as conversion to App-V and MSIX, publishing to other end point management systems, resolving Windows compatibility issues, etc. Please refer to our online documentation for a complete list of AdminStudio PowerShell Cmdlets.

Figure 7: Select all the tasks to be performed on the packageFigure 7: Select all the tasks to be performed on the package

Wrapping is a simple, yet powerful way, to customize your installation and to inject any pre-installation or post-installation configurations or actions. As an increasing number of software vendors provide good support for silent command line switches, more and more IT Pros are switching to wrapping from traditional repackaging.

AdminStudio provides two options to easily wrap your software package in a script:

  1. PowerShell wrapping, which wraps your package into a PowerShell Script using a predefined template, where you may add any customizations or configurations desired.
  2. EXE Wrapping, which leverages older WiseScript technology to provide similar benefits using a pre-defined template, where you may add any customizations or configurations desired. This option may be preferable for those not familiar with PowerShell as WiseScript provides a point and click interface and does not require any knowledge of scripting.

You will be presented with the dialog below (figure 😎 only if you chose to Wrap from the list of desired actions. Here you may choose between PowerShell Wrapping and EXE Wrapping.

Figure 8: Select the technology to be used for wrappingFigure 8: Select the technology to be used for wrapping

Click OK and enjoy the show!

 

Behind the Scenes

The script reads your inventory CSV file and looks up each one in Package Feed Module. In order to limit actions only to new versions of each application, the software version of the application from the Package Feed Module is compared against the software version in AdminStudio’s Application Catalog. If the version in the Package Feed Module is found to be greater than the version in the Application Catalog, the new version of the package will be downloaded and imported to your Application Catalog. Once in the catalog, the package will be put through each of the selected tasks.

Detection Methods that are added to a package are evaluated on the end point when the package is deployed for installation. The Detection Methods help identify if the installation is applicable to the device-- if an older version is installed, then the installation is performed. Along with Detection Methods there are other ConfigMgr application model data properties that you may set for an application in AdminStudio before publishing. AdminStudio exposes PowerShell Cmdlets to set most of these app model properties, however there are certain complex properties like Detection Methods, Requirements, and Supersedence which cannot be set using the existing Cmdlets. AdminStudio has some Cmdlets which are not documented and but are operational in the product, one such Cmdlet is used in this script to add the Detection Methods. 

Running This Script

To make sure you get the exact matches for the inventory list in the CSV file, it is recommended to run this script in 2 passes. In the first pass, provide your inventory CSV file and select the Search Apps action to update your list with the matches found in the Package Feed Module. Then, open the updated CSV file and have a look at the new SelectedProductName column, to confirm column matches your intent. When there are multiple results, pick the correct product name from the list and update the original ProductName column to ensure a proper, singular match. If the product name listed in SelectedProductName matches your intent, you may leave it as is. Once you've massaged the CSV file save the changes and run the script again.

This second time, provide the updated CSV file and select Process Apps. This will take you through the choices explained earlier in this article. Depending on the how big the inventory list is and the tasks selected, it may take some time to download the installers and perform the selected tasks but the script will update you on its progress as it runs.

In case you missed it, a video is also provided to walk you through the above.

Below is a copy of script in question also attached to this article as a text file.

 

###############################################################
# User Defined Settings
###############################################################

$global:CatalogName = 'ApplicationCatalog' #Name of AdminStudio catalog
$SQLUserName        = 'DBacct'             #AdminStudio catalog user who should have access to the catalog (sql server)
$SQLPassword        = 'DBpwd'              #Password for this user
$SQLServer          = '10.10.10.10'        #Sql server name or ip

$SCCMServer         = '10.10.10.10'        #ConfigMgr (SCCM) name or ip
$SCCMServerSiteCode = 'FLX'                #ConfigMgr site code
$SCCMRepositoryPath = '10.10.10.10\SCCMPublish' #ConfigMgr content location(a shared folder)
$SCCMTargetGroup    = 'Applications'       #ConfigMgr destination foldeer where the applications will be created  
$SCCMUser           = 'CMacct'             #ConfigMgr username
$SCCMPass           = 'CMpwd'              #ConfigMgr password
$DistributionName   = 'ConfigMgr'          #Connection name that will be added in AdminStudio
$ShareUser          = 'CMacct'             #Username having access to content location
$SharePwd           = 'CMpwd'              #Password for this username

#####################################################################
# Non-User Settings
#####################################################################

$ConnectionString   = 'PROVIDER=SQLOLEDB.1;Data Source=' + $SQLServer+';Initial Catalog=' + $global:CatalogName + ';user ID='+$SQLUserName+';password='+$SQLPassword+''
$shive              = "HKLM:\SOFTWARE\Wow6432Node\InstallShield\AdminStudio\18.0\"
$slocation          = "Product Location"
$sAsLoc             = (Get-ItemProperty $shive $slocation).$slocation
$sCurrentLoc        = [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
$sAsLoc             = $sAsLoc + "Common\"
$SCCMPluginID       = 13
$Global:CSVFilePath = $null
$Global:ProductColumnName  = $null
$Global:VendorColumnName   = $null
$Global:VersionColumnName  = $null
$Global:CSVContent         = $null

#####################################################################
# Functions
#####################################################################

function LoadDLL ($s)
{ 
    $FileName = $sAsLoc + $s
    import-module -name $FileName
}

function PrepAS ()
{    
    LoadDLL 'AdminStudio.Platform.PowerShellExtensions.dll'
    LoadDLL 'AdminStudio.Utilities.dll'
    LoadDLL 'AdminStudio.SCCM.Model.dll'
    LoadDLL 'AdminStudio.SCCM.Integrator.dll'
    Set-ASConfigPlatform -ConnectionString   $ConnectionString
    $sync = Invoke-ASPackageFeedSync

}

function ProcessInputCSV()
{

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$csvfilepath = [Microsoft.VisualBasic.Interaction]::InputBox("Enter CSV File Path", "CSV File Path")


try{


    if (Test-Path $csvfilepath -ErrorAction Stop)

        {
            $Global:CSVFilePath = $csvfilepath
        }
    else
        {
            Write-Host 'File not found. Please run the script again with the correct file path!' -ForegroundColor Red
            Exit
        }
    }
catch
    {
Write-Host 'File not found. Please run the script again with the correct file path!' -ForegroundColor Red
exit
    }
$CSVContent = Import-Csv $csvfilepath

$Columns = $CSVContent[0].psobject.Properties.Name
$ProductColumnName = SelectFromDropDown 'Product Name' $Columns
If ($ProductColumnName -eq $null)
{

Write-Host 'Make a selection for Product Name column. Exiting script!' -ForegroundColor Red
Exit

}

$VendorColumnName = SelectFromDropDown 'Vendor Name' $Columns


If ($VendorColumnName -eq $null)
{

Write-Host 'Make a selection for Vendor Name column. Exiting scrtip!' -ForegroundColor Red
Exit

}

$CSVContent | 
Select-Object *,"SearchResult","MatchedProductName","MatchedVersion","SelectedProductName","SelectedVersion","SelectedPkgFid" -ErrorAction Ignore|
Export-Csv -Path $Global:CSVFilePath -Force -NoTypeInformation 
$Global:CSVContent = Import-Csv $csvfilepath
$Global:ProductColumnName = $ProductColumnName
$Global:VendorColumnName = $VendorColumnName

}

function SearchResults($ProductsList)
{


$ProductsList| ForEach-Object {

$product = $_.$Global:ProductColumnName
$vendor = $_.$Global:VendorColumnName



$Search = Invoke-ASPackageFeedSearch -ProductName $product -Vendor $vendor

 $MatchedProductName = $null
 $MatchedVersion = $null
 $fids = $null


if ($Search -like '*No matching records found*')
{

    $_.SearchResult = 'Sorry, no match found'
    $_.MatchedProductName = 'Not found'
    $_.MatchedVersion = 'Not found'
    $_.SelectedProductName = 'Not found'
    $_.SelectedVersion = 'Not found'
    $_.SelectedPkgFid = 'Not found'

    $ProductsList |Export-Csv -Path $Global:CSVFilePath -Force -NoTypeInformation

}
else{

    if ($Search.Count -gt 1)
    {$_.SearchResult = 'Matches Found'}
    else
    {$_.SearchResult = 'Match Found'}
    
    for ($i=0; $i -lt $Search.Count; $i++)
    {

        $MatchedProductName= $MatchedProductName + $Search.Item($i).ProductName+"`n"
        $MatchedVersion= $MatchedVersion + $Search.Item($i).Version+"`n"
        $_.MatchedProductName = $MatchedProductName
        $_.MatchedVersion = $MatchedVersion

    }

    $_.SelectedProductName = $Search.Item(0).ProductName
    $_.SelectedVersion = $Search.Item(0).Version
    $_.SelectedPkgFid = $Search.Item(0).PackageFeedId
    $ProductsList |Export-Csv -Path $Global:CSVFilePath -Force -NoTypeInformation
}


if (!($Search -like '*No matching records found*')){

$fids = $Search.Item(0).PackageFeedId
return $fids
} 

}

}

function ExecuteSQLQuery($strSQLQuery)
{

    $retval=-1
    $temp = ''
    $adapter = ''
    $command = ''
    $dataset = ''
    $Value = @()
    $result = ''
    $strSQLQuerySplit = ''
    If($strSQLQuery)
    {
    $ConnectionInfo   = 'Data Source=' + $SQLServer+';Initial Catalog=' + $global:CatalogName + ';user ID='+$SQLUserName+';password='+$SQLPassword+''
    $connection = new-object system.data.SqlClient.SQLConnection($connectionInfo)
    $command = new-object system.data.sqlclient.sqlcommand($strSQLQuery,$connection)
    $connection.Open()

    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $temp= $adapter.Fill($dataSet) 
    
    
    $result= $dataset.Tables

        $strSQLQuerySplit = $strSQLQuery.split()      
        if(($strSQLQuerySplit.item(0) -eq "select"))
        {
            if($strSQLQuerySplit[1].Contains(","))
            {
                
                for($row=0; $row -lt $result[0].Rows.Count;$row++)
                {
                    $Value+= $result[0].rows[$row].ItemArray+"`n"
                    $retval=$Value                   
                }
             }   
                
            else
            {        
                 $Value = $result[0].Columns[0].ColumnName
                
              if(![string]::IsNullOrEmpty($result.$Value)) 
                {
                       
                    $retval = ([string]$result.$Value).trim()
                      
                }
                else 
                {                         
                    $retval= $result.$Value   #Some select queries return null values

                }
            }
        }
        else
        {
            $retval = 0
        }  
        
    $connection.Close()       

    }
    return $retval
}

function SelectOptions ($Option1,$Option2)
{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
    
 
    $Form = New-Object System.Windows.Forms.Form
    $Form.width = 500
    $Form.height = 300
    $Form.Text = ”Select an option"
    $Form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen

 
 
    $WrapOptionsGrp = New-Object System.Windows.Forms.GroupBox
    $WrapOptionsGrp.Location = '40,30'
    $WrapOptionsGrp.size = '400,150'
 
    

    $Opt1Btn = New-Object System.Windows.Forms.RadioButton
    $Opt1Btn.Location = '20,40'
    $Opt1Btn.size = '350,30'
    $Opt1Btn.Checked = $true 
    $Opt1Btn.Text = $Option1
 
    $Opt2Btn = New-Object System.Windows.Forms.RadioButton
    $Opt2Btn.Location = '20,70'
    $Opt2Btn.size = '350,30'
    $Opt2Btn.Checked = $false
    $Opt2Btn.Text = $Option2
 
   
    $OKBtn = new-object System.Windows.Forms.Button
    $OKBtn.Location = '130,200'
    $OKBtn.Size = '80,30' 
    $OKBtn.Text = 'OK'
    $OKBtn.DialogResult=[System.Windows.Forms.DialogResult]::OK
 
    $CancelBtn = new-object System.Windows.Forms.Button
    $CancelBtn.Location = '255,200'
    $CancelBtn.Size = '80,30'
    $CancelBtn.Text = "Cancel"
    $CancelBtn.DialogResult=[System.Windows.Forms.DialogResult]::Cancel
 
    $form.Controls.AddRange(@($WrapOptionsGrp,$OKBtn,$CancelBtn))

 
  
    $WrapOptionsGrp.Controls.AddRange(@($Opt1Btn,$Opt2Btn))
    
    $form.AcceptButton = $OKBtn
    $form.CancelButton = $CancelBtn
 
    $form.Add_Shown({$form.Activate()})    
    
  
    $dialogResult = $form.ShowDialog()
 
 
    if ($dialogResult -eq "OK"){
        
 
        if ($Opt1Btn.Checked){
                     
           $OptionSelected = $Option1
           
           }
        elseif ($Opt2Btn.Checked){
                          
              $OptionSelected = $Option2
              }
        
        return $OptionSelected

    }
    else
    {

    $OptionSelected = $null
    return $OptionSelected

    }

}

function SelectTasks()
{

$TasksList = "Import", "Test","Wrap","PublishToSCCM"

$formTitle="Select Tasks"


    $Form = New-Object System.Windows.Forms.Form
    $btnCancel = New-Object System.Windows.Forms.Button
    $btnNext = New-Object System.Windows.Forms.Button
    $cloCheckList = New-Object System.Windows.Forms.CheckedListBox
    $btnMargin = New-Object System.Windows.Forms.Padding(4,4,4,4)
    $btnSize = New-Object System.Drawing.Size(80,30)
	
    $Form.SuspendLayout()

    $btnCancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    $btnCancel.Location = New-Object System.Drawing.Point(246, 134)
    $btnCancel.Margin = $btnMargin
    $btnCancel.Size = $btnSize
    $btnCancel.Text = "Cancel"

   
    $btnNext.DialogResult = [System.Windows.Forms.DialogResult]::OK
    $btnNext.Location = New-Object System.Drawing.Point(246, 83)
    $btnNext.Margin = $btnMargin
    $btnNext.Size = $btnSize
    $btnNext.Text = "OK"

    $cloCheckList.FormattingEnabled = $true
    $cloCheckList.Items.AddRange($TasksList)
    $cloCheckList.Location = New-Object System.Drawing.Point(12, 12)
    $cloCheckList.Size = New-Object System.Drawing.Size(227, 165)
    			
			
    $Form.AcceptButton = $btnNext
    $Form.AutoScaleMode = [System.Windows.Forms.AutoScaleMode]::None
    $Form.CancelButton = $btnCancel
    $Form.ClientSize = New-Object System.Drawing.Size(376, 189)
    $Form.Margin = $btnMargin
    $Form.Name = "Form"
    $Form.Text = $formTitle
    $Form.MaximizeBox = $False
    $Form.MinimizeBox = $False
    $Form.ShowIcon = $true
    $Form.ShowInTaskbar = $true
    $Form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
    $Form.TopMost = $True
    $Form.WindowState = [System.Windows.Forms.FormWindowState]::Normal
    $Form.Controls.Add($cloCheckList)
    $Form.Controls.Add($btnCancel)
    $Form.Controls.Add($btnNext)
	
	
	$Form.ResumeLayout($true)
    
	$result = $form.ShowDialog()
	if ($result -eq ([System.Windows.Forms.DialogResult]::OK)){
		$selections += for($i=0; $i -lt $($cloCheckList.CheckedItems.Count); $i++){
			$($cloCheckList.CheckedItems[$i])
		}
	}
	else{
		$selections = $null
        
	}

   
    If ($selections -eq $null)

    {

    Write-Host 'No tasks selected. Exiting Script!' -ForegroundColor Red
    Exit
    
    }
    
    If ($selections.contains('Wrap')) {

    $selectwrap = SelectOptions 'PowerShellWrapping' 'EXEWrapping'
    if ($selectwrap -eq $null)
    {
        Write-Host 'Make a selection for Wrapping Option. Exiting Script!' -ForegroundColor Red
        Exit
    }
    else
    {
        $selections -replace 'Wrap', $selectwrap
    }
    
    }

    else{$selections}
 
}                        
                            
function AddDetectionMethod($PkgO,$DMFilePath,$DLFilePath, $DMPrimaryFileVersion)
{
                            
$DMPrimaryFilePath = split-path $DMFilePath -Parent
$DMPrimaryFileName = split-path $DMFilePath -leaf

$xmlcontent =  '<?xml version="1.0"?>
                <DetectionMethod>
                <FileDetectionMethodHelper>
                <Id>0</Id>
                <Connector>None</Connector>
                <DetectionType>FileSystem</DetectionType>
                <FileSystemType>File</FileSystemType>
                <FileSystemPath>'+$DMPrimaryFilePath +'</FileSystemPath>
                <FileSystemName>'+$DMPrimaryFileName+'</FileSystemName>
                <Is64BitFile>false</Is64BitFile>
                <CheckExistsOnly>false</CheckExistsOnly>
                <FileSystemProperty>Version</FileSystemProperty>
                <Operator>IsEquals</Operator>
                <Value>'+$DMPrimaryFileVersion+'</Value>
                </FileDetectionMethodHelper>
                </DetectionMethod>'

$strSource= split-path $DLFilePath -Parent
Set-Content $strSource\$ProdName.xml $xmlcontent

$AddDM = Set-ASAppModelData -PackageId $PkgO.RowID -Type DetectionMethod -XmlPath $strSource\$ProdName.xml

If ($AddDM -eq $null)

{

Write-Host $ProdName ': Adding Detection Method for this package failed. If there are no default detection methods, then Publish to ConfigMgr may fail' -ForegroundColor Red

}

Remove-Item -Path $strSource\$Prodname.xml


}

function DownloadSetupFile ($PackageFid, $SetupFile)             
{
                
    try{

       $download = Invoke-ASPackageFeedDownload -PackageFeedId $PackageFid -FileName $SetupFile -ErrorAction Stop

                                
       }          
    catch
       {
        
        Write-Host 'Download may have failed:'$SetupFile -ForegroundColor Red
        $download = $null
                
       }

    return $download

}

function ProcessApplication($AppsList)
{

    $pkgfids = SearchResults($AppsList)
    $Tasks = SelectTasks

    Foreach($pkgfid in $pkgfids){

    
    $AppsList | ForEach-Object {
    if ($_.SelectedPkgFid -eq $pkgfid)
    {
    
    $SearchedProd = $_.$Global:ProductColumnName
    
    }
    } #To identify the product name from the csv file 


    $PackageDetails = Get-ASPackageFeedDetails -PackageFeedId  $pkgfid
    
    $SilentCmdLineSwitch = $PackageDetails.SilentCommandLineSwitches
    $SetupFileName=$PackageDetails.FileName
    $ProdName = $PackageDetails.ProductName
    $PFSoftVersion = $PackageDetails.Version
    $PrimaryFileVersion = $PackageDetails.PrimaryFileVersion
    $FilePath = $PackageDetails.PrimaryFile


    Foreach ($Task in $Tasks)
    {
    
    switch($Task){

    Import
    {
            
 
    $ProdExistQuery = "Select * from cstblpackage where ProductName like '%$SearchedProd%'"
    $ProdExists = ExecuteSQLQuery $ProdExistQuery

    If ($ProdExists -ne $null)
    {

        $SoftVersionQuery = "Select ProductVersion from cstblpackage where ProductName like '%$SearchedProd%'"
        $SoftVersion = ExecuteSQLQuery $SoftVersionQuery
        
        $SoftVersionSplit = $SoftVersion.split()       
        $maxVerion = ($SoftVersionSplit | Measure -Max).Maximum   

        try{

                If ([System.Version]$PFSoftVersion -gt [System.Version]$maxVerion)               
                {


                    $DownloadedFilePath = DownloadSetupFile $pkgfid $SetupFileName

                    if ($DownloadedFilePath -ne $null)
                        {

            
                            $PkgObj = Import $DownloadedFilePath $SilentCmdLineSwitch

                            if ($PkgObj -ne $null)
                            {
                            AddDetectionMethod $PkgObj $FilePath $DownloadedFilePath $PrimaryFileVersion
                            }
                            else
                            {
                            Write-Host 'Import may have failed for the setup file:' $DownloadedFilePath -ForegroundColor Red
                            Break
                           
                            }

                        }
                    else
                        {
                            Write-Host 'Setup file not found. Download may have failed!' -ForegroundColor Red
                            $PkgObj = $null
                            Break
                        }
    
                }
    
                else
                {

                    Write-Host $ProdName ':AdminStudio catalog already has this setup file of either same or higher software version' -ForegroundColor Red
                    $PkgObj = $null
                    Break

                }

            }

        catch{

                Write-Host $ProdName ':Error while comparing software version, importing the package anyway' -ForegroundColor Green
                
                    $DownloadedFilePath = DownloadSetupFile $pkgfid $SetupFileName
                    if ($DownloadedFilePath -ne $null)
                        {
            
                            $PkgObj = Import $DownloadedFilePath $SilentCmdLineSwitch
                         if ($PkgObj -ne $null)
                            {
                            AddDetectionMethod $PkgObj $FilePath $DownloadedFilePath $PrimaryFileVersion
                            }
                         else
                            {
                            Write-Host 'Import may have failed for the setup file:' $DownloadedFilePath -ForegroundColor Red
                            Break
                           
                            }


                        }
             }
    }
    else
    {

        $DownloadedFilePath = DownloadSetupFile $pkgfid $SetupFileName
        if ($DownloadedFilePath -ne $null)
        {
           Write-Host $ProdName ': Package does not exist in catalog. Importing the package...' -ForegroundColor Green

           $PkgObj = Import $DownloadedFilePath $SilentCmdLineSwitch
           if ($PkgObj -ne $null)
              {
                 AddDetectionMethod $PkgObj $FilePath $DownloadedFilePath $PrimaryFileVersion
              }
           else
              {
                 Write-Host 'Import may have failed for the setup file:' $DownloadedFilePath -ForegroundColor Red
                 Break
             
              }

        }
        else
        {
            Write-Host 'Setup file not found. Download may have failed!' -ForegroundColor Red
            $PkgObj = $null
            Break
        }


    }

    }

    Test
    {
    
    if ($PkgObj -ne $null)
       {
         Test ($PkgObj)
       }
    else
       {
         Write-Host $ProdName ':Cannot Test. Import may have failed for this package' -ForegroundColor Red
         Break
                 
       }
    }

    PublishToSCCM
    {

        if ($PkgObj -ne $null)
       {

       Write-Host 'tasks' + $Tasks

       If ($Tasks.Contains("PowerShellWrapping") -or $Tasks.Contains("EXEWrapping"))
       
       {
       $PkgId = $PkgObj.RowID + 1
       }
       
        else 
        
       {
       $PkgId = $PkgObj.RowID
       }

         DistributePackage ($PkgId)
         
       }
    else
       {
         Write-Host $ProdName ':Cannot Publish. Import may have failed for this package' -ForegroundColor Red
         Break
                 
       }
    }

    PowerShellWrapping
    {
    
    if ($PkgObj -ne $null)
       {
         Invoke-ASWrapPackage -PackageID $PkgObj.RowID -WrapType Ps1
       
       }
    else
       {
         Write-Host $ProdName ':Cannot Wrap. Import may have failed for this package' -ForegroundColor Red
         Break
                 
       }
    }
    

    EXEWrapping
    {

        if ($PkgObj -ne $null)
       {
         Invoke-ASWrapPackage -PackageID $PkgObj.RowID -WrapType Exe
       }
    else
       {
         Write-Host $ProdName ':Cannot Wrap. Import may have failed for this package' -ForegroundColor Red
         Break
                 
       }

    }

    $null
    {
    
    Write-Host 'No tasks selected!' -ForegroundColor Red
    exit}

    
    }

}
}
}

function Test ($o)
{
    Write-Host 'Testing Package:' $o.DisplayedProductName -nonewline -foregroundcolor white
    Write-Host ' RowId:' $o.RowID -foregroundcolor gray
    $oTestResults = Test-ASPackage -PackageId $o.RowID
    $errors = 0;
    $warn = 0;
    $fixable=0;
    foreach ($oTestResult in $oTestResults.Stats) 
    {
          $errors =  $errors + $oTestResult.Errors
          $warn   =  $warn +   $oTestResult.Warnings
          
    }
    Write-Host-Indent
    Write-Host 'Errors:' $errors -foregroundcolor red
    Write-Host-Indent
    Write-Host 'Warnings:' $warn -foregroundcolor yellow
    Write-Host

}

function Import ($s, $SilentSwitch)
{


    $f = [System.IO.File]::GetAttributes($s)
    $d = ($f -band [System.IO.FileAttributes]::Directory)
    if (!$d)
    {
        Write-Host 'Importing:' $s -foregroundcolor white
        $obj = Invoke-ASImportPackage -PackagePath $s -InstallCommandLine $SilentSwitch
        if ($obj.GetType().FullName -eq 'AdminStudio.Platform.Helpers.PackageHelper')
        {

        return $obj

        }
        else
        {
            Write-Host 'Failed to import:' $s -foregroundcolor red
            $obj = $null
            return $obj
        }


    }


}

function DistributePackage($PkgID)
{

    New-ASDistributionConnection -Name $DistributionName -PluginID $SCCMPluginID -ServerAddress $SCCMServer -SiteCode $SCCMServerSiteCode -DistributionWindowsAuthentication 0 -DistributionUser $SCCMUser -DistributionPassword $SCCMPass -SharePath $SCCMRepositoryPath -ShareWindowsAuthentication 0 -ShareUserName $ShareUser -SharePassword $SharePwd

            
        Write-Host 'Distributing the Package:' $oPkg.DisplayedProductName -nonewline -foregroundcolor white
        Write-Host ' RowId:' $PkgID -foregroundcolor gray
           
        $oAppID = Get-ASApplicationID -PackageID $PkgID
        Invoke-ASPublish -ConnectionName $DistributionName -ApplicationID $oAppID �'TargetGroup $SCCMTargetGroup
}

function SelectFromDropDown ($ColumnName,$arrName) 
{

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = $ColumnName
$form.Size = New-Object System.Drawing.Size(500,200)
$form.StartPosition = 'CenterScreen'

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size (400,20)
$label.Text = 'Please select the column for: '+$ColumnName
$form.Controls.Add($label)

$DropDown = New-Object System.Windows.Forms.ComboBox
$DropDown.Location = New-Object System.Drawing.Point(10,40)
$DropDown.Size = New-Object System.Drawing.Size(260,20)
$DropDown.Height = 80


 ForEach ($Item in $arrName) {
     [void] $DropDown.Items.Add($Item)
    }


$form.Controls.Add($DropDown)

$form.Topmost = $true

$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $x = $DropDown.SelectedItem
    return $x
}

else 
{
$x = $null

return $x

}

}

function Write-Host-Drawline ()
{
    Write-Host '**************************************' -foregroundcolor yellow
}

function Write-Host-Indent ()
{
    Write-Host '                 ' -nonewline
}


################################################################
# Main Loop
################################################################

cd $sAsLoc
Write-Host
Write-Host-Drawline
Write-Host 'AdminStudio Directory =' $sAsLoc -foregroundcolor gray
Write-Host 'Catalog Name=' $global:CatalogName -foregroundcolor gray
Write-Host-Drawline
Write-Host


PrepAS
ProcessInputCSV

$Option = SelectOptions 'Search Apps' 'Process Apps'
If ($Option -eq 'Search Apps')
{SearchResults($Global:CSVContent)}
elseif ($Option -eq 'Process Apps')
{ProcessApplication($Global:CSVContent)}
else
{write-host 'Exiting the script. Please make a selection.' -ForegroundColor Red
Exit
}


cd $sCurrentLoc

################################################################
# End
################################################################