none
HCK: How to use PackageWriter to merge submission packages RRS feed

  • Question

  • Hello,

    I'm curious how to use the HCK Object Model to merge submission packages.

    After a large HCK run, I will have a pile of packages that I wish to merge together.  So in the reference I looked up the function under the PackageWriter class:

    Merge

    This method merges a project into an existing package. This method can only be used for existing submission packages.

    Question 1.  Can the PackageWriter's Merge function be used to merge two submission packages together, or is it only one submission package and one project?  This is important because the original plan was to merge packages together after tests were run, packages were created, and projects were deleted.

    Question 2.  Assuming we can only merge an existing package into a project (instead of another package), I wrote a function to try it out:

    Function mergeSubmissionPackage
    {
        Param(
            [Parameter(Mandatory=$false)]
            [string]$controller = $env:COMPUTERNAME,
    
            [Parameter(Mandatory=$true)]
            [string]$projectName,
    
            [Parameter(Mandatory=$true)]
            [string]$packageToMergeIn
    
            #[Parameter(Mandatory=$false)]
            #[string]$packageFileToOpen
        )
    
        # Connect to controller with custom function
        connect $controller
    
        # Load project
        $project = $Manager.GetProject($projectName)
        if ($project -eq $null)
        {
            Write-Host "Unable to load project `n" $error.ToString() -ForegroundColor Red
        }
    
        # Merge
        $packageWriter = new-object -typename Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageWriter -Args $project
        $packageWriter.Merge($packageToMergeIn)
    }
    

    My cute attempt resulted in this message:

    Cannot find an overload for "Merge" and the argument count: "1".At C:\Users\HCKRUNNER\automation\hck.ps1:1193 char:5
    +     $packageWriter.Merge($packageToMergeIn)
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : MethodCountCouldNotFindBest

    I'm quite sure this means I am not feeding the Merge function properly.  Referencing http://msdn.microsoft.com/en-us/library/windows/hardware/jj124718.aspx to see if there are more clues.  It would be awesome if that included a PowerShell example (I wish it did : )  May I ask what I'm doing wrong?  Thanks!
                                                                                                                                     
    Friday, December 6, 2013 11:09 PM

All replies

  • Question 1 - yes, you can merge a package with another package. More particularly, PackageManager packages and merges projects rather than package files. The PackageWriter constructor takes in a "base" project from either a database connection or package connection (ProjectManager::GetProject()). You can then merge in other projects.

    Question 2 - The Merge method takes in a Project (you passed in the path to the package) and [out] StringCollection as parameters. See http://msdn.microsoft.com/en-us/library/windows/hardware/jj124718.aspx for more info.


    John -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, December 6, 2013 11:22 PM
  • Thank you.   …So, let's say I have two packages to merge.  They are not in the HCK Studio under "Projects", so I assume they are not "opened".

    To use PackageWriter.Merge(), I must "connect" to the two packages somehow, or "open them up", and they will show in the HCK Studio as 'projects'.  Then, I believe, I can merge them.

    How, in PowerShell, can I open up two submission packages so that they are 'projects' that can be passed into the PackageWriter for Merge()?  I've been looking all over the documentation and web, but haven't found the clue : )

    (To better word the question:  how do we get a project from a package connection?)

    • Edited by hh-hh-hh Monday, December 9, 2013 9:46 PM
    Monday, December 9, 2013 8:48 PM
  • You can just provide the folder path of .hckx files, then run a counter to count the number of .hckx files and then start merging the package. in this case, you don't need to open the .hckx package in studio for merging purpose.

    Thanks,

    Mudit

    Tuesday, December 10, 2013 4:41 AM
  • Thank you for the reply.  I feel close to the solution, however it still is not working.  I modified the function to work in this manner:

    Function mergeSubmissionPackage
    {
        Param(
            [Parameter(Mandatory=$false)]
            [string]$controller = $env:COMPUTERNAME,
    
            [Parameter(Mandatory=$true)]
            [string]$package1,
    
            [Parameter(Mandatory=$true)]
            [string]$packageToMergeIn
        )
    
        # Connect to controller with custom function
        connect $controller
    
        # Merge
        $packageWriter = new-object -typename Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageWriter -Args $package1
        $packageWriter.Merge($packageToMergeIn)
    }

    However, calling that function results in an error which suggests that I am not using the Merge correctly:

    PS C:\Users\HCKRUNNER> . .\hck.ps1
    PS C:\Users\HCKRUNNER> mergeSubmissionPackage -package1 C:\run_a.hckx -packageToMergeIn C:\run_b.hckx

    new-object : Cannot find an overload for "PackageWriter" and the argument count: "1".
    At C:\Users\HCKRUNNER\hck.ps1:1182 char:22
    +     $packageWriter = new-object -typename Microsoft.Windows.Kits.Hardware.Object ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodException
        + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
    
    You cannot call a method on a null-valued expression.
    At C:\Users\HCKRUNNER\hck.ps1:1183 char:5
    +     $packageWriter.Merge($packageToMergeIn)
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : InvokeMethodOnNull
    

    The goal here was to merge the two packages, 'run_a' and 'run_b'.  What am I doing wrong?


    • Edited by hh-hh-hh Tuesday, December 10, 2013 2:45 PM
    Tuesday, December 10, 2013 2:41 PM
  • It looks like you are trying to pass the package into the Merge method. As I mentioned above, you need to pass in the project. Create an instance of PackageManager passing in the package file. Get the project and pass that into the merge method.

    John -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, December 10, 2013 4:31 PM
  • I need to pass in a project to the Merge() method.  I can create an instance of Package Manager passing in the package file, I think it would be like this:

    Let's say I have two packages, $package1 and $package2:

    $packageManager = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -ArgumentList $package1

    I've passed $project1 to $packageManager.  Now I need to get the project.  Then I will need to pass that project into the Merge().  I presume the project will need to come from $package2.

    How, from $package2, can I get the project to pass into the PackageWriter.Merge()?

    • Edited by hh-hh-hh Saturday, December 14, 2013 5:04 AM
    Tuesday, December 10, 2013 11:38 PM
  • Hi John,

    I posted one query, till now no able to answer it. I think you have missed that. I'm hoping that you must have solution for my issue. here is the link of my query

    http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/a62524cc-ce2c-4dc3-8e50-d86c7bfc6cfc/project-info-is-not-updating-when-scheduling-the-test-by-using-the-queuetest-function-of-test-class?forum=whck#a62524cc-ce2c-4dc3-8e50-d86c7bfc6cfc

    Thanks,

    Mudit

    Saturday, December 14, 2013 3:33 AM
  • Mudit,

    I added a reply to your question in the link you provided.  It may or may not be exactly what you are looking for, but I hope it is helpful.

    Saturday, December 14, 2013 5:24 AM
  • thanks, I checked it and replied
    Sunday, December 15, 2013 11:25 AM
  • The main question at the moment is, how do I 'get the project'?
    Monday, December 16, 2013 7:32 PM
  • See http://social.msdn.microsoft.com/Forums/en-US/348d0e72-cf11-44ea-852c-a55ec3e5fd3b/hck-object-model-obtain-project-from-package?forum=whck (where this question was posted).

    John -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, December 18, 2013 4:56 PM
  • John, 

    Thank you!  It's getting close now : )

    The merge function is updated, and a bit verbose, but a good share of it is working:

    Function mergeSubmissionPackage
    {
        Param(
            [Parameter(Mandatory=$false)]
            [string]$controller = $env:COMPUTERNAME,
    
            [Parameter(Mandatory=$true)]
            [string]$package1,
    
            [Parameter(Mandatory=$true)]
            [string]$package2
        )
    
        $packageManager1 = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package1
        $packageManager2 = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package2
    
        $project1name = $packageManager1.GetProjectNames()[0]
        $project2name = $packageManager2.GetProjectNames()[0]
    
        $project1 = $packageManager1.GetProject($project1name)
        $project2 = $packageManager2.GetProject($project2name)
    
        Write-Host "Project 1: $project1, $($project1.Name)"
        Write-Host "Project 2: $project2, $($project2.Name)"
    
        # things work good up to this point
    
        $packageWriter = new-object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageWriter -ArgumentList $project1
    
        $errors = New-Object -TypeName System.Collections.Specialized.StringCollection
    
        $packageWriterMergeResult = $packageWriter.Merge($project2, $errors)
        Write-Host "Merge result: $packageWriterMergeResult"
    }

    I get the following result:

    Argument: '2' should be a System.Management.Automation.PSReference. Use [ref].
    At C:\Users\HCKRUNNER\hck.ps1:1355 char:5
    +     $packageWriterMergeResult = $packageWriter.Merge($project2, $errors)
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : NonRefArgumentToRefParameterMsg

    Well, the API reference did say:

    "errors 
         Reference to a string collection that returns error messages for merging a project."

    (http://msdn.microsoft.com/en-us/library/windows/hardware/jj124718.aspx)

    Ok, then.  I change it from:

       $errors = New-Object -TypeName System.Collections.Specialized.StringCollection

    to:

       $errors = New-Object -TypeName System.Management.Automation.PSReference

    and get:

    New-Object : Constructor not found. Cannot find an appropriate constructor for type System.Management.Automation.PSReference.
    At C:\Users\HCKRUNNER\hck.ps1:1354 char:15
    +     $errors = New-Object -TypeName System.Management.Automation.PSReference
    +               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (:) [New-Object], PSArgumentException
        + FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.Commands.NewObjectCommand

    Argument: '2' should be a System.Management.Automation.PSReference. Use [ref].
    At C:\Users\HCKRUNNER\hck.ps1:1355 char:5
    +     $packageWriterMergeResult = $packageWriter.Merge($project2, $errors)
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : NonRefArgumentToRefParameterMsg

    I need to learn more about PSRefernce.  So I looked up system.management.automation.PSReference in , and was surprised to get:

    "No Results Found For: system.management.automation.PSReference"

    So, in a bit of frustration, I think "maybe the 2nd parameter is optional?"  I cannot tell from the documentation (http://msdn.microsoft.com/en-us/library/windows/hardware/jj124718.aspx) if it is.

    Trying it without the 2nd parameter

    $packageWriterMergeResult = $packageWriter.Merge($project2)

    yields:

    Cannot find an overload for "Merge" and the argument count: "1".
    At C:\Users\HCKRUNNER\hck.ps1:1355 char:5
    +     $packageWriterMergeResult = $packageWriter.Merge($project2)
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : MethodCountCouldNotFindBest

    What does it want from me?


    • Edited by hh-hh-hh Wednesday, December 18, 2013 11:42 PM
    Wednesday, December 18, 2013 11:18 PM
  • I'm not strong with PowerShell but Merge takes error and a 'out' parameter. I think you need to leave it as a string value and preface the call with [ref] -

        $errors = New-Object -TypeName System.Collections.Specialized.StringCollection
    
        $packageWriterMergeResult = $packageWriter.Merge($project2, [ref] $errors)
     


    John -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, December 19, 2013 4:55 PM
  • John,

    Thank you : )  It was enough to get me going.  I created a working prototype of merging packages:

    Function mergeSubmissionPackage
    {
        Param(
            [Parameter(Mandatory=$false)]
            [string]$controller = $env:COMPUTERNAME,
            
            [Parameter(Mandatory=$false)]
            [string]$package1,
    
            [Parameter(Mandatory=$false)]
            [string]$package2,
    
            [Parameter(Mandatory=$false)]
            [string]$package3,
    
            [Parameter(Mandatory=$false)]
            [string]$newPackageName = "C:\mergedPackage"
        )
    
        $packageManager1 = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package1
        $packageManager2 = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package2
        $packageManager3 = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package3
        
        $project1name = $packageManager1.GetProjectNames()[0]
        $project2name = $packageManager2.GetProjectNames()[0]
        $project3name = $packageManager3.GetProjectNames()[0]
    
        $project1 = $packageManager1.GetProject($project1name)
        $project2 = $packageManager2.GetProject($project2name)
        $project3 = $packageManager3.GetProject($project3name)
    
        Write-Host "Project 1: $project1, $($project1.Name)"
        Write-Host "Project 2: $project2, $($project2.Name)"
        Write-Host "Project 3: $project3, $($project3.Name)"
        
        $packageWriter = new-object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageWriter -ArgumentList $project1
        $errors = New-Object -TypeName System.Collections.Specialized.StringCollection
    
        $packageWriterMergeResult = $packageWriter.Merge($project2, [ref]$errors)
        Write-Host "Merge result: $packageWriterMergeResult"
        $packageWriterMergeResult = $packageWriter.Merge($project3, [ref]$errors)
        Write-Host "Merge result: $packageWriterMergeResult"
    
        $packageWriter.Save("c:\mergeTesting\$newPackageName")
    
        $packageWriter.Dispose()
        $packageManager1.Dispose()
        $packageManager2.Dispose()
        $packageManager3.Dispose()
    }
    

    I am trying to make this work for any number of packages, 2 or more.

    PackageManager's constructor takes a package as a parameter.

    It seemed as if I had to create a new packageManager object for each package that I wanted to obtain a project for, in order to merge it in.

    After I am done with the packageWriter and all the many packageManagers I had created, they all need to be cleaned up.  That appears to not be working reliably, sometimes a subsequent run of the function fails because a file is in use and cannot be opened (meaning I have not cleaned up from the previous run correctly).

    It would seem easiest if there exists a more elegant way to merge packages together than what I have attempted below (note that the "log" function called in this code is a homegrown thing I made, not a PowerShell standard method):

    Function mergeSubmissionPackage
    {
        Param(
            [Parameter(Mandatory=$false)]
            [string]$controller = $env:COMPUTERNAME,
    
            [Parameter(Mandatory=$true)]
            [string[]]$packages,
    
            [Parameter(Mandatory=$false)]
            [string]$newPackageName = "C:\mergedPackage"
            
        )
        
     
        # TODO: Find the proper way to clean up the packageManagers -- we cannot
        # dispose them until the merge and save are completed, but by that time,
        # we are out of the loop that iterates over the array of packages.
        # If we delete the PackageManagers too soon, the merge and save 
        # will not work, and will complain of
        # not being able to use a disposed object.  : (
    
        # intended for keeping track of the packagemanagers, till we delete them
        $packageManagerArray = @()
    
        $package0 = $packages[0]
        Log "First package: $package0" debug
        $packageManager0 = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package0
        $packageManagerArray = $packageManagerArray + $packageManager0
        $project0Name = $packageManager0.GetProjectNames()[0]
        $project0 = $packageManager0.GetProject($project0Name)
    
        # create package writer
        $packageWriter = new-object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageWriter -ArgumentList $project0
        $errors = New-Object -TypeName System.Collections.Specialized.StringCollection
        
        # create the remaining projects here and merge them into the packagewriter
        Foreach ($package in ($packages | select -Skip 1))
        {
            log "$package" debug
            log "$($package.gettype().FullName)" debug
            Log "Index: $([array]::indexof($packages, $package))`n" debug
            log "Package to send in: $package" debug
        
            # give it a custom name based on the index of the package being passed in
            $packageManager = "packageManager" + $([array]::indexof($packages, $package))
            log "packageManager name: $packageManager" debug
            
            $packageManager = New-Object -TypeName Microsoft.Windows.Kits.Hardware.ObjectModel.Submission.PackageManager -Args $package
            # add this instance of PackageManager to the array that we are using
            # to keep track of the objects we want to dispose of 
            # after we have safely obtained our final merged package.
            $packageManagerArray = $packageManagerArray + $packageManager
    
            $newProjectName = $packageManager.GetProjectNames()[0]
            $newProject = $packageManager.GetProject($newProjectName)
    
            $packageWriterMergeResult = $packageWriter.Merge($newProject, [ref]$errors)
            Log "PackageWriter merge result: $packageWriterMergeResult" debug
            
        }
    
        # append the file extension to the submission package name, if needed
        if ($newPackageName.EndsWith(".hckx")) {}
        else {$newPackageName = "$newPackageName.hckx"}
        
        # save the new package
        $packageWriter.Save($newPackageName)
    
        # Attempt to .Dispose() of the packageManager objects
        # all while not knowing if this will really work.
        Foreach ($item in $packageManagerArray)
        {
            log $($item) debug
            $item.dispose()
        }
        # finally, retire the packageWriter
        $packageWriter.Dispose()
    }
    

    Is there a C# example of merging 2+ packages somewhere in the world that might show a much more elegant attempt than mine?  : )

    Thanks!

    Friday, December 20, 2013 4:20 AM