{"id":180,"date":"2026-06-23T09:00:17","date_gmt":"2026-06-23T16:00:17","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/insidemsix\/?p=180"},"modified":"2026-06-07T22:10:12","modified_gmt":"2026-06-08T05:10:12","slug":"add-vs-stage-and-register","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/insidemsix\/add-vs-stage-and-register\/","title":{"rendered":"Add vs Stage and Register"},"content":{"rendered":"<p>As <a href=\"https:\/\/devblogs.microsoft.com\/insidemsix\/there-is-no-install-its-stage-and-register\/\">previously mentioned<\/a> to &#8216;install&#8217; a package, as people think of the term, Windows actually performs two separate operations: <em>staging<\/em> and <em>registration<\/em>.<\/p>\n<p>To oversimplify:<\/p>\n<ul>\n<li><strong>Staging<\/strong> puts the package content on disk. At this point the package is present, but inert and unused.<\/li>\n<li><strong>Registering<\/strong> wires the package into a user&#8217;s profile. This includes creating tiles on the Start Menu, defining <a href=\"https:\/\/learn.microsoft.com\/uwp\/schemas\/appxpackage\/uapmanifestschema\/element-uap-filetypeassociation\">file type associations<\/a> for the package&#8217;s applications and otherwise making the package available to the user.<\/li>\n<\/ul>\n<p>One way to &#8216;install&#8217; a package for a user is to explicitly stage it, then register the package:<\/p>\n<pre><code class=\"csharp\">var packageUri = new Uri(\"C:\\\\Packages\\\\ContosoParts-v1.2.3.4-x64.msix\");\nvar stageOptions = new StagePackageOptions();\nvar packageManager = new PackageManager();\nvar stageResult = await packageManager.StagePackageByUriAsync(packageUri, stageOptions);\n...\nvar packageFullName = \"Contoso.Parts_1.2.3.4_x64__1234567890abc\");\nvar registerOptions = DeploymentOptions.None;\nvar registerResult = await packageManager.RegisterPackageByFullNameAsync(packageFullName, null, registerOptions);\n...\n<\/code><\/pre>\n<p>But this scenario is common enough that deployment handles it more efficiently as a single <a href=\"https:\/\/devblogs.microsoft.com\/insidemsix\/deployment-operations-requests-and-queue\/\">deployment operation<\/a>: stage the package <em>and<\/em> register it in one request.<\/p>\n<p>That&#8217;s what the &#8216;Add Package&#8217; operation does:<\/p>\n<pre><code class=\"csharp\">var packageUri = new Uri(\"C:\\\\Packages\\\\ContosoParts-v1.2.3.4-x64.msix\");\nvar options = new AddPackageOptions();\nvar packageManager = new PackageManager();\nvar result = await packageManager.AddPackageByUriAsync(packageUri, options);\n...\n<\/code><\/pre>\n<p><code>AddPackage*()<\/code> ensures the package is staged if necessary, then registers it for the user.<\/p>\n<h2>Why not always Add?<\/h2>\n<p>Because staging and registration have very different scopes.<\/p>\n<p>A package is only staged once on a machine. Calling <a href=\"https:\/\/learn.microsoft.com\/uwp\/api\/windows.management.deployment.packagemanager.stagepackageasync\">PackageManager.StagePackageAsync()<\/a> multiple times only stages the package the first time. After that, deployment sees the package is already staged. Subsequent calls complete <em>very<\/em> quickly \ud83d\ude42.<\/p>\n<p>In practice, staging behaves like a per-machine operation. Multiple staging operations still result in only one copy of the package on disk.<\/p>\n<p>On the other hand, registration is inherently per-user. A user cannot access a package unless it&#8217;s registered for that user.<\/p>\n<p>An &#8220;Add Package&#8221; operation guarantees both staging and registration succeed together. That makes Add undesirable if you don&#8217;t want to register the package just yet.<\/p>\n<p>For example:<\/p>\n<ul>\n<li>You may want to stage and provision a package for all users without registering it for any specific user.<\/li>\n<li>Or you may want to stage an update while connectivity is available, but delay registration until a later time when updating the package would not disrupt the user.<\/li>\n<\/ul>\n<p>Likewise, sometimes you only need to register an already-staged package without performing any staging work \u2014 particularly if you no longer have access to the original <code>.msix<\/code> file needed for <code>AddPackageAsync()<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As previously mentioned to &#8216;install&#8217; a package, as people think of the term, Windows actually performs two separate operations: staging and registration. To oversimplify: Staging puts the package content on disk. At this point the package is present, but inert and unused. Registering wires the package into a user&#8217;s profile. This includes creating tiles on [&hellip;]<\/p>\n","protected":false},"author":911,"featured_media":81,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[8,9,3,2,5,4,10],"class_list":["post-180","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-msix","tag-architecture","tag-code","tag-deployment","tag-msix","tag-register","tag-stage","tag-terminology"],"acf":[],"blog_post_summary":"<p>As previously mentioned to &#8216;install&#8217; a package, as people think of the term, Windows actually performs two separate operations: staging and registration. To oversimplify: Staging puts the package content on disk. At this point the package is present, but inert and unused. Registering wires the package into a user&#8217;s profile. This includes creating tiles on [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/posts\/180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/users\/911"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/comments?post=180"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/posts\/180\/revisions"}],"predecessor-version":[{"id":182,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/posts\/180\/revisions\/182"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/media\/81"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/media?parent=180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/categories?post=180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/insidemsix\/wp-json\/wp\/v2\/tags?post=180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}