Updating deployment manifest for a ClickOnce application programmatically results in missing element, required in 4.0

后端 未结 2 1215
南旧
南旧 2021-02-06 09:52

I\'m working on automating the installer for a .NET 4.0 ClickOnce WPF application, which needs a few items to be set in the app.config file. I\'ve gone through the thor

相关标签:
2条回答
  • 2021-02-06 10:43

    I also needed to add CompatibleFrameworks. I also tried do add the CompatibleFrameworks like this (which does not work)

    dm.CompatibleFrameworks.Add(...);
    

    My solution was to set:

    dm.TargetFrameworkMoniker = ".NETFramework,Version=v4.0";                 
    

    After this the Manifest generation was correct.

    Be careful If you set the TargetFrameworkMoniker before WriteManifest you have the <compatibleFrameworks> twice and your application file is corrupt. Here is my solution for this:

    DeployManifest dm = ManifestReader.ReadManifest("DeployManifest", applicationFileName, false) as DeployManifest;
    dm.ResolveFiles();
    //doing stuff..
    dm.UpdateFileInfo();
    ManifestWriter.WriteManifest(dm, applicationFileName);
    dm.TargetFrameworkMoniker = ".NETFramework,Version=v4.0";
    ManifestWriter.WriteManifest(dm, applicationFileName);
    
    0 讨论(0)
  • 2021-02-06 10:44

    Figured it out myself. The culprit is ManifestReader.ReadManifest( "DeployManifest", sPathMft, true ).

    MSDN says, [preserveStream argument] "specifies whether to preserve the input stream in the InputStream property of the resulting manifest object. Used by ManifestWriter to reconstitute input which is not represented in the object representation."

    Wording aside, setting true is not enough by itself: dm.CompatibleFrameworks.Count will still be 0, but now the addition of CompatibleFramework items will have an effect!

    For someone else in the same boat, I do that before dm.ResolveFiles( ):

    if(  dm.CompatibleFrameworks.Count <= 0  )
    {
        CompatibleFramework cf= new CompatibleFramework( );
        cf.Profile= "Client";       cf.Version= "4.0";      cf.SupportedRuntime=    "4.0.30319";
        dm.CompatibleFrameworks.Add( cf );              //  cf= new CompatibleFramework( );
        cf.Profile= "Full";     //  cf.Version= "4.0";      cf.SupportedRuntime=    "4.0.30319";
        dm.CompatibleFrameworks.Add( cf );              /// no need for separate object
    }
    

    @davidair, thanks for your suggestion!  Agreed, though I prefer to work with API objects (vs. XML).
    Another alternative is to call mage (directly or from a .cmd file), as it seems that we are allowed to redistribute it.


    I also added the following portion, which doesn't have an impact on the question itself, but may be quite important for anyone following the same path (/client is the deployment root, and can be customized):

    dm.DeploymentUrl=   string.Format( "http://{0}/{1}/client/{1}.application",
                            Dns.GetHostName( ), Context.Parameters[ scTokVirtDir ] );
    dm.UpdateMode=      UpdateMode.Background;
    dm.UpdateUnit=      UpdateUnit.Weeks;
    dm.UpdateInterval=  1;
    dm.UpdateEnabled=   true;
    

    2019-Oct-08
    Just stumbled on an issue with app.manifest:
    compatibility section with supportedOS elements was stripped out during deployment.

    Same root cause; the line reading it should set preserveStream to true:

    ApplicationManifest am = ManifestReader.ReadManifest( "ApplicationManifest", sPathMft, true ) as ApplicationManifest;
    
    0 讨论(0)
提交回复
热议问题