none
AddUpdateContent Method in Class SMS_SoftwareUpdatesPackage "ContentSourcePath?"

    Question

  • Hello,

    I'm attempting to programmatically (.NET API) add software updates to software update packages. I found the following method in SMS_SoftwareUpdatePackage (AddUpdateContent):

    http://msdn.microsoft.com/en-us/library/hh949568.aspx

    ... what the heck is this "ContentSourcePath" argument? I can't find this anywhere in the GUI. Is this supposed to be a path where source files will be placed (...?) or somewhere where they ALREADY exist (also '...?')? Neither particularly makes sense to me, since the package already defines a "source path" (and, obviously, where they "already exist" is on the internet, D'OH). When I try manually downloading the update (I read somewhere that you must manually download the update), it doesn't seem to change the source path in the software update's property sheet (nor did I get the opportunity to input a path):


    What do I do here? Where do I get this? Do I need to put this in manually (AKA, request user input) or is there a way to query for this? 





    Wednesday, August 28, 2013 9:05 PM

Answers

  • After speaking with MS support about this issue, we were able to resolve the problem.

    Basically, you need to query for the "SourceURL" of the software update, download it to a folder accessible from the SCCM server (such as a UNC share), and then put that folder path in the "ContentSourcePath" array for each software update.

    SCCM won't automatically download the update and stuff, but it will copy it from this path to the package source path so you don't have to do that part manually.

    ... also, the "ContentIds" array is supposed to be an array of "ContentID" so you have to join SMS_SoftwareUpdate to SMS_CIToContent. To get the SourceURL you have to join that with SMS_CIContentFiles.

    Once all that is done, the function works. What a pain.

    Friday, September 20, 2013 1:40 PM

All replies

  • Hi,

    I believe you don't need that.

    Have a look at my script here: http://www.david-obrien.net/2013/01/07/update-how-to-create-a-new-software-update-group-in-configmgr-2012/

    I know it doesn't cover all the use cases, but you should get an idea of how to add SOftware Updates to Update Groups.

    Hope that helps!


    My blog on ConfigMgr automation: www.david-obrien.net | me on Twitter: @david_obrien Please remember to mark the post(s) that helped you resolve the issue (even if it was your own) so that people searching for similar issues with a "Answered" filter can find it easier.

    Thursday, August 29, 2013 6:54 AM
  • That seems to be adding updates to a group, not a package.
    Thursday, August 29, 2013 12:50 PM
  • I've been playing around with it. I compiled the code that is going to eventually be adding these updates to a package and tried putting in a blank "ContentSourcePath" - SCCM throws errors. It's definitely a mandatory field (and it's documented as such).

    If I put a URL in there ("SourceURL"), SCCM throws "ContentSourcePath is a URL."

    If I put a blank path or some random path, it throws "Downloaded content specified in package source directory is in wrong location."

    Where do I find this information? I feel like I'm pulling teeth here.

    EDIT: Even worse is what I previously mentioned about the "Download" menu option on software updates - so it changes the "Downloaded" flag to "Yes" but then doesn't update the "ImportPath" (I'm kind of assuming this is what I need to look for but I also tried the "FileName" field on SMS_CIContentFiles - both failed with the "wrong location" error)

    Thursday, August 29, 2013 4:00 PM
  • The field is the same as PkgSourcePath in SMS_SoftwareUpdatesPackage

    - Dave

    • Proposed as answer by tomcomtech_ Monday, July 21, 2014 8:25 PM
    Thursday, August 29, 2013 5:27 PM
  • That's good to know and points me in the right direction; however, when I manually enter the package source path (if this turns out to be the answer I will be querying for it, of course), I still get the "wrong location" error message.

    I'm not confident that this is the exact same functionality that I'm attempting, but when I click "Deploy" on a software update (this is the only way that I've found to assign an update to a package in the GUI at this point), it does something automatically and eventually adds the software update to the software update package without having to manually enter a source path. I don't know if it automatically downloads it and then takes that path and sticks it into this function ("AddUpdateContent"), but whatever it does I never had to manually enter a path.

    Now, if I look at the package's source path, I see that there was some folder created (the name of the folder seems to be a GUID) containing the update's file (in this case, it's a ".cab" file). Presumably this was downloaded because of the "Deploy" action I made (I can't be sure, I've been messing with this stuff all day long). Note that I had previously deployed a software update to a package and nothing was downloaded. Thereafter I noticed that the package's source path was "wrong" (I put in a local path C:\etc - I had created this thing programmatically and so I guess I was not subject to the "health checks"), and I subsequently changed it (to \\server\c$\etc, which is what the field says it should be). I have yet to get this particular software update to actually "Download" its contents (even after numerous manual "Download" actions made from the package's softwareupdate's menu).

    Do you see my issue here? If it's the case that this is absolutely necessary to be done manually, that's one thing, but I would like my users to be shielded from this exactly as much as SCCM users are currently shielded while using the SCCM console.

    Basically, I see two ways "around" this manual input of the content paths:

    1. (Somehow) Query for the source content path. Apparently, the argument to this function ("AddUpdateContent") is not exactly the same as the PkgSourcePath, otherwise my test would have worked. Perhaps it's meant to be "based on" the pkgsourcepath or something, but either way there must be (or at least seem to be) some other steps that the SCCM console performs here, like downloading the package contents automatically, etc.
    2. (Somehow) Automatically download the update to the PkgSourcePath. I haven't found a way to do this programmatically. Of course, I can download whatever I want and place it in a folder, but I'm using the .NET API - my users will not necessarily have admin access to the server that hosts the package source*, so I can't just use some extraneous .NET functionality to download the files. Now, even if I figured out how to download the contents to the package's source path automatically, it seems SCCM puts these into some kind of GUID folder (as I previously mentioned). If (IF!) I must follow this structure (create a GUID folder, download the contents to the folder, then "AddUpdateContent"), what does this GUID represent? Is it a field that is query-able?

    * - Note: The paths that I specify from within my SCCM console are relative to my SCCM server. In my case, for testing, the server is on another domain. My sysadmin had set up some dns forwarding or something (I'm not a network guy so I can't say for sure) so that I can access this server as \\server.domain. Of course I have admin privileges and all that, so it's no problem for me, HOWEVER, in the SCCM environment this package is set up to use "\\server\path." This means that if I'm executing this code on a machine in our main domain, I will certainly (100%) be unable to access that path. In other words, doing a "third-party" download of the update's file(s) would be impossible in this state. YES: I could change the path in my SCCM environment to point to "\\server.domain\path" but I would like this to work for my users under all possible circumstances and this "won't fly." Another consideration is the user context. My users currently provide credentials with which to connect to an SCCM environment. The "execution user" may NEVER have access to this SCCM environment. I may be able to fenagle something where I can use the provided credentials to spawn a new process that downloads this file, but in my case the SCCM credentials have no access on our main domain, which means I will never be able to spawn a process using those credentials on any given execution machine (in our case - other environments might be set up in a more sensical manner that allows for this to happen, but again I'd like all my use cases validated, even if my current use case is just a "sample" or "test" environment). 

    To summarize (I bolded my goal, main problem, and questions):

    • My goal is to enable my users to perform the same functions in the scope of my application as they can perform in the SCCM console (in other words, "programmatically" versus "manually"). This includes (but is obviously not limited to) assigning an update to a software update package.
    • The problem is this API doesn't seem to correlate to the functionality I find in the console. Could it be that I am not using the right methodology? Maybe there is a different function or some other way I could perform this assignment. I am certainly no SCCM expert, so it very well may be the case that I don't understand what's really going on here. Maybe I shouldn't be looking to "assign" this update to a package, but instead I should be attempting to "deploy" the software update. Are there other steps in this process that I am missing? Does what I'm trying to do even make sense? Can you perform a "deploy" of a software update using the .NET API?
    • Perhaps related: is there a way to download the contents of a software update through the SCCM .NET API? Again, it may not (always) be possible for my users to use a "third party" approach to this download.

    Thanks! I really appreciate the input. So far I've been "OK" working with the .NET API on my own (again, I'm not an SCCM expert so I expect to run into issues understanding and performing basic SCCM functionality), but this aspect of the project is turning out to be exceedingly difficult.

    Thanks again and sorry for the huggggge post!



    Thursday, August 29, 2013 6:41 PM
  • ContentSourcePath is an array that has same number of element as  ContentIDs parameter and
    each element has the same value as PkgSourcePath in SMS_SoftwareUpdatesPackage.  after you've changed to use this, what additional error do you meet? also you could do it in console and watch the smsprov.log to learn and mimic the console behavior
    Thursday, August 29, 2013 10:43 PM
  • While it's a very simple example, have you looked at:

    How to Add Updates to a Deployment Package

    http://msdn.microsoft.com/en-us/library/jj218135.aspx


    Jim Bradbury

    Friday, August 30, 2013 12:23 AM
  • Chuanbo: ContentIds is an unsigned integer array, and ContentSourcePath is a string array. Both contain exactly one element.

    (Note: As I wrote this post, I realized that ContentIds was supposed to be a uint array, whereas I was doing a .ToString() on each element to get a string array and then passing that in. I changed it to a uint array as documented without effect)

    ContentIds contains some ID of an update that I query for (I don't manually enter an ID)

    ContentSourcePath contains the string "\\SERVER\c$\TMP" (at this point I manually entered the path, but eventually I would like to take the manual entry out of the equation). EDIT: To be clear, this is the package's source path. I just checked, the case was off ("C$\TMP" instead of "c$\tmp" so I changed it without effect)

    The error I get is "Downloaded content specified in package source directory is in wrong location." This is the same as if I input any random path or just leave it blank.

    Jim: This is exactly the basic format that I use in my code, except it is unacceptable to have my user manually input these parameters (as implied by those hardcoded arrays in the example). Instead, I have the user (or at least this is what I'm attempting to do) feed me an update's name, a package name, and whether or not they want to refresh the package and I then query for the update's ID, the package ID (to do a GetInstance() for the SCCM package object), and whatever other information I (may) need to perform this action. This is more user-friendly. After all, if I - as a developer - can't make heads or tails out of these inputs, how can I expect my users to understand what they mean?

    Thanks, guys!



    Friday, August 30, 2013 1:57 PM
  • No ideas?

    At this point I think I'm going to assume there's a bug in this area.

    EDIT: I've opened a MS tech support case. Once we reach a resolution, I will post here with the results.

    Thanks, guys.

    Tuesday, September 03, 2013 12:46 PM
  • After speaking with MS support about this issue, we were able to resolve the problem.

    Basically, you need to query for the "SourceURL" of the software update, download it to a folder accessible from the SCCM server (such as a UNC share), and then put that folder path in the "ContentSourcePath" array for each software update.

    SCCM won't automatically download the update and stuff, but it will copy it from this path to the package source path so you don't have to do that part manually.

    ... also, the "ContentIds" array is supposed to be an array of "ContentID" so you have to join SMS_SoftwareUpdate to SMS_CIToContent. To get the SourceURL you have to join that with SMS_CIContentFiles.

    Once all that is done, the function works. What a pain.

    Friday, September 20, 2013 1:40 PM