Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -345,23 +345,24 @@ public enum LaunchAction
}

/// <summary>
/// The scope of the bundle when the chain contains per-user-or-machine or per-machone-or-user packages.
/// The scope of the bundle when the chain contains dual-purpose (per-user-or-machine or per-machone-or-user) packages.
/// </summary>
public enum BundleScope
{
/// <summary>
/// Let Burn choose the scope. Per-user-or-machine packages will be
/// planned as per-user packages. Per-machine-or-user packages will be
/// planned as per-machine packages.
/// </summary>
Default,

/// <summary>
/// Set per-machine scope for per-user-or-machine packages.
/// Set per-machine scope for dual-purpose packages.
/// </summary>
PerMachine,

/// <summary>
/// Set per-user scope for per-user-or-machine packages.
/// Set per-user scope for dual-purpose packages.
/// </summary>
PerUser,
}
Expand Down
2 changes: 1 addition & 1 deletion src/burn/engine/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ extern "C" HRESULT CorePlan(
pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action;
pEngineState->plan.fPlanPackageCacheRollback = BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pEngineState->registration.detectedRegistrationType;

hr = PlanPackagesAndBundleScope(pEngineState->packages.rgPackages, pEngineState->packages.cPackages, pEngineState->plan.plannedScope, pEngineState->registration.scope, pEngineState->command.commandLineScope, pEngineState->registration.detectedScope, &pEngineState->plan.plannedScope, &pEngineState->registration.fPerMachine);
hr = PlanPackagesAndBundleScope(pEngineState->packages.rgPackages, pEngineState->packages.cPackages, pEngineState->registration.sczPrimaryUpgradeCode, pEngineState->registration.relatedBundles.rgRelatedBundles, pEngineState->registration.relatedBundles.cRelatedBundles, pEngineState->plan.plannedScope, pEngineState->registration.scope, pEngineState->command.commandLineScope, pEngineState->registration.detectedScope, &pEngineState->plan.plannedScope, &pEngineState->registration.fPerMachine);
ExitOnFailure(hr, "Failed to determine packages and bundle scope.");

if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pEngineState->registration.scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pEngineState->registration.scope)
Expand Down
5 changes: 0 additions & 5 deletions src/burn/engine/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,6 @@ HRESULT CoreSerializeEngineState(
HRESULT CoreQueryRegistration(
__in BURN_ENGINE_STATE* pEngineState
);
//HRESULT CoreDeserializeEngineState(
// __in BURN_ENGINE_STATE* pEngineState,
// __in_bcount(cbBuffer) BYTE* pbBuffer,
// __in SIZE_T cbBuffer
// );
HRESULT CoreDetect(
__in BURN_ENGINE_STATE* pEngineState,
__in_opt HWND hwndParent
Expand Down
9 changes: 8 additions & 1 deletion src/burn/engine/engine.mc
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,14 @@ MessageId=227
Severity=Success
SymbolicName=MSG_PLAN_INSTALLED_SCOPE
Language=English
Bundle was already installed with scope: %1!hs!
Bundle was already installed with scope: %1!hs!. Scope cannot change during maintenance.
.
MessageId=228
Severity=Success
SymbolicName=MSG_PLAN_UPGRADE_SCOPE
Language=English
Upgraded bundle %1!ls! was already installed with scope: %2!hs!. Scope cannot change during upgrade.
.
MessageId=201
Expand Down
57 changes: 56 additions & 1 deletion src/burn/engine/plan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ static BOOL ForceCache(
__in BURN_PLAN* pPlan,
__in BURN_PACKAGE* pPackage
);
static HRESULT GetUpgradedBundleScope(
__in DWORD cRelatedBundles,
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
__in_z LPCWSTR wzUpgradeCode,
__inout BOOTSTRAPPER_SCOPE* pScope
);

// function definitions

Expand Down Expand Up @@ -823,6 +829,9 @@ extern "C" HRESULT PlanUpdateBundle(
extern "C" HRESULT PlanPackagesAndBundleScope(
__in BURN_PACKAGE* rgPackages,
__in DWORD cPackages,
__in_z LPCWSTR wzUpgradeCode,
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
__in DWORD cRelatedBundles,
__in BOOTSTRAPPER_SCOPE scope,
__in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
__in BOOTSTRAPPER_SCOPE commandLineScope,
Expand Down Expand Up @@ -855,7 +864,11 @@ extern "C" HRESULT PlanPackagesAndBundleScope(
}
}

if (BOOTSTRAPPER_SCOPE_DEFAULT != detectedScope)
// If we're upgrading, lock the scope to that of the upgraded bundle.
hr = GetUpgradedBundleScope(cRelatedBundles, rgRelatedBundles, wzUpgradeCode, &scope);

// If we're in maintenance mode instead, lock the scope to the original scope.
if (S_FALSE == hr && BOOTSTRAPPER_SCOPE_DEFAULT != detectedScope)
{
scope = detectedScope;

Expand Down Expand Up @@ -888,6 +901,48 @@ extern "C" HRESULT PlanPackagesAndBundleScope(
}


static HRESULT GetUpgradedBundleScope(
__in DWORD cRelatedBundles,
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
__in_z LPCWSTR wzUpgradeCode,
__inout BOOTSTRAPPER_SCOPE* pScope
)
{
HRESULT hr = S_OK;

for (DWORD i = 0; i < cRelatedBundles; ++i)
{
BURN_RELATED_BUNDLE* pRelatedBundle = rgRelatedBundles + i;

if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->detectRelationType)
{
for (DWORD j = 0; j < pRelatedBundle->package.Bundle.cUpgradeCodes; ++j)
{
LPCWSTR wzRelatedUpgradeCode = *(pRelatedBundle->package.Bundle.rgsczUpgradeCodes + j);

// Is the related bundle's upgrade code the same as ours?
// If so, lock our scope to the "original" bundle's scope.
if (CSTR_EQUAL == ::CompareStringOrdinal(wzRelatedUpgradeCode, -1, wzUpgradeCode, -1, FALSE))
if (CSTR_EQUAL == ::CompareStringOrdinal(wzRelatedUpgradeCode, -1, wzUpgradeCode, -1, TRUE))
{
*pScope = pRelatedBundle->detectedScope;

LogId(REPORT_STANDARD, MSG_PLAN_UPGRADE_SCOPE, pRelatedBundle->package.Bundle.sczBundleCode, LoggingBundleScopeToString(*pScope));

ExitFunction();
}
}
}
}

// No upgrade codes or none match, which is fine. But note it via S_FALSE
// so we can distinguish the upgrade case from the maintenance case.
hr = S_FALSE;

LExit:
return hr;
}

static HRESULT PlanPackagesHelper(
__in BURN_PACKAGE* rgPackages,
__in DWORD cPackages,
Expand Down
3 changes: 3 additions & 0 deletions src/burn/engine/plan.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ void PlanDump(
HRESULT PlanPackagesAndBundleScope(
__in BURN_PACKAGE* rgPackages,
__in DWORD cPackages,
__in_z LPCWSTR wzUpgradeCode,
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
__in DWORD cRelatedBundles,
__in BOOTSTRAPPER_SCOPE scope,
__in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
__in BOOTSTRAPPER_SCOPE commandLineScope,
Expand Down
18 changes: 12 additions & 6 deletions src/burn/engine/registration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ const LPCWSTR REGISTRY_BUNDLE_UNINSTALL_STRING = L"UninstallString";
const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine";
const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor";
const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor";
const LPCWSTR REGISTRY_BUNDLE_SCOPE = L"BundleScope";
const LPCWSTR SWIDTAG_FOLDER = L"swidtag";
const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables";
const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";


// internal function declarations

Expand Down Expand Up @@ -146,6 +147,10 @@ extern "C" HRESULT RegistrationParseFromXml(
hr = XmlGetAttributeEx(pixnRegistrationNode, L"Tag", &pRegistration->sczTag);
ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Tag.");

// @PrimaryUpgradeCode
hr = XmlGetAttributeEx(pixnRegistrationNode, L"PrimaryUpgradeCode", &pRegistration->sczPrimaryUpgradeCode);
ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @PrimaryUpgradeCode.");

hr = BundlePackageEngineParseRelatedCodes(pixnBundle, &pRegistration->rgsczDetectCodes, &pRegistration->cDetectCodes, &pRegistration->rgsczUpgradeCodes, &pRegistration->cUpgradeCodes, &pRegistration->rgsczAddonCodes, &pRegistration->cAddonCodes, &pRegistration->rgsczPatchCodes, &pRegistration->cPatchCodes);
ExitOnFailure(hr, "Failed to parse related bundles");

Expand Down Expand Up @@ -327,7 +332,8 @@ extern "C" void RegistrationUninitialize(
{
ReleaseStr(pRegistration->sczCode);
ReleaseStr(pRegistration->sczTag);

ReleaseStr(pRegistration->sczPrimaryUpgradeCode);

for (DWORD i = 0; i < pRegistration->cDetectCodes; ++i)
{
ReleaseStr(pRegistration->rgsczDetectCodes[i]);
Expand Down Expand Up @@ -666,8 +672,8 @@ extern "C" HRESULT RegistrationSessionBegin(
hr = RegWriteStringFormatted(hkRegistration, REGISTRY_BUNDLE_DISPLAY_ICON, L"%s,0", pRegistration->sczCacheExecutablePath);
ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON);

hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_SCOPE, pRegistration->fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_SCOPE);
hr = RegWriteNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, pRegistration->fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);

// update display name
hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
Expand Down Expand Up @@ -1780,8 +1786,8 @@ static HRESULT DetectInstalled(

pRegistration->detectedRegistrationType = (1 == dwInstalled) ? BOOTSTRAPPER_REGISTRATION_TYPE_FULL : BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;

hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_SCOPE, &dwScope);
ExitOnFailure(hr, "Failed to read registration %ls@%ls.", pRegistration->sczRegistrationKey, REGISTRY_BUNDLE_SCOPE);
hr = RegReadNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, &dwScope);
ExitOnFailure(hr, "Failed to read registration %ls@%ls.", pRegistration->sczRegistrationKey, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);

pRegistration->detectedScope = static_cast<BOOTSTRAPPER_SCOPE>(dwScope);
}
Expand Down
5 changes: 3 additions & 2 deletions src/burn/engine/registration.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_VERSION = L"EngineVersion";
const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion";
const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey";
const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag";

const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE = L"BundleScope";

enum BURN_RESUME_MODE
{
Expand Down Expand Up @@ -69,6 +68,7 @@ typedef struct _BURN_RELATED_BUNDLE
BOOTSTRAPPER_REQUEST_STATE defaultRequestedRestore;
BOOTSTRAPPER_REQUEST_STATE requestedRestore;
BOOTSTRAPPER_ACTION_STATE restore;
BOOTSTRAPPER_SCOPE detectedScope;
} BURN_RELATED_BUNDLE;

typedef struct _BURN_RELATED_BUNDLES
Expand Down Expand Up @@ -106,6 +106,7 @@ typedef struct _BURN_REGISTRATION
BOOTSTRAPPER_PACKAGE_SCOPE scope;
LPWSTR sczCode;
LPWSTR sczTag;
LPWSTR sczPrimaryUpgradeCode;

LPWSTR *rgsczDetectCodes;
DWORD cDetectCodes;
Expand Down
12 changes: 12 additions & 0 deletions src/burn/engine/relatedbundle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ static HRESULT LoadRelatedBundleFromKey(
BOOL fExists = FALSE;
BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL;
DWORD dwScope = 0;

// Only support progress from engines that are compatible.
hr = RegReadNumber(hkBundleCode, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion);
Expand Down Expand Up @@ -355,6 +356,11 @@ static HRESULT LoadRelatedBundleFromKey(
LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, wzRelatedBundleCode, sczBundleVersion);
}

hr = RegReadNumber(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, &dwScope);
ExitOnFailure(hr, "Failed to read registration %ls for bundle %ls.", wzRelatedBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);

pRelatedBundle->detectedScope = static_cast<BOOTSTRAPPER_SCOPE>(dwScope);

hr = RegReadString(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath);
ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleCode);

Expand Down Expand Up @@ -390,6 +396,12 @@ static HRESULT LoadRelatedBundleFromKey(

pRelatedBundle->detectRelationType = relationType;

hr = StrAllocString(&pRelatedBundle->package.Bundle.sczBundleCode, wzRelatedBundleCode, 0);
ExitOnFailure(hr, "Failed to bundle code to related bundle.");

hr = RegReadStringArray(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &pRelatedBundle->package.Bundle.rgsczUpgradeCodes, &pRelatedBundle->package.Bundle.cUpgradeCodes);
ExitOnFailure(hr, "Failed to read upgrade codes.");

hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleCode,
#ifdef DEBUG
pRelatedBundle->detectRelationType,
Expand Down
3 changes: 3 additions & 0 deletions src/burn/test/BurnUnitTest/RelatedBundleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ namespace Bootstrapper

hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, wzVersion);
NativeAssert::Succeeded(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION);

hr = RegWriteNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
NativeAssert::Succeeded(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="WixToolset.Sdk">
<PropertyGroup>
<BA>TestBA</BA>
<DefineConstants>$(DefineConstants);Version=1.0.0.0</DefineConstants>
</PropertyGroup>

<Import Project="Bundle.props" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="WixToolset.Sdk">
<PropertyGroup>
<BA>TestBA</BA>
<DefineConstants>$(DefineConstants);Version=2.0.0.0</DefineConstants>
</PropertyGroup>

<Import Project="Bundle.props" />
</Project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="WixToolset.Sdk">
<PropertyGroup>
<BA>WixStdBA</BA>
<DefineConstants>$(DefineConstants);Version=1.0.0.0</DefineConstants>
</PropertyGroup>

<Import Project="Bundle.props" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
<Bundle Id="AllPuomBundle$(BA)" Name="AllPuomBundle$(BA)" Manufacturer="Acme" Version="1.0.0.0">
<Bundle Id="AllPuomBundle$(BA)" Name="AllPuomBundle$(BA)" Manufacturer="Acme" Version="$(Version)">
<?if $(BA) = "WixStdBA"?>
<BootstrapperApplication>
<bal:WixStandardBootstrapperApplication LicenseUrl="https://www.example.com/license" Theme="hyperlinkLicense" />
Expand Down
48 changes: 48 additions & 0 deletions src/test/burn/WixToolsetTest.BurnE2E/ConfigurableScopeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,54 @@ public void CommandLineScopeTestPerMachine()
pkg2.VerifyInstalled(false);
}

[RuntimeFact]
public void BundleUpgradeIsLockedToFirstBundlesScope()
{
var testBAController = this.CreateTestBAController();
testBAController.SetBundleScope(BundleScope.Default);

var bundle = this.CreateBundleInstaller("AllPuomBundleTestBA");
var log = bundle.Install();

bundle.VerifyRegisteredAndInPackageCache(plannedPerMachine: false);

Assert.True(LogVerifier.MessageInLogFile(log, "Plan begin, 3 packages, action: Install, planned scope: Default"));

log = bundle.Repair();
Assert.True(LogVerifier.MessageInLogFile(log, "Bundle was already installed with scope: PerUser. Scope cannot change during maintenance."));

var bundleV2 = this.CreateBundleInstaller("AllPuomBundleTestBAv2");
testBAController.SetBundleScope(BundleScope.PerMachine);
log = bundleV2.Install();
Assert.True(LogVerifier.MessageInLogFileRegex(log, @"Upgraded bundle [{][0-9A-Fa-f\-]{36}[}] was already installed with scope: PerUser\. Scope cannot change during upgrade\."));

bundleV2.Uninstall();
bundleV2.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
bundle.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
}

[RuntimeFact]
public void BundleUpgradeWithSameScopeSucceeds()
{
var bundle = this.CreateBundleInstaller("AllPuomBundleTestBA");
var log = bundle.Install();

bundle.VerifyRegisteredAndInPackageCache(plannedPerMachine: false);

Assert.True(LogVerifier.MessageInLogFile(log, "Plan begin, 3 packages, action: Install, planned scope: Default"));

log = bundle.Repair();
Assert.True(LogVerifier.MessageInLogFile(log, "Bundle was already installed with scope: PerUser. Scope cannot change during maintenance."));

var bundleV2 = this.CreateBundleInstaller("AllPuomBundleTestBAv2");
log = bundleV2.Install();
Assert.True(LogVerifier.MessageInLogFileRegex(log, @"Upgraded bundle [{][0-9A-Fa-f\-]{36}[}] was already installed with scope: PerUser\. Scope cannot change during upgrade\."));

bundleV2.Uninstall();
bundleV2.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
bundle.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
}

[RuntimeFact]
public void PMOU_Bundle_Default_Plan_Installs_PerMachine()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ public void Execute()
writer.WriteAttributeString("Tag", this.BundleSymbol.Tag);
writer.WriteAttributeString("Version", this.BundleSymbol.Version);
writer.WriteAttributeString("ProviderKey", this.BundleSymbol.ProviderKey);
writer.WriteAttributeString("PrimaryUpgradeCode", this.BundleSymbol.UpgradeCode);

writer.WriteStartElement("Arp");
writer.WriteAttributeString("DisplayName", this.BundleSymbol.Name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public void CanBuildSimpleBundle()
var registrationElements = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
WixAssert.CompareLineByLine(new[]
{
$"<Registration Code='{bundleSymbol.BundleCode}' ExecutableName='test.exe' Scope='perMachine' Tag='' Version='1.0.0.0' ProviderKey='{bundleSymbol.BundleCode}'>" +
$"<Registration Code='{bundleSymbol.BundleCode}' ExecutableName='test.exe' Scope='perMachine' Tag='' Version='1.0.0.0' ProviderKey='{bundleSymbol.BundleCode}' PrimaryUpgradeCode='{bundleSymbol.UpgradeCode}'>" +
"<Arp DisplayName='~TestBundle' DisplayVersion='1.0.0.0' InProgressDisplayName='~InProgressTestBundle' Publisher='Example Corporation' />" +
"</Registration>",
}, registrationElements);
Expand Down
Loading