Dotfuscator and ClickOnce

  • Thread starter Thread starter Stewart Berman
  • Start date Start date
Hi Stewart,

Thank you for your prompt reply!
It does not regenerate the manifest files after the BeforePublish target.

You're right.

In the Microsoft.Common.targets file, you can see that the
GenerateManifests target is sequenced after the BeforePublish target in the
DependsOn list of the PublishOnly target. It looks as if the ClickOnce
manifests would be re-generated after the BeforePublish target is built.
But the fact is that the GenerateManifests will be skipped if the ClickOnce
manifests have been created and the number of the input files is not
changed.

After doing some research, I find that only when the Project Designer is
opened and the Publish tab is selected, the AfterCompile target will be
built for multiple times when you publish the application via Publish
Wizard. Please switch to other tabs than the Publish tab within the Project
Designer or close the Project Designer directly and right click the project
in Solution Explorer and choose Publish command to publish the application.
Alternatively, you can publish the application using MSBuild command in
VS05 Command Prompt.

To summary, use AfterCompile target to apply dotfuscate to the executable
assembly and re-sign this assembly if it is strong-named. Then publish the
application using Publish Wizard or msbuild command in the VS05 Command
Prompt. When using Publish Wizard, remember not to select the Publish tab
in the Project Designer when publishing.

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
In the Microsoft.Common.targets file, you can see that the
GenerateManifests target is sequenced after the BeforePublish target in the
DependsOn list of the PublishOnly target. It looks as if the ClickOnce
manifests would be re-generated after the BeforePublish target is built.
But the fact is that the GenerateManifests will be skipped if the ClickOnce
manifests have been created and the number of the input files is not
changed.

What is the correct way to add the GenerateManifests to the AfterPublish target? I tried a couple
of ways and while it appears to run and the manifest files are changed the results doesn't work.
Alternatively, you can publish the application using MSBuild command in
VS05 Command Prompt.

I got the MSBUILD version to sort of work. It builds correctly and creates the
ApplicationName/ApplicationName_X_X_X_X directory but it does not copy the contents to the web
publish site. Is there a way to get it to actually publish?

How do you change the Revision level that will be used my MSBUILD. It is not in the project file --
where is it?

Is there a conditional switch I can test to see if the process is being run under the IDE or outside
it and if so what is it?
 
But the fact is that the GenerateManifests will be skipped if the ClickOnce
manifests have been created and the number of the input files is not
changed.

One of the input files is the Application executable which was changed by Dotfuscatore (which is the
reason its hash doesn't match). There appears to be a bug in the way MSBuild checks for
dependencies.

I can put a pause in the BeforePublish target -- what file do I have to change or delete to get
GenerateManifests to run instead of being skipped?
 
I took a step back and looked at the Visual Studio 2005 development environment. Please note that I
have been away from this environment for a number of years. I find it very confusing compared to
other IDEs -- including earlier Microsoft versions.

1. It is impossible to create the same build process in and outside the IDE. That is, the same
project file (the equivalent of the old make files) is handled completely differently in the IDE
than outside via MSBuild. Some targets are executed multiple times in the IDE while others that
should be executed are not while outside the IDE no one seems to be able to predicate what targets
will be executed when.

2. There isn't any support for building and publishing ClickOnce applications outside of the IDE. It
does not appear to be possible, much less supported, to use MSBuild outside of the IDE to build and
publish a ClickOnce application.

3. The treating of the folder naming conventions on the user's C: drive for ClickOnce applications
and Isolated Storage as a Microsoft trade secret makes it difficult, if not impossible, to properly
design ClickOnce applications' use of Isolated Storage and to verify the correct installation of
ClickOnce applications.

4. It appears that Microsoft does not have definitive documentation as to what actually goes on in
an IDE Build and Publish process.

5. The documentation available on MSDN fails to connect MSBuild to the IDE. All references to VS
project files lead to MSBuild as run from a command line. But the IDE does not simply invoke
MSBuild against a project file. Which leads us back to (1) above.

Again, I admit that I have been away from this for a number of years and may be missing the obvious.
Can you recommend a book or document that would help me walk through my project file and the various
Microsoft target files and understand the process flow within MSBuild and why it is different when
invoked from the IDE than from a command line?
 
Hi Stewart,
What is the correct way to add the GenerateManifests to the AfterPublish
target?

You can use the CallTarget task to call the GenerateManifests target from
within the AfterPublish target so that the GenerateManifests target will be
built after the AfterPublish target is built. For example:
<Target Name="AfterPublish">
<CallTarget Targets="GenerateManifests">
Is there a way to get it to actually publish?

MSBuild command doesn't do this work(VS IDE copies the ClickOnce
application as well as the manifests to the publish location by itself). So
you need to copy the relevant files to the publish location by yourself if
you don't publish the application inside VS IDE.
How do you change the Revision level that will be used my MSBUILD. It is
not in the project file --where is it?

MSBuild uses the ApplicationVersion and ApplicationRevision properties to
determine the publish version. I only find the ApplicationVersion property
in the project file.
Is there a conditional switch I can test to see if the process is being
run under the IDE or outside it and if so what is it?

You can use the BuildingInsideVisualStudio property to determine whether
the building process is being run inside the IDE or outside it. When inside
the IDE, this BuildingInsideVisualStudio property has a 'true' value.
I can put a pause in the BeforePublish target -- what file do I have to
change or delete to get GenerateManifests to run instead of being skipped?

IMO, you need to change the number of the files included in the publishing
process. You can create a dummy file, e.g. a .txt file. Include this dummy
file in the ClickOnce application's application files when publishing the
application and then exclude this file during the pause, so the
GenerateManifests target won't be skipped after the BeforePubish target is
built.

But it still has a problem: the GenerateManifests task creates manifests in
the intermediate output path (obj\debug or obj\release), so you need to
copy the newly generated ClickOnce manifests from the intermediate output
path to the publish folder.

I strongly recommend you to use the AfterCompile target rather than the
BeforePublish target to apply dotfuscator to the executable assembly.

My answers to your 5 questions:
1. I agree with you. IDE doesn't only rely on the MSBuild to build and
publish applications. It does do some extra work besides the MSBuild
command.
2. You can use the MSBuild command to do the most work of building and
publishing outside of the IDE. MSBuild is capable of this. The only thing
left for publishing is to copy the relevant files to the publish location
by yourself.
3. The ClickOnce Isolated Storage on the client machines is transparent to
the developer. You needn't worry about the structure of this storage. You
can also store data into an Isolated Storage from within your ClickOnce
application without any problem.
4. I will consult this question in our internal discussion group.
5. IDE doesn't only rely on the MSBuild.

The MSDN documents on MSBuild should explain the content of the project
file and the common targets file:

"MSBuild Overview"
http://msdn.microsoft.com/en-us/library/ms171452.aspx

"MSBuild Targets"
http://msdn.microsoft.com/en-us/library/ms171462.aspx

"MSBuild Tasks"
http://msdn.microsoft.com/en-us/library/ms171466.aspx

Sincerely,
Linda Liu
Microsoft Online Community Support
 
Thanks for the detailed response.
IMO, you need to change the number of the files included in the publishing
process. You can create a dummy file, e.g. a .txt file. Include this dummy
file in the ClickOnce application's application files when publishing the
application and then exclude this file during the pause, so the
GenerateManifests target won't be skipped after the BeforePubish target is
built.

If I am running Publish Now in the IDE how do I then exclude a file while paused in the
BeforePublish target?
But it still has a problem: the GenerateManifests task creates manifests in
the intermediate output path (obj\debug or obj\release), so you need to
copy the newly generated ClickOnce manifests from the intermediate output
path to the publish folder.

If I do this while running in the IDE won't the publication process copy them to the web site?
3. The ClickOnce Isolated Storage on the client machines is transparent to
the developer. You needn't worry about the structure of this storage. You
can also store data into an Isolated Storage from within your ClickOnce
application without any problem.

It is not transparent. For example, the structure of the Isolated Storage directory tree determines
if the next version of the application can see a file produced by the prior version. This is true
even if the Assembly Version (Application\Assembly Information\Assembly Version) is unchanged.
If the structure contains:
...
StrongName_xxxxxx
StrongName.yyyyyy
The multiple versions of the application will be able to access the same file.
If the structure contains:
...
StrongName_xxxxxx
zzzzzzz
Multiple versions of the application will not be able to access the same file.

So if a user is having problems with their Isolated Storage data disappearing when you push out a
new version of the application the structure of Isolated Storage will help you do problem
determination.


BTW, does this thread need to move to the VB.NET forums?
 
I final figured out what to put into the BeforePublish target to regenerate the manifest files and
copy them to the correct locations so they are published to the web site.

However, I seem to get inconsistent results. That is I can publish the application and then run the
new version and it works fine. If I just publish it again it the new version doesn't work -- it
just ends after displaying the splash screen.

I think it is time to diagram the process and make sure all of it is determinant.
 
Hi Stewart,

Thank you for your reply!
So if a user is having problems with their Isolated Storage data
disappearing when you push out a new version of the application the
structure of Isolated Storage will help you do problem determination.

At this point, I agree with you. But it is not recommended to operate files
installed into the ClickOnce Isolated Storage manually.

BTW, the data files of the previous version of application installed to the
data directory will be copied to the data directory of the newer version of
the same application automatically, no matter whether the data files are
generated by the ClickOnce application at run time or not. Thus the new
version of application can access the data files.

For more information on accessing local and remote data in ClickOnce
applications, please read the following MSDN document:

"Accessing Local and Remote Data in ClickOnce Applications"
http://msdn.microsoft.com/en-us/library/d8saf4wy(VS.80).aspx
BTW, does this thread need to move to the VB.NET forums?

No. But the microsoft.public.dotnet.languages.vb newsgroup has been
migrated to VB.NET forum. Refer to the following document for more
information:
http://msdn.microsoft.com/en-us/subscriptions/aa974230.aspx
I think it is time to diagram the process and make sure all of it is
determinant.

I still recommend you to use the AfterCompile target rather than the
BeforePublish target.

My answer to your previous question:
4 . It appears that Microsoft does not have definitive documentation as to
what actually goes on in an IDE Build and Publish process

Yes. Only documents related to MSBuild are provided. Our product team has
confirmed that VS IDE relies mostly on MSBuild to build and publish an
application.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
BTW, the data files of the previous version of application installed to the
data directory will be copied to the data directory of the newer version of
the same application automatically, no matter whether the data files are
generated by the ClickOnce application at run time or not. Thus the new
version of application can access the data files.

Unfortunately, Data files go under Local Settings not Application Data and thus will not be flushed
back to a roaming profile. They should therefore only be used for either static data or machine
specific data.
No. But the microsoft.public.dotnet.languages.vb newsgroup has been
migrated to VB.NET forum. Refer to the following document for more
information:
http://msdn.microsoft.com/en-us/subscriptions/aa974230.aspx
I still recommend you to use the AfterCompile target rather than the
BeforePublish target.

AfterCompile is called too many times.

I have it working in BeforePublish:
<Target Name="BeforePublish" Condition="'$(Configuration)'=='Release'">
<!-- -->
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot; &quot;BeforePublish01Begins&quot;" />
<SAB_MsgBox Prompt="BeforePublish Begins" />
<!-- -->
<Exec Command="&quot;C:\Program Files\PreEmptive Solutions\Dotfuscator Enhanced Community
Edition 4.2\dotfuscator.exe&quot; /q &quot;$(ProjectDir)Dotfuscator_Project_Exclude.xml&quot; " />
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot;
&quot;BeforePublish02AfterDotfuscator&quot;" />
<SAB_MsgBox Prompt="BeforePublish After Dotfuscator" />
<!-- -->
<Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sn.exe&quot; -Rca
&quot;$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)&quot;
VS_KEY_*****************************" />
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot; &quot;BeforePublish03Aftersn&quot;" />
<SAB_MsgBox Prompt="BeforePublish After sn" />
<!-- -->
<Touch Files="$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)" />
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot; &quot;BeforePublish04AfterTouch&quot;"
/>
<SAB_MsgBox Prompt="BeforePublish After Touch" />
<!-- -->
<Copy SourceFiles="$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)"
DestinationFolder="$(ProjectDir)$(OutputPath)" />
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot; &quot;BeforePublish05AfterCopy&quot;" />
<SAB_MsgBox Prompt="BeforePublish After Copy" />
<!-- -->
<CallTarget Targets="GenerateManifests" />
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot;
&quot;BeforePublish06AfterGenerateManifests&quot;" />
<SAB_MsgBox Prompt="BeforePublish After GenerateManifests" />
<!-- -->
<CallTarget Targets="_CopyManifestFiles" />
<Exec Command="&quot;H:\Visual Studio
2005\Projects\ApplicationName\ApplicationName\ListAll&quot;
&quot;BeforePublish07After_CopyManifestFiles&quot;" />
<SAB_MsgBox Prompt="BeforePublish After _CopyManifestFiles" />
</Target>

The SAB_MsgBox task lets me pause the process until the time goes to the next minute which makes it
easier to see changes in the Date Modified in the output of the ListAll.cmd file. Both the
SAB_MsgBox task and the ListAll command would be commented out in normal usage.

ListAll contains:

IF %1. == . GOTO MISSING
H:
CD "\Visual Studio 2005\Projects\ApplicationName\ApplicationName"
DIR OBJ /ON /S > OBJBIN%1.LST
DIR BIN /ON /S >> OBJBIN%1.LST
GOTO EXIT
:MISSING
ECHO Operand Missing
PAUSe
:EXIT

I had to set signing to Delayed so I could run Dotfuscator and then sign the assemply using SN.EXE.
I have that working -- including regenerating the manifest files. The last problem was if I wanted
to skip the Dotfuscator (to be able to see what is happening in the installed version) the manifest
generation was skipped even though SN.EXE signed the file. From the output of the ListAll.cmd file
it appears that SN.EXE signs the file without changing its Date Modified timestamp. I had to add a
Touch task (included above).

I can now publish from within the IDE and have a Dotfuscatored, Strong Named application pushed to
the web site.
Yes. Only documents related to MSBuild are provided. Our product team has
confirmed that VS IDE relies mostly on MSBuild to build and publish an
application.

The key word is MOSTLY. The VS IDE appears to invoke MSBuild at least twice during the process
before actually publishing the files to the web site. It may be more under certain conditions as I
had BeforeCompile invoked three to five time when running in the IDE and only once when trying to
use MSBuild via the command line. It is also runs differently depending on how it is invoked from
the IDE. Right click on the project and selecting publish produces different output than using the
Publish Now button.

Is there anyway to get the parameters passed to MSBuild from the IDE for each call? The interface
between the IDE and MSBuild should be clearly documented. For example, if you select Sign Assembly
without checking Delay Signing the information for signing the assembly is passed to VBC. It would
be helpful if there was a simply table that mapped each item in the Project property sheets to the
corresponding element in the project file or the corresponding parameter that the IDE passes to
MSBuild. This would greatly facilitate running the project file via MSBuild from the command line.
 
Hi Stewart,

Thank you for sharing how you successfully solve the problem!
It would be helpful if there was a simply table that mapped each item in
the Project property sheets to the
corresponding element in the project file or the corresponding parameter
that the IDE passes to MSBuild.

I understand your concern. I suggest you to make a suggestion for this in
the Microsoft Connection web site:
http://connect.microsoft.com/VisualStudio/Feedback

Thank you for your contribution to our product!

If you don't have any question, I would like to close this issue.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
Thank you for sharing how you successfully solve the problem!

I would still like to know why signing an application's executable doesn't change the Date Modified
for the file.
I understand your concern. I suggest you to make a suggestion for this in
the Microsoft Connection web site:
http://connect.microsoft.com/VisualStudio/Feedback

Visual Studio 2005 is not supported there. I have hit a few bugs but am unable to report them via
Feedback. The worst one is that the IDE goes into a hard loop if I make changes to the main form
via Designer. For example, if I simply add a menu item and then press save the IDE goes into a hard
loop and I have to kill it through Task Manager. I have to make changes in Main by editing
Main.Designer.vb. (Takes me back to my C days before IDEs.)

The only way I can report bugs in Visual Studio 2005 is by providing a credit card number so
Microsoft can charge me for the privilege.
 
If you don't have any question, I would like to close this issue.

I think I have a fairly good handle on developing and publishing a ClickOnce application.

Test project is finished. Doesn't do much but it let me explore the ClickOnce process and PC based
VB.NET application process.

Description here: http://www.saberman.com/SABBackgroundSlideShow/

Thanks for your help and please close this issue.
 
Thanks Stewart for your response!

Ok, I will close this issue now. If you have any other questions in the
future, please don't hesitate to contact us. It's always our pleasure to be
of assistance.

Have a nice day.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
Back
Top